From 23c0b35c4a10dc5d2d9d3e452559a93dcf913a0d Mon Sep 17 00:00:00 2001 From: chenlinghy Date: Thu, 29 Jul 2021 10:25:35 +0800 Subject: [PATCH] =?UTF-8?q?OCT=20REM:=201.=20=E6=96=B0=E5=A2=9EUPF?= =?UTF-8?q?=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dispose/ability/impl/UpfAbilityImpl.java | 519 ++++++++++++++++++ .../com/dispose/common/DisposeDeviceType.java | 4 + .../java/com/dispose/common/ErrorCode.java | 5 +- .../impl/DeviceTaskManagerServiceImpl.java | 8 + .../impl/DisposeAbilityRouterServiceImpl.java | 4 + 5 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/dispose/ability/impl/UpfAbilityImpl.java diff --git a/src/main/java/com/dispose/ability/impl/UpfAbilityImpl.java b/src/main/java/com/dispose/ability/impl/UpfAbilityImpl.java new file mode 100644 index 00000000..b3410082 --- /dev/null +++ b/src/main/java/com/dispose/ability/impl/UpfAbilityImpl.java @@ -0,0 +1,519 @@ +package com.dispose.ability.impl; + +import com.dispose.common.DisposeCapacityType; +import com.dispose.common.DisposeConfigValue; +import com.dispose.common.DisposeObjectType; +import com.dispose.common.ErrorCode; +import com.dispose.common.Helper; +import com.dispose.common.IpAddrType; +import com.dispose.common.NetflowDirection; +import com.dispose.pojo.dto.protocol.base.ProtocolRespDTO; +import com.dispose.pojo.entity.ServiceInfo; +import com.dispose.pojo.po.MulReturnType; +import com.dispose.pojo.vo.DeviceFirewareInfo; +import com.pengxin.dispose.common.PengXinDisposeAbilityRsp; +import com.pengxin.dispose.common.PengXinStartTaskItem; +import com.pengxin.dispose.common.PengXinStartTaskRsp; +import com.pengxin.dispose.common.PengXinStopTaskRsp; +import com.pengxin.dispose.common.PengXinTaskStatusRsp; +import com.pengxin.dispose.protocol.PengXinInterface; +import inet.ipaddr.IPAddress; +import inet.ipaddr.IPAddressString; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.RandomStringUtils; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +/** + * The type upf ability. + * @author Nicole + */ +@Slf4j +public class UpfAbilityImpl extends PengXinAbilityImpl { + /** + * The Protect ip v 4. + */ + private final List protectIpV4 = new ArrayList<>(); + /** + * The Protect ip v 6. + */ + private final List protectIpV6 = new ArrayList<>(); + /** + * The Restful interface. + */ + private final PengXinInterface restfulInterface = new PengXinInterface(); + /** + * The upf dispose type. + */ + private final Integer[] upfDisposeType = new Integer[]{0, 4, 1, 3}; + /** + * The Task req id. + */ + private Long taskReqId = System.currentTimeMillis(); + /** + * The Timer cnt. + */ + private long timerCnt = 0; + /** + * The Device link status. + */ + private boolean deviceLinkStatus = false; + + /** + * The Url root path. + */ + @Getter + @Setter + private String urlRootPath; + /** + * The Username. + */ + @Getter + @Setter + private String username; + /** + * The Password. + */ + @Getter + @Setter + private String password; + /** + * The Token. + */ + private String token; + + /** + * Gets upf task type. + * + * @param capType the cap type + * @return the upf task type + */ + private int getUpfTaskType(DisposeCapacityType capType) { + return upfDisposeType[capType.getValue()]; + } + + /** + * Gets upf object type. + * + * @param objType the obj type + * @return the upf object type + */ + private int getUpfObjectType(DisposeObjectType objType) { + switch (objType) { + case URL: + return 2; + case DOMAIN: + return 1; + default: + return 0; + } + } + + /** + * Init device env. + * + * @param urlPath the url path + * @param username the username + * @param password the password + */ + @Override + public void initDeviceEnv(String urlPath, String username, String password) { + this.urlRootPath = urlPath; + this.username = username; + this.password = password; + restfulInterface.setParams(1, 0); + //获取token值 + upgradeToken(); + } + + /** + * Run dispose mul return type. + * + * @param disposeObject the dispose object + * @param objectType the object type + * @param capType the cap type + * @param nfDirection the nf direction + * @param attackType the attack type + * @param duration the duration + * @return the mul return type + */ + @Override + public MulReturnType runDispose(String disposeObject, DisposeObjectType objectType, + DisposeCapacityType capType, + @Nullable NetflowDirection nfDirection, + @Nullable Integer attackType, + @Nullable Long duration) { + List reqItems = new ArrayList<>(); + String url = urlRootPath + "dispose_device/task/start"; + //1.调用upf设备登录接口,生成token值;2.upf不提供登录接口,随机生成token值,保证有token值 + if (token == null || token.length() == 0) { + return new MulReturnType<>(ErrorCode.ERR_LOGOUT, ""); + } + + try { + log.info("++++Begging UPF Start Cleanup Task: {}", disposeObject); + if (capType != DisposeCapacityType.BLACKHOOL) { + log.error("----Error UPF don't support dispose capacity type: {}", capType); + return new MulReturnType<>(ErrorCode.ERR_UNSUPPORT, null); + } + + // 适配处置时间参数, -1为不限制处置时间 + if (duration == null || duration < 0) { + duration = -1L; + } + + reqItems.add(PengXinStartTaskItem.builder() + .type(getUpfTaskType(capType)) + .disposeObject(disposeObject) + .objectType(getUpfObjectType(objectType)) + .disposeTime(duration) + .taskReqId(String.valueOf(taskReqId++)) + .build()); + + ProtocolRespDTO rspInfo = restfulInterface.startDisposeTask(url, token, reqItems); + + // upf设备不判断header认证消息中的token值 + if (rspInfo == null || rspInfo.getCode() != ErrorCode.ERR_OK.getHttpCode()) { + log.error("----Error UPF start clean {} server return error", disposeObject); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } + + if (rspInfo.getMsgContent().getItems().size() == 0) { + log.error("----Error UPF start clean {} server return nothing", disposeObject); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } else { + int errCode = rspInfo.getMsgContent().getItems().get(0).getStatus(); + if (errCode != ErrorCode.ERR_OK.getCode()) { + log.error("----Error UPF start clean {} server return error: {}", disposeObject, errCode); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } + + log.debug("----Finish UPF Start Cleanup Task: {}", disposeObject); + return new MulReturnType<>(ErrorCode.ERR_OK, rspInfo.getMsgContent().getItems().get(0).getTaskId()); + } + } catch (Exception ex) { + log.error("----Exception UPF Start Cleanup Task: {}, {}, {}", disposeObject, nfDirection, duration); + return new MulReturnType<>(ErrorCode.ERR_SYSTEMEXCEPTION, null); + } + } + + /** + * Stop dispose mul return type. + * + * @param disposeObject the dispose object + * @param capType the cap type + * @param nfDirection the nf direction + * @param attackType the attack type + * @param taskId the task id + * @return the mul return type + */ + @Override + public MulReturnType stopDispose(String disposeObject, DisposeCapacityType capType, + @Nullable NetflowDirection nfDirection, + @Nullable Integer attackType, + @Nullable String taskId) { + String url = urlRootPath + "dispose_device/task/stop"; + //1.调用upf设备登录接口,生成token值;2.upf不提供登录接口,随机生成token值,保证有token值 + if (token == null || token.length() == 0) { + return new MulReturnType<>(ErrorCode.ERR_LOGOUT, null); + } + + try { + log.info("++++Begging UPF Stop Cleanup Task: {}", taskId); + if (capType != DisposeCapacityType.BLACKHOOL) { + log.error("----Error UPF don't support dispose capacity type: {}", capType); + return new MulReturnType<>(ErrorCode.ERR_UNSUPPORT, null); + } + + if (taskId == null) { + return new MulReturnType<>(ErrorCode.ERR_PARAMS, null); + } + + ProtocolRespDTO rspInfo = restfulInterface.stopDisposeTask(url, token, + new String[]{taskId}); + + if (rspInfo == null || rspInfo.getCode() != ErrorCode.ERR_OK.getHttpCode()) { + log.error("----Error UPF stop task{} server return error", taskId); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } + + if (rspInfo.getMsgContent().getItems().size() == 0) { + log.error("----Error UPF stop clean {} server return nothing", disposeObject); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } else { + int errCode = rspInfo.getMsgContent().getItems().get(0).getStatus(); + if (errCode != ErrorCode.ERR_OK.getCode()) { + log.error("----Error UPF stop clean {} server return error: {}", disposeObject, errCode); + return new MulReturnType<>(ErrorCode.ERR_UPF_ERROR, null); + } + + log.debug("----Finish UPF Stop Cleanup Task: {}", taskId); + return new MulReturnType<>(ErrorCode.ERR_OK, null); + } + } catch (Exception ex) { + log.error("----Exception UPF Stop Cleanup Task: {}, {}, {}", disposeObject, nfDirection, taskId); + return new MulReturnType<>(ErrorCode.ERR_SYSTEMEXCEPTION, null); + } + } + + /** + * Gets ability device fireware. + * + * @return the ability device fireware + */ + @Override + public MulReturnType getAbilityDeviceFireware() { + return new MulReturnType<>(ErrorCode.ERR_OK, + DeviceFirewareInfo.builder() + .vendor("UPF") + .model("Unknown") + .firmware("Unknown") + .os("Linux Server") + .kernel("Linux") + .arch("x86_64") + .version("Unknown") + .memory(-1) + .freeMemory(-1) + .cpuUsed(-1) + .build()); + } + + /** + * To device attack type long. + * + * @param ddosAttackTypeMask the ddos attack type mask + * @return the long + */ + @Override + public Long toDeviceAttackType(Long ddosAttackTypeMask) { + return ddosAttackTypeMask; + } + + /** + * Gets device link status. + * + * @return the device link status + */ + @Override + public boolean getDeviceLinkStatus() { + return deviceLinkStatus; + } + + /** + * Dev get link status. + */ + private void devGetLinkStatus() { + try { + String url = urlRootPath + "dispose_device/information/linkstatus"; + + if (token == null || token.length() == 0) { + deviceLinkStatus = false; + return; + } + + ErrorCode err = restfulInterface.getLinkStatus(url, token); + + if (err == ErrorCode.ERR_LOGOUT) { + // 重新登录获取 token + upgradeToken(); + err = restfulInterface.getLinkStatus(url, token); + } + + if (err == ErrorCode.ERR_OK) { + deviceLinkStatus = true; + } + + return; + } catch (Exception ex) { + log.error(ex.getMessage()); + } + + deviceLinkStatus = false; + } + + /** + * Gets dispose device protect object. + */ + @Override + public void getDisposeDeviceProtectObject() { + if (token == null || token.length() == 0) { + return; + } + + try { + String url = urlRootPath + "dispose_device/information/capacity"; + ProtocolRespDTO rspInfo = restfulInterface.getDeviceDisposeAbility(url, token); + + if (rspInfo != null && rspInfo.getCode() == ErrorCode.ERR_OK.getHttpCode() + && rspInfo.getMsgContent().getStatus() == ErrorCode.ERR_OK.getCode()) { + + rspInfo.getMsgContent().getCapacity().forEach(v -> { + if (v.getObjectType().equals(DisposeObjectType.DOMAIN.getValue())) { + log.error("Unsupported: {}", v.getObjectType()); + } else if (v.getObjectType().equals(DisposeObjectType.URL.getValue())) { + log.error("Unsupported: {}", v.getObjectType()); + } else { + synchronized (this) { + + protectIpV4.clear(); + protectIpV6.clear(); + + if (v.getIpType() == null || v.getIpType().equals(IpAddrType.IPV4_IPV6.getValue())) { + if (v.getDisposeIp() == null) { + protectIpV4.add(""); + protectIpV6.add(""); + } + } else if (v.getIpType().equals(IpAddrType.IPV4.getValue())) { + protectIpV4.add(""); + } else if (v.getIpType().equals(IpAddrType.IPV6.getValue())) { + protectIpV6.add(""); + } + } + } + }); + + } + } catch (Exception ignored) { + } + } + + /** + * Is carry protect ip boolean. + * + * @param ipAddress the ip address + * @return the boolean + */ + @Override + public boolean isCarryProtectIp(String ipAddress) { + boolean ret = false; + IPAddress address = new IPAddressString(ipAddress).getAddress(); + synchronized (this) { + if (address.isIPv4()) { + ret = protectIpV4.stream().anyMatch(v -> Helper.ipInRange(v, ipAddress)); + } + + if (address.isIPv6()) { + ret = protectIpV6.stream().anyMatch(v -> Helper.ipInRange(v, ipAddress)); + } + } + + if (!ret) { + // 更新设备防护IP + getDisposeDeviceProtectObject(); + + synchronized (this) { + if (address.isIPv4()) { + ret = protectIpV4.stream().anyMatch(v -> Helper.ipInRange(v, ipAddress)); + } + + if (address.isIPv6()) { + ret = protectIpV6.stream().anyMatch(v -> Helper.ipInRange(v, ipAddress)); + } + } + } + + return ret; + } + + /** + * Task status mul return type. + * + * @param taskId the task id + * @return the mul return type + */ + @Override + public MulReturnType taskStatus(String taskId) { + if (token == null || token.length() == 0) { + return new MulReturnType<>(ErrorCode.ERR_LOGOUT, -1L); + } + + try { + String url = urlRootPath + "dispose_device/task/get"; + ProtocolRespDTO rspInfo = restfulInterface.getDeviceTaskStatus(url, token, + new String[]{taskId}); + + if (rspInfo != null && rspInfo.getCode() == ErrorCode.ERR_OK.getHttpCode()) { + int errCode = rspInfo.getMsgContent().getItems().get(0).getStatus(); + if (rspInfo.getMsgContent().getItems().size() == 0 || errCode != ErrorCode.ERR_OK.getCode()) { + return new MulReturnType<>(ErrorCode.ERR_NOSUCHTASK, -1L); + } + + return new MulReturnType<>(ErrorCode.ERR_OK, + rspInfo.getMsgContent().getItems().get(0).getTaskStatus()); + } else { + return new MulReturnType<>(ErrorCode.ERR_CALLDEVICE, -1L); + } + } catch (Exception ignored) { + return new MulReturnType<>(ErrorCode.ERR_SYSTEMEXCEPTION, -1L); + } + } + + /** + * Upgrade token. + */ + private void upgradeToken() { + try { + //目前1.UPF不提供用户登录接口,使用随机生成的token值;2UPF登录接口不校验用户名和密码,返回值为REE_OK和token值 + //方案1: + this.token = RandomStringUtils.random(10); +// //方案2 +// String url = urlRootPath + "dispose_device/auth/login"; +// ProtocolRespDTO logInfo = restfulInterface.login(url, username, password); +// +// if (logInfo != null && logInfo.getMsgContent().getStatus() == ErrorCode.ERR_OK.getCode()) { +// this.token = logInfo.getMsgContent().getToken(); +// } + } catch (Exception ignored) { + } + } + + /** + * Period task runtime. + */ + @Override + public void periodTaskRuntime() { + log.debug("++++UPF Period Task Running"); + // 更新防护对象 + getDisposeDeviceProtectObject(); + // 更新心跳状态 + if (timerCnt++ % DisposeConfigValue.HEART_PERIOD_OF_SECOND == 0) { + devGetLinkStatus(); + } + + log.debug("----UPF Period Task Running"); + } + + /** + * Device ready boolean. + * + * @return the boolean + */ + @Override + public boolean deviceReady() { + return true; + } + + /** + * Upgrade service group. + * + * @param svrList the svr list + */ + @Override + public void upgradeServiceGroup(List svrList) { + } + + /** + * Is carry attack type boolean. + * + * @param attackType the attack type + * @return the boolean + */ + @Override + public boolean isCarryAttackType(Long attackType) { + return true; + } +} diff --git a/src/main/java/com/dispose/common/DisposeDeviceType.java b/src/main/java/com/dispose/common/DisposeDeviceType.java index a2b79ad8..e5dc8bf3 100644 --- a/src/main/java/com/dispose/common/DisposeDeviceType.java +++ b/src/main/java/com/dispose/common/DisposeDeviceType.java @@ -30,6 +30,10 @@ public enum DisposeDeviceType implements BaseEnum { * The Huawei FireWall platform. */ HUAWEI_FIREWALL_PLATFORM(5, "华为防火墙"), + /** + * The upf platform. + */ + UPF_PLATFORM(6, "UPF设备"), /** * The Virtual dispose. */ diff --git a/src/main/java/com/dispose/common/ErrorCode.java b/src/main/java/com/dispose/common/ErrorCode.java index 0cba359e..467c6dfb 100644 --- a/src/main/java/com/dispose/common/ErrorCode.java +++ b/src/main/java/com/dispose/common/ErrorCode.java @@ -240,7 +240,10 @@ public enum ErrorCode { * The Err pengxin error. */ ERR_PENGXIN_ERROR(117, "鹏信设备返回错误"), - + /** + * The Err upf error. + */ + ERR_UPF_ERROR(118, "UPF设备返回错误"), /** * The Err nosuchumcprotectobject. */ diff --git a/src/main/java/com/dispose/service/impl/DeviceTaskManagerServiceImpl.java b/src/main/java/com/dispose/service/impl/DeviceTaskManagerServiceImpl.java index 9d3338a3..2a836203 100644 --- a/src/main/java/com/dispose/service/impl/DeviceTaskManagerServiceImpl.java +++ b/src/main/java/com/dispose/service/impl/DeviceTaskManagerServiceImpl.java @@ -588,6 +588,10 @@ public class DeviceTaskManagerServiceImpl implements DeviceTaskManagerService { restfulDeviceTaskRun(ai, v, task, DisposeDeviceType.HUAWEI_FIREWALL_PLATFORM); break; + case UPF_PLATFORM: + restfulDeviceTaskRun(ai, v, task, DisposeDeviceType.UPF_PLATFORM); + break; + default: log.error("Unknown dispose device type: {}", ai.getDev()); break; @@ -669,6 +673,10 @@ public class DeviceTaskManagerServiceImpl implements DeviceTaskManagerService { restfulDeviceTaskStop(ai, v, task, DisposeDeviceType.HUAWEI_FIREWALL_PLATFORM); break; + case UPF_PLATFORM: + restfulDeviceTaskStop(ai, v, task, DisposeDeviceType.UPF_PLATFORM); + break; + default: log.error("Unknown dispose device type: {}", ai.getDev()); break; diff --git a/src/main/java/com/dispose/service/impl/DisposeAbilityRouterServiceImpl.java b/src/main/java/com/dispose/service/impl/DisposeAbilityRouterServiceImpl.java index de72ad6c..37d4a8c3 100644 --- a/src/main/java/com/dispose/service/impl/DisposeAbilityRouterServiceImpl.java +++ b/src/main/java/com/dispose/service/impl/DisposeAbilityRouterServiceImpl.java @@ -7,6 +7,7 @@ import com.dispose.ability.impl.HaoHanAbilityImpl; import com.dispose.ability.impl.HuaWeiAbilityImpl; import com.dispose.ability.impl.HuaWeiFireWallAbilityImpl; import com.dispose.ability.impl.PengXinAbilityImpl; +import com.dispose.ability.impl.UpfAbilityImpl; import com.dispose.ability.impl.VirtualAbilityImpl; import com.dispose.common.DisposeCapacityType; import com.dispose.common.ErrorCode; @@ -172,6 +173,9 @@ public class DisposeAbilityRouterServiceImpl implements DisposeAbilityRouterServ case HUAWEI_FIREWALL_PLATFORM: db = new HuaWeiFireWallAbilityImpl(); break; + case UPF_PLATFORM: + db = new UpfAbilityImpl(); + break; default: log.error("Unknown dispose device type: {}", dev.getDeviceType()); return ErrorCode.ERR_PARAMS;