From 9421d1f1ebe5ebae6fd793ac2c1017a7305e61b5 Mon Sep 17 00:00:00 2001 From: aixiao Date: Sat, 8 Oct 2022 14:28:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=8E=B7=E5=8F=96=E5=85=AC?= =?UTF-8?q?=E7=BD=91IP=E6=96=B9=E6=B3=95=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=89=93=E5=8D=B0=20=09=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=9A=20=20=20=20=20Makefile=20=09=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=9A=20=20=20=20=20README.md=20=09=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=9A=20=20=20=20=20conf.c=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A?= =?UTF-8?q?=20=20=20=20=20conf.h=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20?= =?UTF-8?q?=20=20denyhosts.sh=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20?= =?UTF-8?q?=20libiptc.c=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20=20lib?= =?UTF-8?q?iptc.h=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20=20rhost.c?= =?UTF-8?q?=20=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20=20rhost.conf=20?= =?UTF-8?q?=09=E4=BF=AE=E6=94=B9=EF=BC=9A=20=20=20=20=20rhost.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- README.md | 12 +- conf.c | 76 ++++++++----- conf.h | 15 ++- denyhosts.sh | 4 +- libiptc.c | 39 +++---- libiptc.h | 5 +- rhost.c | 310 ++++++++++++++++++++++++++++----------------------- rhost.conf | 8 +- rhost.h | 11 +- 10 files changed, 268 insertions(+), 214 deletions(-) diff --git a/Makefile b/Makefile index 49003e3..c5d89c9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CROSS_COMPILE ?= CC := $(CROSS_COMPILE)gcc -CFLAGS += -O2 -g -Wall +CFLAGS += -Os -g -Wall LIB += -lcurl -lip4tc OBG = rhost diff --git a/README.md b/README.md index 729c4bb..d529af9 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,16 @@ ssh防止暴力破解,适用Debian 8、9、11 Centos 7 支持钉钉告警和邮件告警 支持第三方QQ邮箱告警 支持一次运行检测、后台运行检测 + +``` Debian系统请安装libcurl库和libiptc库 -Centos 7系统请安装libcurl库和iptables-devel库,yum install iptables-devel libcurl-devel + apt install libip4tc-dev libcurl4-openssl-dev (或者libcurl4-gnutls-dev) +``` + +``` +Centos 7系统请安装libcurl库和iptables-devel库 + yum install iptables-devel libcurl-devel +``` ``` @@ -45,8 +53,6 @@ global { DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK IS_QQMAIL = 0; // 开启QQ邮箱告警(0关闭,1开启) - SEND_QQ = "1605227279"; // 发送者QQ - QQMAIL_KEY = "caczsjchvyibiabe"; // 发送者QQ密钥 RECV_MAIL = "1605227279"; // 接收者QQ } ``` diff --git a/conf.c b/conf.c index eda3da1..88fc141 100644 --- a/conf.c +++ b/conf.c @@ -81,7 +81,7 @@ static void parse_global_module(char *content, conf * conf) while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) { if (strcasecmp(var, "DAEMON") == 0) { val_begin_len = val_end - val_begin; - + if (copy_new_mem(val_begin, val_begin_len, &conf->DAEMON) != 0) return; } @@ -89,61 +89,67 @@ static void parse_global_module(char *content, conf * conf) if (strcasecmp(var, "TIME") == 0) { val_begin_len = val_end - val_begin; conf->TIME = atoi(val_begin); - + } - + if (strcasecmp(var, "REFUSE_NUMBER") == 0) { val_begin_len = val_end - val_begin; conf->REFUSE_NUMBER = atoi(val_begin); - + } - + if (strcasecmp(var, "IS_MAIL") == 0) { val_begin_len = val_end - val_begin; conf->IS_MAIL = atoi(val_begin); - + } - + if (strcasecmp(var, "IS_DING_WEBHOOK") == 0) { val_begin_len = val_end - val_begin; conf->IS_DING_WEBHOOK = atoi(val_begin); - + } - + if (strcasecmp(var, "PHONE") == 0) { val_begin_len = val_end - val_begin; if (copy_new_mem(val_begin, val_begin_len, &conf->PHONE) != 0) return; } - + if (strcasecmp(var, "DING_WEBHOOK") == 0) { val_begin_len = val_end - val_begin; if (copy_new_mem(val_begin, val_begin_len, &conf->DING_WEBHOOK) != 0) return; } - + if (strcasecmp(var, "IS_QQMAIL") == 0) { val_begin_len = val_end - val_begin; conf->IS_QQMAIL = atoi(val_begin); } - + if (strcasecmp(var, "SEND_QQ") == 0) { val_begin_len = val_end - val_begin; if (copy_new_mem(val_begin, val_begin_len, &conf->SEND_QQ) != 0) return; } - + if (strcasecmp(var, "QQMAIL_KEY") == 0) { val_begin_len = val_end - val_begin; if (copy_new_mem(val_begin, val_begin_len, &conf->QQMAIL_KEY) != 0) return; } - + if (strcasecmp(var, "RECV_MAIL") == 0) { val_begin_len = val_end - val_begin; if (copy_new_mem(val_begin, val_begin_len, &conf->RECV_MAIL) != 0) return; } + + if (strcasecmp(var, "PUBLIC_IP") == 0) { + val_begin_len = val_end - val_begin; + if (copy_new_mem(val_begin, val_begin_len, &conf->PUBLIC_IP) != 0) + return; + } content = strchr(lineEnd + 1, '\n'); } @@ -206,27 +212,43 @@ void read_conf(char *filename, conf * configure) void free_conf(conf * conf) { - free(conf->DAEMON); - free(conf->PHONE); - free(conf->DING_WEBHOOK); - free(conf->SEND_QQ); - free(conf->QQMAIL_KEY); - free(conf->RECV_MAIL); + if (conf->DAEMON) + free(conf->DAEMON); + if (conf->PHONE) + free(conf->PHONE); + if (conf->DING_WEBHOOK) + free(conf->DING_WEBHOOK); + if (conf->SEND_QQ) + free(conf->SEND_QQ); + if (conf->QQMAIL_KEY) + free(conf->QQMAIL_KEY); + if (conf->RECV_MAIL) + free(conf->RECV_MAIL); + if (conf->PUBLIC_IP) + free(conf->PUBLIC_IP); return; } -void ptintf_conf(conf *conf) +void ptintf_conf(conf * conf) { - printf("%s\n", conf->DAEMON); + if (conf->DAEMON) + printf("%s\n", conf->DAEMON); printf("%d\n", conf->TIME); printf("%d\n", conf->REFUSE_NUMBER); printf("%d\n", conf->IS_MAIL); printf("%d\n", conf->IS_DING_WEBHOOK); - printf("%s\n", conf->PHONE); - printf("%s\n", conf->DING_WEBHOOK); + if (conf->PHONE) + printf("%s\n", conf->PHONE); + if (conf->DING_WEBHOOK) + printf("%s\n", conf->DING_WEBHOOK); printf("%d\n", conf->IS_QQMAIL); - printf("%s\n", conf->SEND_QQ); - printf("%s\n", conf->QQMAIL_KEY); - printf("%s\n", conf->RECV_MAIL); + if (conf->SEND_QQ) + printf("%s\n", conf->SEND_QQ); + if (conf->QQMAIL_KEY) + printf("%s\n", conf->QQMAIL_KEY); + if (conf->RECV_MAIL) + printf("%s\n", conf->RECV_MAIL); + if (conf->PUBLIC_IP) + printf("%s\n", conf->PUBLIC_IP); } diff --git a/conf.h b/conf.h index 75ba8be..632b8a0 100644 --- a/conf.h +++ b/conf.h @@ -10,23 +10,26 @@ typedef struct CONF { char *DAEMON; int TIME; - + int REFUSE_NUMBER; + // 获取公网IP Url地址 + char *PUBLIC_IP; + int IS_MAIL; - + int IS_DING_WEBHOOK; char *PHONE; char *DING_WEBHOOK; - + int IS_QQMAIL; char *SEND_QQ; char *QQMAIL_KEY; char *RECV_MAIL; } conf; -void read_conf(char *filename, conf *configure); +void read_conf(char *filename, conf * configure); void free_conf(conf * conf); -void ptintf_conf(conf *conf); +void ptintf_conf(conf * conf); -#endif \ No newline at end of file +#endif diff --git a/denyhosts.sh b/denyhosts.sh index ed34431..a18c66f 100644 --- a/denyhosts.sh +++ b/denyhosts.sh @@ -9,7 +9,7 @@ source /etc/profile function init() { - SEND_MAIL=0 + SEND_MAIL=1 PWD_PATH="/root"; TIME=`date +"%Y%m%d%H%M"`; LOG_FILE="${PWD_PATH}/${TIME}.log"; @@ -28,7 +28,7 @@ function run() free -hl &>> ${LOG_FILE} echo "System process:" &>> ${LOG_FILE} - ps -auxwwjf &>> ${LOG_FILE} + ps -auxwwf &>> ${LOG_FILE} echo "Network Connections" &>> ${LOG_FILE} netstat -tnulp &>> ${LOG_FILE} diff --git a/libiptc.c b/libiptc.c index 6f7a9d1..41a6f9d 100644 --- a/libiptc.c +++ b/libiptc.c @@ -2,7 +2,7 @@ int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4) { - int r=1; + int r = 1; const struct ipt_entry *entry; struct ipt_entry_match *entry_match; @@ -10,14 +10,13 @@ int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4) const char *t = iptc_get_target(entry, handle); entry_match = (struct ipt_entry_match *)entry->elems; //printf("u.user.name: %s\n", entry_match->u.user.name); - char addr[33]; - memset(addr, 0, 33); - inet_ntop(AF_INET, &(entry->ip.dst), addr, sizeof(addr)); + char addr[64]; + memset(addr, 0, 64); + inet_ntop(AF_INET, &(entry->ip.src), addr, sizeof(addr)); //printf("%s\n", addr); //printf("%s\n", t); - if (0 == strcmp(ipv4, addr) && 0 == strcmp(t, "DROP") && 0 == strcmp(entry_match->u.user.name, "tcp")) - { - r=0; + if (0 == strcmp(ipv4, addr) && 0 == strcmp(t, "DROP") && 0 == strcmp(entry_match->u.user.name, "tcp")) { + r = 0; break; } } @@ -28,25 +27,24 @@ int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4) int show_all_rule(char *ipv4) { - int r=0; + int r = 0; struct xtc_handle *handle; const char *chain = NULL; struct ipt_counters counter; - + handle = iptc_init("filter"); - for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle)) - { + for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle)) { if (chain != NULL && handle != NULL) { iptc_get_policy(chain, &counter, handle); } r = x_get_rule(chain, handle, ipv4); - if (r==0){ + if (r == 0) { break; } } - + return r; } @@ -70,6 +68,7 @@ static void parse_ports(const char *portstring, u_int16_t * ports) ports[0] = buffer[0] ? parse_port(buffer) : 0; ports[1] = cp[0] ? parse_port(cp) : 0xFFFF; } + free(buffer); } @@ -82,7 +81,7 @@ struct ipt_entry_match *get_match(const char *sports, const char *dports, unsign size = IPT_ALIGN(sizeof(*match)) + IPT_ALIGN(sizeof(*udpinfo)); match = (struct ipt_entry_match *)calloc(1, size); match->u.match_size = size; - strncpy(match->u.user.name, protocol, IPT_FUNCTION_MAXNAMELEN-2); + strncpy(match->u.user.name, protocol, IPT_FUNCTION_MAXNAMELEN - 2); udpinfo = (struct ipt_udp *)match->data; udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF; @@ -99,8 +98,7 @@ struct ipt_entry_match *get_match(const char *sports, const char *dports, unsign return match; } -int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src, - unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) +int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src, unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) { struct xtc_handle *handle; struct ipt_entry *chain_entry; @@ -137,7 +135,7 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int)); entry_target = (struct ipt_entry_target *)calloc(1, size); entry_target->u.user.target_size = size; - strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN); + strncpy(entry_target->u.user.name, target, XT_EXTENSION_MAXNAMELEN); } if (entry_match) { match_size = entry_match->u.match_size; @@ -149,14 +147,14 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char if (chain_entry == NULL) { free(tmp_ipt); } - + memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size); chain_entry->target_offset = sizeof(*chain_entry) + match_size; chain_entry->next_offset = sizeof(*chain_entry) + match_size + entry_target->u.target_size; if (entry_match) { memcpy(chain_entry->elems, entry_match, match_size); } - + handle = iptc_init(table); if (!handle) { printf("libiptc error: Can't initialize table %s, %s\n", table, iptc_strerror(errno)); @@ -200,11 +198,10 @@ int iptc_add_rule(const char *table, const char *chain, int protocol, const char return 1; } - if (entry_match) free(entry_match); free(entry_target); free(chain_entry); - + return 0; } diff --git a/libiptc.h b/libiptc.h index 3d56ab3..749a83f 100644 --- a/libiptc.h +++ b/libiptc.h @@ -18,7 +18,6 @@ /* Dest port. */ #define NFC_IP_DST_PT 0x0400 - #ifndef IPT_MIN_ALIGN #define IPT_MIN_ALIGN (__alignof__(struct ipt_entry)) #endif @@ -30,9 +29,7 @@ #define IPTC_TARGET_SIZE XT_ALIGN(sizeof(struct ipt_entry_target)) #define IPTC_FULL_SIZE IPTC_ENTRY_SIZE + IPTC_MATCH_SIZE + IPTC_TARGET_SIZE - int show_all_rule(char *ipv4); -int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src, - unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append); +int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src, unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append); #endif diff --git a/rhost.c b/rhost.c index e6b4ad6..0dea6af 100644 --- a/rhost.c +++ b/rhost.c @@ -1,11 +1,76 @@ - #include "conf.h" #include "rhost.h" #include "libiptc.h" - // 存储公网IP -char public_ip[BUFFER]; +char *public_ip; + +struct MemoryStruct { + char *memory; + size_t size; +}; + +static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct MemoryStruct *mem = (struct MemoryStruct *)userp; + + // 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小 + char *ptr = realloc(mem->memory, mem->size + realsize + 1); + if (ptr == NULL) { + /* 内存不足! */ + printf("not enough memory (realloc returned NULL)\n"); + return 0; + } + + mem->memory = ptr; + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + + return realsize; +} + +// 获取公网IP +static char *GET_PUBLIC_IP(char *URL) +{ + CURL *curl_handle; + CURLcode res; + + struct MemoryStruct chunk; + + chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */ + chunk.size = 0; /* 此时没有数据 */ + + curl_global_init(CURL_GLOBAL_ALL); + + /* 初始化curl会话 */ + curl_handle = curl_easy_init(); + + /* 指定要获取的URL */ + curl_easy_setopt(curl_handle, CURLOPT_URL, URL); + /* 将所有数据发送到此函数 */ + //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + /* 将“chunk”结构传递给回调函数 */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback + res = curl_easy_perform(curl_handle); + + if (res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + } else { + //printf("%lu bytes retrieved\n", (unsigned long)chunk.size); + //printf("%s", chunk.memory); + ; + } + + curl_easy_cleanup(curl_handle); + curl_global_cleanup(); + + return chunk.memory; +} // 检测系统 int check_system() @@ -19,74 +84,22 @@ int check_system() return UNKNOWN_SYSTEM; } -// 获取公网IP -char *get_public_ip(char *ip) -{ - FILE *fp; - char buff[BUFFER]; - - memset(buff, 0, BUFFER); - if (NULL == (fp = popen("curl members.3322.org/dyndns/getip --silent", "r"))) { - perror("popen curl"); - } - - while (fgets(buff, BUFFER, fp) != NULL) { - buff[strlen(buff) - 1] = '\0'; - } - - if (NULL != fp) - pclose(fp); - - return strcpy(ip, buff); -} - -// 替换字符串 -int strReplaceAll(char *str, char *sub, char *replace) -{ - if (NULL == str || NULL == sub || NULL == replace) { - printf("strReplaceAll\n"); - return 1; - } - - char *p = NULL; - char *t = NULL; - char *q = NULL; - char *dst = NULL; - char *src = NULL; - - int str_len = strlen(str); - int sub_len = strlen(sub); - int replace_len = strlen(replace); - - p = str; - while ('\0' != *p) { - t = str + str_len; - q = strstr(str, sub); - if (NULL == q) // 没有子串了直接返回 - break; - - src = q + sub_len; // 源头, 原有sub后的一个字符 - dst = q + replace_len; // 目的,放完replace后的一个字符 - memcpy(dst, src, t - src); // 原有字符串后移,放出空间 - memcpy(q, replace, replace_len); // 将replace字符拷贝进来 - str_len = str_len + replace_len - sub_len; - - p = q + replace_len; // p 下一轮replace后的一个字符 - } - - str[str_len] = '\0'; // 通过'\0'表示结尾 - - return 0; -} - // 钉钉告警 -int dingding_warning(char *illegal_ip, char *public_ip, conf *conf) +int dingding_warning(char *illegal_ip, char *public_ip, conf * conf) { FILE *fp; - if ((fp = fopen("libcurl_ding.log", "wt+")) == NULL){ + char temp[64]; + char jsonObj[BUFFER]; + + memset(jsonObj, 0, BUFFER); + memset(temp, 0, 64); + strcpy(temp, public_ip); + temp[strlen(public_ip) - 1] = '\0'; + + if ((fp = fopen("libcurl_ding.log", "wt+")) == NULL) { return 1; } - + CURL *curl; CURLcode res; @@ -95,22 +108,20 @@ int dingding_warning(char *illegal_ip, char *public_ip, conf *conf) if (curl == NULL) { return 1; } - - char jsonObj[BUFFER] = "{ \ + + #define JSIN "{ \ \"msgtype\": \"text\", \ \"text\": { \ - \"content\": \"Alert @PHONE 主机PUBLIC 非法主机IP被封禁! Warning!\" \ + \"content\": \"Alert @%s 服务器地址:%s,封禁非法入侵主机:%s\" \ }, \ \"at\": { \ - \"atMobiles\": [\"PHONE\"], \ + \"atMobiles\": [\"%s\"], \ \"isAtAll\": false \ } \ - }"; + }" - strReplaceAll(jsonObj, "IP", illegal_ip); - strReplaceAll(jsonObj, "PHONE", conf->PHONE); - strReplaceAll(jsonObj, "PUBLIC", public_ip); - //printf("%s\n", jsonObj); + sprintf(jsonObj, JSIN, conf->PHONE, temp, illegal_ip, conf->PHONE); + printf("%s\n", jsonObj); struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Accept: application/json"); @@ -125,28 +136,31 @@ int dingding_warning(char *illegal_ip, char *public_ip, conf *conf) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj); curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); - + res = curl_easy_perform(curl); curl_easy_cleanup(curl); curl_global_cleanup(); fclose(fp); - + return res; } // 邮件告警 -int mail_warning(char *illegal_ip, char *public_ip) +int mail_warning(char *illegal_ip, char *public_ip, conf * conf) { FILE *fp = NULL; char buff[BUFFER]; - char text[BUFFER] = "echo \"主机:HOST, 禁止IP访问!\" |"; + char text[BUFFER]; + char temp[64]; memset(buff, 0, BUFFER); - strReplaceAll(text, "IP", illegal_ip); - strReplaceAll(text, "HOST", public_ip); + memset(text, 0, BUFFER); + memset(temp, 0, 64); - strcat(text, " mail -s \"System ban IP\" 1605227279@qq.com"); + strcpy(temp, public_ip); + temp[strlen(public_ip) - 1] = '\0'; + sprintf(text, "echo \"主机:%s, 禁止%s访问\" | mail -s \"System ban IP\" %s", temp, illegal_ip, conf->RECV_MAIL); if (NULL == (fp = popen(text, "r"))) { perror("popen text"); @@ -163,29 +177,30 @@ int mail_warning(char *illegal_ip, char *public_ip) } // 第三方邮箱告警 -int QQ_mail_warning(char *illegal_ip, char *public_ip, conf *conf) +int QQ_mail_warning(char *illegal_ip, char *public_ip, conf * conf) { - - char string[BUFFER+(sizeof(QQMAIL))]; - char text[BUFFER] = "主机:HOST, 禁止IP访问"; - - strReplaceAll(text, "IP", illegal_ip); - strReplaceAll(text, "HOST", public_ip); - - memset(string, 0, BUFFER+(sizeof(QQMAIL))); - - sprintf(string, QQMAIL, conf->SEND_QQ, conf->QQMAIL_KEY, conf->RECV_MAIL, text); - - system(string); - - return 0; + char string[BUFFER + (sizeof(QQMAIL))]; + char text[BUFFER]; + char temp[32]; + + memset(string, 0, BUFFER + (sizeof(QQMAIL))); + memset(text, 0, BUFFER); + memset(temp, 0, 32); + + strcpy(temp, public_ip); + temp[strlen(public_ip) - 1] = '\0'; + + sprintf(text, "主机:%s, 禁止%s访问", temp, illegal_ip); + sprintf(string, QQMAIL, conf->RECV_MAIL, text); + + return system(string); } // 封禁非法IP -int rule(conf *conf) +int rule(conf * conf) { FILE *fp, *fc; - + //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]; @@ -241,7 +256,7 @@ int rule(conf *conf) strcat(splice_command, "\n"); } } - printf("%s", splice_command); // 打印所有非法IP + printf("%s", splice_command); // 打印所有非法IP // 拼接命令 sprintf(awk, AWK, conf->REFUSE_NUMBER); @@ -250,54 +265,53 @@ int rule(conf *conf) 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'; // 去除回车 + 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) // 钉钉告警 + if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警 { dingding_warning(buffer, public_ip, conf); sleep(3); } - - if (conf->IS_MAIL == 1) // 邮件告警 + + if (conf->IS_MAIL == 1) // 邮件告警 { - mail_warning(buffer, public_ip); + mail_warning(buffer, public_ip, conf); sleep(3); } - - if (conf->IS_QQMAIL == 1) // 邮件告警 + + if (conf->IS_QQMAIL == 1) // 邮件告警 { QQ_mail_warning(buffer, public_ip, conf); sleep(3); } - + /* - // 调用命令下发规则 - if ((fc = popen(iptables, "r")) == NULL) { - perror("popen iptables"); - return 1; - } - */ - + // 调用命令下发规则 + 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 destIp; - inet_pton(AF_INET, buffer, &destIp); - iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, 0, destIp, NULL, NULL, "DROP", NULL, 1); - + 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); + } } @@ -317,28 +331,49 @@ static void sig_child(int signo) int stat; // 处理僵尸进程 while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) ; - + return; } +static int get_executable_path(char *processdir, char *processname, int len) +{ + char *filename; + if (readlink("/proc/self/exe", processdir, len) <= 0) + return -1; + filename = strrchr(processdir, '/'); + if (filename == NULL) + return -1; + ++filename; + strcpy(processname, filename); + *filename = '\0'; + return (int)(filename - processdir); +} + int main(int argc, char *argv[], char **env) { - conf *conf = (struct CONF *)malloc(sizeof(struct CONF)); - read_conf("rhost.conf", conf); - //ptintf_conf(conf); + char path[BUFFER] = { 0 }; + char executable_filename[BUFFER] = { 0 }; + (void)get_executable_path(path, executable_filename, sizeof(path)); - memset(public_ip, 0, BUFFER); - get_public_ip(public_ip); + strcat(executable_filename, ".conf"); + strcat(path, executable_filename); + + + conf *conf = (struct CONF *)malloc(sizeof(struct CONF)); + read_conf(path, conf); + //ptintf_conf(conf); + + // 新版本获取公网IP + public_ip = GET_PUBLIC_IP(conf->PUBLIC_IP); + //printf("%s", public_ip); signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 - if (0 == strcmp(conf->DAEMON, "on")) - { + if (0 == strcmp(conf->DAEMON, "on")) { goto goto_daemon; } - if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) - { + if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) { goto_daemon: if (daemon(1, 1)) // 守护进程 { @@ -351,16 +386,13 @@ goto_daemon: sleep(conf->TIME); } - } - else - { + } else { rule(conf); } - free_conf(conf); free(conf); - + free(public_ip); + return 0; } - diff --git a/rhost.conf b/rhost.conf index 13b007b..86bb32b 100644 --- a/rhost.conf +++ b/rhost.conf @@ -2,7 +2,9 @@ global { DAEMON = "off"; // on开启后台运行,off不开启 TIME = "60"; // 睡眠时间 - REFUSE_NUMBER = 5; // 拒绝攻击次数 + PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP + + REFUSE_NUMBER = 3; // 拒绝攻击次数 IS_MAIL = 0; // 开启邮件告警 @@ -11,7 +13,5 @@ global { DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK IS_QQMAIL = 0; // 开启QQ邮箱告警 - SEND_QQ = "1605227279"; // 发送者QQ - QQMAIL_KEY = "caczsjchvyibiabe"; // 发送者QQ密钥 - RECV_MAIL = "1605227279"; // 接收者QQ + RECV_MAIL = "1605227279@qq.com"; // 接收者QQ } diff --git a/rhost.h b/rhost.h index 38ad78a..83c863a 100644 --- a/rhost.h +++ b/rhost.h @@ -13,7 +13,6 @@ #include #include - #define CENTOS_SYSTEM 1 #define DEBISN_SYSTEM 2 #define UNKNOWN_SYSTEM 3 @@ -31,12 +30,10 @@ #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 "qqMail -l smtp.qq.com -p 25 -f %s -e %s -q NIUYULING -r %s@QQ.COM -n NIUYULING -s \"System ban IP\" -t \"%s\"" +#define QQMAIL "email -r %s -s \"System ban IP\" -t \"%s\"" - -extern void read_conf(char *filename, conf *configure); +extern void read_conf(char *filename, conf * configure); extern void free_conf(conf * conf); -extern void ptintf_conf(conf *conf); +extern void ptintf_conf(conf * conf); - -#endif \ No newline at end of file +#endif