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..4f59739 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,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/libiptc.c b/libiptc.c index 6f7a9d1..48ba643 100644 --- a/libiptc.c +++ b/libiptc.c @@ -137,7 +137,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; diff --git a/rhost.c b/rhost.c index e6b4ad6..42060fd 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,70 +84,19 @@ 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) { FILE *fp; + 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; } @@ -95,22 +109,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"); @@ -140,12 +152,18 @@ int mail_warning(char *illegal_ip, char *public_ip) { 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); + + strcpy(temp, public_ip); + temp[strlen(public_ip)-1] = '\0'; + sprintf(text, "主机:%s, 禁止%s访问", temp, illegal_ip); strcat(text, " mail -s \"System ban IP\" 1605227279@qq.com"); if (NULL == (fp = popen(text, "r"))) { @@ -165,17 +183,22 @@ int mail_warning(char *illegal_ip, char *public_ip) // 第三方邮箱告警 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); - + char text[BUFFER]; + char temp[32]; + memset(string, 0, BUFFER+(sizeof(QQMAIL))); + memset(text, 0, BUFFER); + memset(temp, 0, 32); - sprintf(string, QQMAIL, conf->SEND_QQ, conf->QQMAIL_KEY, conf->RECV_MAIL, text); + strcpy(temp, public_ip); + temp[strlen(public_ip)-1] = '\0'; + + sprintf(text, "主机:%s, 禁止%s访问", temp, illegal_ip); + + sprintf(string, QQMAIL, conf->RECV_MAIL, text); + printf("%s\n", string); system(string); return 0; @@ -327,8 +350,12 @@ int main(int argc, char *argv[], char **env) read_conf("rhost.conf", conf); //ptintf_conf(conf); - memset(public_ip, 0, BUFFER); - get_public_ip(public_ip); + + // 新版本获取公网IP + public_ip = GET_PUBLIC_IP("http://ip.sb"); + + //printf("%s", public_ip); + signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 @@ -360,6 +387,7 @@ goto_daemon: free_conf(conf); free(conf); + free(public_ip); return 0; } diff --git a/rhost.conf b/rhost.conf index 13b007b..10b7e9c 100644 --- a/rhost.conf +++ b/rhost.conf @@ -2,7 +2,7 @@ global { DAEMON = "off"; // on开启后台运行,off不开启 TIME = "60"; // 睡眠时间 - REFUSE_NUMBER = 5; // 拒绝攻击次数 + REFUSE_NUMBER = 3; // 拒绝攻击次数 IS_MAIL = 0; // 开启邮件告警 @@ -10,8 +10,6 @@ global { PHONE = "15565979082"; // @的人手机号 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 + IS_QQMAIL = 1; // 开启QQ邮箱告警 + RECV_MAIL = "1605227279@qq.com"; // 接收者QQ } diff --git a/rhost.h b/rhost.h index 38ad78a..ed63421 100644 --- a/rhost.h +++ b/rhost.h @@ -31,7 +31,7 @@ #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);