增加IP白名单,增加显示封禁IP地域

This commit is contained in:
aixiao 2022-10-10 17:52:00 +08:00
parent 15b093d3f6
commit 706299cd4c
7 changed files with 217 additions and 49 deletions

View File

@ -42,17 +42,30 @@ update-alternatives --set ebtables /usr/sbin/ebtables-legacy
配置文件 配置文件
global { global {
DAEMON = "off"; // on开启后台运行off不开启 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"; // @的人手机号 PHONE = "15565979082"; // @的人手机号
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK 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
} }
``` ```

35
conf.c
View File

@ -92,6 +92,12 @@ static void parse_global_module(char *content, conf * conf)
} }
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) { if (strcasecmp(var, "REFUSE_NUMBER") == 0) {
val_begin_len = val_end - val_begin; val_begin_len = val_end - val_begin;
conf->REFUSE_NUMBER = atoi(val_begin); conf->REFUSE_NUMBER = atoi(val_begin);
@ -151,6 +157,19 @@ static void parse_global_module(char *content, conf * conf)
return; 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'); content = strchr(lineEnd + 1, '\n');
} }
} }
@ -226,6 +245,8 @@ void free_conf(conf * conf)
free(conf->RECV_MAIL); free(conf->RECV_MAIL);
if (conf->PUBLIC_IP) if (conf->PUBLIC_IP)
free(conf->PUBLIC_IP); free(conf->PUBLIC_IP);
if (conf->IPV4_WHITE_LIST)
free(conf->IPV4_WHITE_LIST);
return; return;
} }
@ -251,4 +272,18 @@ void ptintf_conf(conf * conf)
printf("%s\n", conf->RECV_MAIL); printf("%s\n", conf->RECV_MAIL);
if (conf->PUBLIC_IP) if (conf->PUBLIC_IP)
printf("%s\n", 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);
}
} }

8
conf.h
View File

@ -7,15 +7,22 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#define WHITELIST_IP_NUM 1024
typedef struct CONF { typedef struct CONF {
char *DAEMON; char *DAEMON;
int TIME; int TIME;
int IS_BLOCKED;
int REFUSE_NUMBER; int REFUSE_NUMBER;
// 获取公网IP Url地址 // 获取公网IP Url地址
char *PUBLIC_IP; char *PUBLIC_IP;
// IPV4 白名单
int IPV4_RESTRICTION;
char *IPV4_WHITE_LIST;
int IS_MAIL; int IS_MAIL;
int IS_DING_WEBHOOK; int IS_DING_WEBHOOK;
@ -31,5 +38,6 @@ typedef struct CONF {
void read_conf(char *filename, conf * configure); void read_conf(char *filename, conf * configure);
void free_conf(conf * conf); void free_conf(conf * conf);
void ptintf_conf(conf * conf); void ptintf_conf(conf * conf);
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]);
#endif #endif

View File

@ -176,10 +176,16 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char
free(entry_match); free(entry_match);
return 1; return 1;
} }
if (append) if (append)
{
result = iptc_append_entry(labelit, chain_entry, handle); result = iptc_append_entry(labelit, chain_entry, handle);
}
else else
{
result = iptc_insert_entry(labelit, chain_entry, 0, handle); result = iptc_insert_entry(labelit, chain_entry, 0, handle);
}
if (!result) { if (!result) {
printf("libiptc error: Can't add, %s\n", iptc_strerror(errno)); printf("libiptc error: Can't add, %s\n", iptc_strerror(errno));
free(chain_entry); free(chain_entry);
@ -188,6 +194,7 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char
free(entry_match); free(entry_match);
return 1; return 1;
} }
result = iptc_commit(handle); result = iptc_commit(handle);
if (!result) { if (!result) {
printf("libiptc error: Commit error, %s\n", iptc_strerror(errno)); printf("libiptc error: Commit error, %s\n", iptc_strerror(errno));

149
rhost.c
View File

@ -196,26 +196,69 @@ int QQ_mail_warning(char *illegal_ip, char *public_ip, conf * conf)
return system(string); 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; i<uLen+1; i++)
{
if(str[i] != ' ')
{
strRet[j++] = str[i];
}
}
strRet[j] = '\0';
return strRet;
}
// 封禁非法IP // 封禁非法IP
int rule(conf * conf) int rule(conf * conf)
{ {
FILE *fp, *fc; int i;
char whitelist_ip[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
//char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER], iptables[BUFFER + (sizeof(IPTABLES))], iptables_check[BUFFER + (sizeof(IPTABLES_CHECK))];
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER]; char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER];
FILE *fp, *fc;
time_t timep; time_t timep;
struct tm *tp; struct tm *tp;
i=0;
fp = NULL;
fc = NULL;
time(&timep); time(&timep);
tp = localtime(&timep); tp = localtime(&timep);
memset(splice_command, 0, LONG_BUFFER); memset(splice_command, 0, LONG_BUFFER);
memset(command, 0, LONG_BUFFER); memset(command, 0, LONG_BUFFER);
memset(buffer, 0, BUFFER); memset(buffer, 0, BUFFER);
memset(awk, 0, BUFFER); memset(awk, 0, BUFFER);
//memset(iptables, 0, BUFFER+(sizeof(IPTABLES)));
//memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES_CHECK)));
fp = NULL;
fc = NULL;
if (DEBISN_SYSTEM == check_system()) // Debian 系统规则 if (DEBISN_SYSTEM == check_system()) // Debian 系统规则
{ {
@ -258,8 +301,8 @@ int rule(conf * conf)
} }
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 \""); strcpy(command, "echo \"");
strcat(command, splice_command); strcat(command, splice_command);
strcat(command, "\""); strcat(command, "\"");
@ -273,45 +316,94 @@ int rule(conf * conf)
while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会 while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会
{ {
buffer[strlen(buffer) - 1] = '\0'; // 去除回车 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库判断 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;
}
}
if (0 != show_all_rule(buffer)) // libiptc库判断否存在规则
{ {
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)
{
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) // 钉钉告警 if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警
{ {
dingding_warning(buffer, public_ip, conf); dingding_warning(iplocation, public_ip, conf);
sleep(3); 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); 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); 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 // 是否封禁攻击IP
if (conf->IS_BLOCKED == 1) {
// libiptc 库插入规则 iptables -t filter -A INPUT -p tcp -m tcp -s xxxx -j DROP
unsigned int srcIp; unsigned int srcIp;
inet_pton(AF_INET, buffer, &srcIp); inet_pton(AF_INET, buffer, &srcIp);
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1); iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
}
free(location);
free(location_json);
} }
} }
@ -363,12 +455,15 @@ int main(int argc, char *argv[], char **env)
read_conf(path, conf); read_conf(path, conf);
//ptintf_conf(conf); //ptintf_conf(conf);
// 新版本获取公网IP
// 获取公网IP
public_ip = GET_PUBLIC_IP(conf->PUBLIC_IP); public_ip = GET_PUBLIC_IP(conf->PUBLIC_IP);
//printf("%s", public_ip); //printf("%s", public_ip);
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
if (0 == strcmp(conf->DAEMON, "on")) { if (0 == strcmp(conf->DAEMON, "on")) {
goto goto_daemon; goto goto_daemon;
} }

View File

@ -1,17 +1,27 @@
global { global {
DAEMON = "off"; // on开启后台运行off不开启 DAEMON = "off"; // on开启后台运行off不开启
TIME = "60"; // 睡眠时间 TIME = "10"; // 睡眠时间
PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP 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_MAIL = 0; // 开启邮件告警
IS_DING_WEBHOOK = 1; // 开启叮叮告警 IS_DING_WEBHOOK = 1; // 开启叮叮告警
PHONE = "15565979082"; // @的人手机号 PHONE = "15565979082"; // @的人手机号
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK
IS_QQMAIL = 0; // 开启QQ邮箱告警 IS_QQMAIL = 0; // 开启QQ邮箱告警
RECV_MAIL = "1605227279@qq.com"; // 接收者QQ RECV_MAIL = "1605227279@qq.com"; // 接收者QQ
} }

View File

@ -20,6 +20,8 @@
#define BUFFER 1024 #define BUFFER 1024
#define LONG_BUFFER 1024*100 #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 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 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" #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_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 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\"" #define QQMAIL "email -r %s -s \"System ban IP\" -t \"%s\""