From 706299cd4cce80fbe41c80cef69494e8e78fd1c0 Mon Sep 17 00:00:00 2001 From: aixiao Date: Mon, 10 Oct 2022 17:52:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0IP=E7=99=BD=E5=90=8D=E5=8D=95?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=98=BE=E7=A4=BA=E5=B0=81=E7=A6=81?= =?UTF-8?q?IP=E5=9C=B0=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 ++++++-- conf.c | 35 +++++++++++ conf.h | 8 +++ libiptc.c | 7 +++ rhost.c | 173 +++++++++++++++++++++++++++++++++++++++++------------ rhost.conf | 14 ++++- rhost.h | 4 +- 7 files changed, 217 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index d529af9..1691406 100644 --- a/README.md +++ b/README.md @@ -42,17 +42,30 @@ update-alternatives --set ebtables /usr/sbin/ebtables-legacy 配置文件 global { DAEMON = "off"; // on开启后台运行,off不开启 - TIME = "60"; // 睡眠时间(单位秒,大于等于1) + TIME = "10"; // 睡眠时间 - REFUSE_NUMBER = 5; // 拒绝攻击次数(大于等于1) - IS_MAIL = 0; // 开启邮件告警(0关闭,1开启) + PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP - IS_DING_WEBHOOK = 1; // 开启叮叮告警(0关闭,1开启) + + IPV4_RESTRICTION = 1; // 是否启用百名单 + IPV4_WHITE_LIST = "1.193.37.156 117.158.215.217"; // IP白名单 + + + IS_BLOCKED = 1; // 是否封禁攻击IP + REFUSE_NUMBER = 5; // 拒绝攻击次数 + + + IS_MAIL = 0; // 开启邮件告警 + + + IS_DING_WEBHOOK = 1; // 开启叮叮告警 PHONE = "15565979082"; // @的人手机号 DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK - IS_QQMAIL = 0; // 开启QQ邮箱告警(0关闭,1开启) - RECV_MAIL = "1605227279"; // 接收者QQ + + IS_QQMAIL = 0; // 开启QQ邮箱告警 + RECV_MAIL = "1605227279@qq.com"; // 接收者QQ } + ``` diff --git a/conf.c b/conf.c index 88fc141..5399e8e 100644 --- a/conf.c +++ b/conf.c @@ -91,6 +91,12 @@ static void parse_global_module(char *content, conf * conf) conf->TIME = atoi(val_begin); } + + if (strcasecmp(var, "IS_BLOCKED") == 0) { + val_begin_len = val_end - val_begin; + conf->IS_BLOCKED = atoi(val_begin); + + } if (strcasecmp(var, "REFUSE_NUMBER") == 0) { val_begin_len = val_end - val_begin; @@ -150,6 +156,19 @@ static void parse_global_module(char *content, conf * conf) if (copy_new_mem(val_begin, val_begin_len, &conf->PUBLIC_IP) != 0) return; } + + if (strcasecmp(var, "IPV4_RESTRICTION") == 0) { + val_begin_len = val_end - val_begin; + conf->IPV4_RESTRICTION = atoi(val_begin); + } + + if (strcasecmp(var, "IPV4_WHITE_LIST") == 0) { + val_begin_len = val_end - val_begin; + if (copy_new_mem(val_begin, val_begin_len, &conf->IPV4_WHITE_LIST) != 0) + return; + } + + content = strchr(lineEnd + 1, '\n'); } @@ -226,6 +245,8 @@ void free_conf(conf * conf) free(conf->RECV_MAIL); if (conf->PUBLIC_IP) free(conf->PUBLIC_IP); + if (conf->IPV4_WHITE_LIST) + free(conf->IPV4_WHITE_LIST); return; } @@ -251,4 +272,18 @@ void ptintf_conf(conf * conf) printf("%s\n", conf->RECV_MAIL); if (conf->PUBLIC_IP) printf("%s\n", conf->PUBLIC_IP); + if (conf->IPV4_WHITE_LIST) + printf("%s\n", conf->IPV4_WHITE_LIST); +} + +void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]) +{ + int i = 0; + char *result = NULL; + result = strtok(string, delims); + while (result != NULL) { + i++; + strcpy(whitelist_ip[i], result); + result = strtok(NULL, delims); + } } diff --git a/conf.h b/conf.h index 632b8a0..8890437 100644 --- a/conf.h +++ b/conf.h @@ -7,15 +7,22 @@ #include #include +#define WHITELIST_IP_NUM 1024 + typedef struct CONF { char *DAEMON; int TIME; + int IS_BLOCKED; int REFUSE_NUMBER; // 获取公网IP Url地址 char *PUBLIC_IP; + // IPV4 白名单 + int IPV4_RESTRICTION; + char *IPV4_WHITE_LIST; + int IS_MAIL; int IS_DING_WEBHOOK; @@ -31,5 +38,6 @@ typedef struct CONF { void read_conf(char *filename, conf * configure); void free_conf(conf * conf); void ptintf_conf(conf * conf); +void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]); #endif diff --git a/libiptc.c b/libiptc.c index 41a6f9d..8429ed7 100644 --- a/libiptc.c +++ b/libiptc.c @@ -176,10 +176,16 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char free(entry_match); return 1; } + if (append) + { result = iptc_append_entry(labelit, chain_entry, handle); + } else + { result = iptc_insert_entry(labelit, chain_entry, 0, handle); + } + if (!result) { printf("libiptc error: Can't add, %s\n", iptc_strerror(errno)); free(chain_entry); @@ -188,6 +194,7 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char free(entry_match); return 1; } + result = iptc_commit(handle); if (!result) { printf("libiptc error: Commit error, %s\n", iptc_strerror(errno)); diff --git a/rhost.c b/rhost.c index 0dea6af..50674df 100644 --- a/rhost.c +++ b/rhost.c @@ -196,28 +196,71 @@ int QQ_mail_warning(char *illegal_ip, char *public_ip, conf * conf) return system(string); } +// IP段白名单对比 +int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM]) +{ + int i; + + for (i = 1; i < WHITELIST_IP_NUM - 1; i++) { + if (strcmp(whitelist_ip[i], "\0") == 0) { // 如果字符串为空就跳出循环 + break; + } + if ((strncmp(client_ip, whitelist_ip[i], strlen(whitelist_ip[i]))) == 0) { // 对比client_ip长度, + return 1; + } + } + + return 0; +} + +char *remove_space(const char *str) +{ + unsigned int uLen = strlen(str); + + if(0 == uLen) + { + return '\0'; + } + + char *strRet = (char *)malloc(uLen + 1); + memset(strRet, 0, uLen+1); + + unsigned int i = 0, j = 0; + for(i=0; itm_mday >= 10) { if ((fp = popen(GE_10, "r")) == NULL) { @@ -230,7 +273,7 @@ int rule(conf * conf) return 1; } } - } else if (CENTOS_SYSTEM == check_system()) // Centos 7系统规则 + } else if (CENTOS_SYSTEM == check_system()) // Centos 7系统规则 { if (tp->tm_mday >= 10) { if ((fp = popen(CENTOS_GE_10, "r")) == NULL) { @@ -256,62 +299,111 @@ int rule(conf * conf) strcat(splice_command, "\n"); } } - printf("%s", splice_command); // 打印所有非法IP + printf("%s", splice_command); // 打印所有非法IP - // 拼接命令 - sprintf(awk, AWK, conf->REFUSE_NUMBER); + + sprintf(awk, AWK, conf->REFUSE_NUMBER); // 拼接命令 strcpy(command, "echo \""); strcat(command, splice_command); strcat(command, "\""); strcat(command, awk); - if ((fp = popen(command, "r")) == NULL) // 执行命令 + if ((fp = popen(command, "r")) == NULL) // 执行命令 { perror("popen command"); return 1; } - while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会 + while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会 { + buffer[strlen(buffer) - 1] = '\0'; // 去除回车 + + + split_string(conf->IPV4_WHITE_LIST, " ", whitelist_ip); + + for (i = 1; i <= WHITELIST_IP_NUM - 1; i++) { + if (*whitelist_ip[i] != '\0') ; + //printf("%s\n", whitelist_ip[i]); + } + + if (conf->IPV4_RESTRICTION == 1) { // 是否启用百名单 + if (whitelist(buffer, whitelist_ip) == 1) { + ; + //printf("白名单IPV4:%s\n", buffer); + + continue; + } + } + - buffer[strlen(buffer) - 1] = '\0'; // 去除回车 - //sprintf(iptables, IPTABLES, buffer); - //sprintf(iptables_check, IPTABLES_CHECK, buffer); - - //if (0 != system(iptables_check)) // 调用iptables命令判断是否存在规则, 不存在时再添加规则 - if (0 != show_all_rule(buffer)) // libiptc库判断 + if (0 != show_all_rule(buffer)) // libiptc库判断否存在规则 { - if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警 + char *location = NULL; + char *location_json = NULL; + char iplocation[BUFFER]; + + char URL[BUFFER+70]; + memset(URL, 0, BUFFER+70); + sprintf(URL, "http://opendata.baidu.com/api.php?query=%s&co=&resource_id=6006&oe=utf8", buffer); + + location_json = GET_PUBLIC_IP(URL); + if (NULL == location_json) { - dingding_warning(buffer, public_ip, conf); + printf("获取IP位置错误!\n"); + } + else + { + //printf("%s\n", location_json); + + char temp[BUFFER]; + memset(temp, 0, BUFFER); + + char *p = strstr(location_json, "\"location\""); + char *p1 = strstr(p, "\","); + + + memcpy(temp, p+12, p1-p-12); + + location = remove_space(temp); + + } + + memset(iplocation, 0, BUFFER); + strcpy(iplocation, buffer); + strcat(iplocation, "("); + strcat(iplocation, location); + strcat(iplocation, ")"); + //printf("%s\n", iplocation); + + if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警 + { + dingding_warning(iplocation, public_ip, conf); sleep(3); } - if (conf->IS_MAIL == 1) // 邮件告警 + if (conf->IS_MAIL == 1) // 邮件告警 { - mail_warning(buffer, public_ip, conf); + mail_warning(iplocation, public_ip, conf); sleep(3); } - if (conf->IS_QQMAIL == 1) // 邮件告警 + if (conf->IS_QQMAIL == 1) // 邮件告警 { - QQ_mail_warning(buffer, public_ip, conf); + QQ_mail_warning(iplocation, public_ip, conf); sleep(3); } - /* - // 调用命令下发规则 - if ((fc = popen(iptables, "r")) == NULL) { - perror("popen iptables"); - return 1; - } - */ - // libiptc 库插入规则 iptables -t filter -A INPUT -p tcp -s xxxx -j DROP - unsigned int srcIp; - inet_pton(AF_INET, buffer, &srcIp); - iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1); + // 是否封禁攻击IP + if (conf->IS_BLOCKED == 1) { + // libiptc 库插入规则 iptables -t filter -A INPUT -p tcp -m tcp -s xxxx -j DROP + unsigned int srcIp; + inet_pton(AF_INET, buffer, &srcIp); + iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1); + } + free(location); + free(location_json); } } @@ -362,13 +454,16 @@ int main(int argc, char *argv[], char **env) conf *conf = (struct CONF *)malloc(sizeof(struct CONF)); read_conf(path, conf); //ptintf_conf(conf); + - // 新版本获取公网IP + // 获取公网IP public_ip = GET_PUBLIC_IP(conf->PUBLIC_IP); //printf("%s", public_ip); + signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 + if (0 == strcmp(conf->DAEMON, "on")) { goto goto_daemon; } diff --git a/rhost.conf b/rhost.conf index 86bb32b..b834b6d 100644 --- a/rhost.conf +++ b/rhost.conf @@ -1,17 +1,27 @@ global { DAEMON = "off"; // on开启后台运行,off不开启 - TIME = "60"; // 睡眠时间 + TIME = "10"; // 睡眠时间 + PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP - REFUSE_NUMBER = 3; // 拒绝攻击次数 + + IPV4_RESTRICTION = 1; // 是否启用百名单 + IPV4_WHITE_LIST = "1.193.37.156 117.158.215.217"; // IP白名单 + + + IS_BLOCKED = 1; // 是否封禁攻击IP + REFUSE_NUMBER = 5; // 拒绝攻击次数 + IS_MAIL = 0; // 开启邮件告警 + IS_DING_WEBHOOK = 1; // 开启叮叮告警 PHONE = "15565979082"; // @的人手机号 DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK + IS_QQMAIL = 0; // 开启QQ邮箱告警 RECV_MAIL = "1605227279@qq.com"; // 接收者QQ } diff --git a/rhost.h b/rhost.h index 83c863a..83c9316 100644 --- a/rhost.h +++ b/rhost.h @@ -20,6 +20,8 @@ #define BUFFER 1024 #define LONG_BUFFER 1024*100 +#define WHITELIST_IP_NUM 1024 + #define AWK " | awk -v num=%d '{a[$1]+=1;} END {for(i in a){if (a[i] >= num) {print i;}}}' " #define GE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\").$(LC_ALL=\"C\" date \"+%d\")\" /var/log/auth.log | grep failure | grep rhost" #define LE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\")..$(LC_ALL=\"C\" date | awk '{print $3}')\" /var/log/auth.log | grep failure | grep rhost" @@ -27,8 +29,6 @@ #define CENTOS_GE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\").$(LC_ALL=\"C\" date \"+%d\")\" /var/log/secure | grep failure | grep rhost" #define CENTOS_LE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\")..$(LC_ALL=\"C\" date | awk '{print $3}')\" /var/log/secure | grep failure | grep rhost" -#define IPTABLES "`which iptables` -t filter -I INPUT -s %s -j DROP" -#define IPTABLES_CHECK "`which iptables` -t filter -C INPUT -s %s -j DROP 2> /dev/null" #define QQMAIL "email -r %s -s \"System ban IP\" -t \"%s\""