2023-05-26 15:44:37 +08:00
|
|
|
package com.zdjizhi.etl;
|
|
|
|
|
|
2023-11-13 16:45:04 +08:00
|
|
|
import com.geedgenetworks.utils.StringUtil;
|
2023-05-26 15:44:37 +08:00
|
|
|
import com.zdjizhi.common.DosDetectionThreshold;
|
|
|
|
|
import com.zdjizhi.common.DosEventLog;
|
|
|
|
|
import com.zdjizhi.common.DosSketchLog;
|
2023-11-13 16:45:04 +08:00
|
|
|
|
|
|
|
|
import com.zdjizhi.utils.IpLookupUtils;
|
2023-05-26 15:44:37 +08:00
|
|
|
import com.zdjizhi.utils.SnowflakeId;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.text.NumberFormat;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
|
|
|
|
|
public class DosDetectionTest {
|
|
|
|
|
|
|
|
|
|
private final static NumberFormat PERCENT_INSTANCE = NumberFormat.getPercentInstance();
|
|
|
|
|
private final static int BASELINE_SIZE = 144;
|
|
|
|
|
private final static int STATIC_CONDITION_TYPE = 1;
|
|
|
|
|
private final static int BASELINE_CONDITION_TYPE = 2;
|
|
|
|
|
private final static int SENSITIVITY_CONDITION_TYPE = 3;
|
|
|
|
|
|
|
|
|
|
private final static String SESSIONS_TAG = "sessions";
|
|
|
|
|
private final static String PACKETS_TAG = "packets";
|
|
|
|
|
private final static String BITS_TAG = "bits";
|
|
|
|
|
@Test
|
|
|
|
|
public void dosDetectionTest(){
|
|
|
|
|
DosDetectionThreshold dosDetectionThreshold = new DosDetectionThreshold();
|
|
|
|
|
ArrayList<String> serverIpList = new ArrayList<>();
|
|
|
|
|
serverIpList.add("192.168.50.11");
|
|
|
|
|
serverIpList.add("192.168.50.1/24");
|
|
|
|
|
serverIpList.add("FC::12:0:0/54");
|
|
|
|
|
serverIpList.add("FC::12:0:0");
|
2023-11-13 16:45:04 +08:00
|
|
|
dosDetectionThreshold.setProfile_id(4437);
|
|
|
|
|
dosDetectionThreshold.setAttack_type("DNS Flood");
|
|
|
|
|
dosDetectionThreshold.setServer_ip_list(serverIpList);
|
|
|
|
|
dosDetectionThreshold.setSessions_per_sec(1);
|
|
|
|
|
dosDetectionThreshold.setPackets_per_sec(1);
|
|
|
|
|
dosDetectionThreshold.setBits_per_sec(100000);
|
|
|
|
|
dosDetectionThreshold.setIs_valid(1);
|
|
|
|
|
dosDetectionThreshold.setSuperior_ids(new Integer[]{5,4,12,27});
|
2023-05-26 15:44:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
DosSketchLog dosSketchLog = new DosSketchLog ();
|
|
|
|
|
|
|
|
|
|
dosSketchLog.setSketch_sessions(68);
|
|
|
|
|
dosSketchLog.setSketch_packets(68);
|
|
|
|
|
dosSketchLog.setSketch_bytes(285820);//185.82
|
|
|
|
|
dosSketchLog.setVsys_id(1);
|
|
|
|
|
dosSketchLog.setAttack_type("ICMP Flood");
|
|
|
|
|
dosSketchLog.setSource_ip("45.170.244.25");
|
|
|
|
|
dosSketchLog.setDestination_ip("24.152.57.56");
|
|
|
|
|
//静态阈值获取
|
2023-11-13 16:45:04 +08:00
|
|
|
long sessionBase = dosDetectionThreshold.getSessions_per_sec();
|
|
|
|
|
long pktBase=dosDetectionThreshold.getPackets_per_sec();
|
|
|
|
|
long bitBase=dosDetectionThreshold.getBits_per_sec();
|
2023-05-26 15:44:37 +08:00
|
|
|
//基于速率进行计算
|
|
|
|
|
long diffSession = dosSketchLog.getSketch_sessions() - sessionBase;
|
|
|
|
|
long diffPkt = dosSketchLog.getSketch_packets() - pktBase;
|
|
|
|
|
long diffByte = dosSketchLog.getSketch_bytes() - bitBase;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Double diffSessionPercent = getDiffPercent(diffSession, sessionBase)*100;
|
|
|
|
|
Double diffPktPercent = getDiffPercent(diffPkt, pktBase)*100;
|
|
|
|
|
Double diffBitPercent = getDiffPercent(diffByte, bitBase)*100;
|
|
|
|
|
long profileId = 0;
|
|
|
|
|
DosEventLog result =null;
|
|
|
|
|
if (diffSessionPercent >= diffPktPercent && diffSessionPercent >= diffBitPercent){
|
2023-11-13 16:45:04 +08:00
|
|
|
profileId = dosDetectionThreshold.getProfile_id();
|
2023-05-26 15:44:37 +08:00
|
|
|
result= getDosEventLog(dosSketchLog, sessionBase, diffSession, profileId, STATIC_CONDITION_TYPE, SESSIONS_TAG);
|
|
|
|
|
System.out.println(result);
|
|
|
|
|
}else if (diffPktPercent >= diffSessionPercent && diffPktPercent >= diffBitPercent){
|
2023-11-13 16:45:04 +08:00
|
|
|
profileId = dosDetectionThreshold.getProfile_id();
|
2023-05-26 15:44:37 +08:00
|
|
|
result = getDosEventLog(dosSketchLog, pktBase, diffPkt,profileId, STATIC_CONDITION_TYPE, PACKETS_TAG);
|
|
|
|
|
System.out.println(result);
|
|
|
|
|
}else if (diffBitPercent >= diffPktPercent && diffBitPercent >= diffSessionPercent){
|
2023-11-13 16:45:04 +08:00
|
|
|
profileId = dosDetectionThreshold.getProfile_id();
|
2023-05-26 15:44:37 +08:00
|
|
|
result = getDosEventLog(dosSketchLog, bitBase, diffByte, profileId, STATIC_CONDITION_TYPE, BITS_TAG);
|
|
|
|
|
System.out.println(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
private DosEventLog getDosEventLog(DosSketchLog value, long base, long diff, long profileId, int type, String tag) {
|
|
|
|
|
DosEventLog result = null;
|
|
|
|
|
String destinationIp = value.getDestination_ip();
|
|
|
|
|
String attackType = value.getAttack_type();
|
|
|
|
|
if (diff > 0 && base != 0) {
|
|
|
|
|
double percent = getDiffPercent(diff, base);
|
|
|
|
|
Severity severity = judgeSeverity(percent);
|
|
|
|
|
Integer staticSensitivityThreshold = 100;
|
|
|
|
|
if (severity != Severity.NORMAL) {
|
|
|
|
|
if (type == BASELINE_CONDITION_TYPE && percent < 0.2) {
|
|
|
|
|
// logger.debug("当前server IP:{},类型:{},基线值{}百分比{}未超过基线敏感阈值,日志详情\n{}", destinationIp, attackType, base, percent, value);
|
|
|
|
|
}else if ((type == BASELINE_CONDITION_TYPE || type == SENSITIVITY_CONDITION_TYPE) && value.getSketch_sessions() < staticSensitivityThreshold){
|
|
|
|
|
// logger.debug("当前server IP:{},类型:{},基线值{}百分比{}未超过静态敏感阈值,日志详情\n{}",destinationIp, attackType, base, percent, value);
|
|
|
|
|
}else {
|
|
|
|
|
result = getResult(value, base, profileId, severity, percent+1, type, tag);
|
|
|
|
|
if (type == SENSITIVITY_CONDITION_TYPE){
|
|
|
|
|
result.setSeverity(Severity.MAJOR.severity);
|
|
|
|
|
}
|
|
|
|
|
// logger.info("检测到当前server IP {} 存在 {} 异常,超出基线{} {}倍,基于{}:{}检测,日志详情\n {}", destinationIp,attackType,base,percent,type,tag,result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// else {
|
|
|
|
|
// logger.debug("当前server IP:{} 未出现 {} 异常,日志详情 {}", destinationIp, attackType, value);
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DosEventLog getResult(DosSketchLog value, long base, long profileId, Severity severity, double percent, int type, String tag) {
|
|
|
|
|
DosEventLog dosEventLog = new DosEventLog();
|
|
|
|
|
// dosEventLog.setLog_id(SnowflakeId.generateId());
|
|
|
|
|
dosEventLog.setVsys_id(value.getVsys_id());
|
|
|
|
|
dosEventLog.setStart_time(value.getSketch_start_time());
|
|
|
|
|
dosEventLog.setEnd_time(value.getSketch_start_time() + value.getSketch_duration());
|
|
|
|
|
dosEventLog.setProfile_id(profileId);
|
|
|
|
|
dosEventLog.setAttack_type(value.getAttack_type());
|
|
|
|
|
dosEventLog.setSeverity(severity.severity);
|
|
|
|
|
// dosEventLog.setConditions(getConditions(PERCENT_INSTANCE.format(percent), base, value.getSketch_sessions(), type, tag));
|
|
|
|
|
dosEventLog.setConditions(getConditions(percent, base, value.getSketch_sessions(), type, tag,dosEventLog));
|
|
|
|
|
dosEventLog.setDestination_ip(value.getDestination_ip());
|
|
|
|
|
// dosEventLog.setDestination_country(IpUtils.ipLookup.countryLookup(value.getDestination_ip()));
|
|
|
|
|
String ipList = value.getSource_ip();
|
|
|
|
|
dosEventLog.setSource_ip_list(ipList);
|
|
|
|
|
dosEventLog.setSource_country_list(getSourceCountryList(ipList));
|
|
|
|
|
dosEventLog.setSession_rate(value.getSketch_sessions());
|
|
|
|
|
dosEventLog.setPacket_rate(value.getSketch_packets());
|
|
|
|
|
dosEventLog.setBit_rate(value.getSketch_bytes());
|
|
|
|
|
return dosEventLog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getConditions(double percent, long base, long sessions, int type, String tag,DosEventLog dosEventLog) {
|
|
|
|
|
int condition =0;
|
|
|
|
|
if ("Minor".equals(dosEventLog.getSeverity())){
|
|
|
|
|
condition=50;
|
|
|
|
|
}else if ("Warning".equals(dosEventLog.getSeverity())){
|
|
|
|
|
condition=100;
|
|
|
|
|
}else if ("Major".equals(dosEventLog.getSeverity())){
|
|
|
|
|
condition=250;
|
|
|
|
|
}else if ("Severe".equals(dosEventLog.getSeverity())){
|
|
|
|
|
condition=500;
|
|
|
|
|
}else if ("Critical".equals(dosEventLog.getSeverity())){
|
|
|
|
|
condition =800;
|
|
|
|
|
}
|
|
|
|
|
switch (type) {
|
|
|
|
|
case STATIC_CONDITION_TYPE:
|
|
|
|
|
return "Rate > " +
|
|
|
|
|
base + " " +
|
|
|
|
|
tag + "/s" + "(>"+condition+"%)";
|
|
|
|
|
case BASELINE_CONDITION_TYPE:
|
|
|
|
|
return tag + " > " +
|
|
|
|
|
PERCENT_INSTANCE.format(percent) + " of baseline";
|
|
|
|
|
case SENSITIVITY_CONDITION_TYPE:
|
|
|
|
|
return String.valueOf(sessions) + " " +
|
|
|
|
|
tag + "/s Unusually high " +
|
|
|
|
|
StringUtils.capitalize(tag);
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Illegal Argument type:" + type + ", known types = [1,2,3]");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String getSourceCountryList(String sourceIpList) {
|
|
|
|
|
if (StringUtil.isNotBlank(sourceIpList)) {
|
|
|
|
|
String countryList;
|
|
|
|
|
try {
|
|
|
|
|
String[] ipArr = sourceIpList.split(",");
|
|
|
|
|
HashSet<String> countrySet = new HashSet<>();
|
|
|
|
|
for (String ip : ipArr) {
|
2023-11-13 16:45:04 +08:00
|
|
|
String country = IpLookupUtils.getCountryLookup(ip);
|
2023-05-26 15:44:37 +08:00
|
|
|
if (StringUtil.isNotBlank(country)){
|
|
|
|
|
countrySet.add(country);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
countryList = StringUtils.join(countrySet, ", ");
|
|
|
|
|
return countryList;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// logger.error("{} source IP lists 获取国家失败", sourceIpList, e);
|
|
|
|
|
return StringUtil.EMPTY;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw new IllegalArgumentException("Illegal Argument sourceIpList = null");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Double getDiffPercent(long diff, long base) {
|
|
|
|
|
return BigDecimal.valueOf((float) diff / base).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Severity judgeSeverity(double diffPercent) {
|
|
|
|
|
if (diffPercent >= 0.5 && diffPercent < 1) {
|
|
|
|
|
return Severity.MINOR;
|
|
|
|
|
} else if (diffPercent >= 1 && diffPercent < 2.5) {
|
|
|
|
|
return Severity.WARNING;
|
|
|
|
|
} else if (diffPercent >= 2.5 && diffPercent < 5) {
|
|
|
|
|
return Severity.MAJOR;
|
|
|
|
|
} else if (diffPercent >= 5 && diffPercent < 8) {
|
|
|
|
|
return Severity.SEVERE;
|
|
|
|
|
} else if (diffPercent >= 8) {
|
|
|
|
|
return Severity.CRITICAL;
|
|
|
|
|
} else {
|
|
|
|
|
return Severity.NORMAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private enum Severity {
|
|
|
|
|
/**
|
|
|
|
|
* 判断严重程度枚举类型
|
|
|
|
|
*/
|
|
|
|
|
CRITICAL("Critical"),
|
|
|
|
|
SEVERE("Severe"),
|
|
|
|
|
MAJOR("Major"),
|
|
|
|
|
WARNING("Warning"),
|
|
|
|
|
MINOR("Minor"),
|
|
|
|
|
NORMAL("Normal");
|
|
|
|
|
|
|
|
|
|
private final String severity;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String toString() {
|
|
|
|
|
return this.severity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Severity(String severity) {
|
|
|
|
|
this.severity = severity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|