diff --git a/Makefile b/Makefile index 8736236..0ace1f3 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ CROSS_COMPILE ?= CC := $(CROSS_COMPILE)gcc -CFLAGS += -g -Wall -LIB += -lcurl +CFLAGS += -g -Wall +LIB += -lcurl -lip4tc OBG = rhost -all: rhost.o +all: conf.o rhost.o libiptc.o $(CC) $(CFLAGS) $^ -o $(OBG) $(LIB) clean: diff --git a/conf.c b/conf.c new file mode 100644 index 0000000..eda3da1 --- /dev/null +++ b/conf.c @@ -0,0 +1,232 @@ +#include "conf.h" + +int8_t copy_new_mem(char *src, int src_len, char **dest) +{ + *dest = (char *)malloc(src_len + 1); + if (*dest == NULL) + return 1; + memcpy(*dest, src, src_len); + *((*dest) + src_len) = '\0'; + + return 0; +} + +/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */ +static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end) +{ + + char *p, *pn, *lineEnd; + ; + int val_len; + + while (1) { + if (content == NULL) + return NULL; + + for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ; + if (*content == '\0') + return NULL; + *var = content; + pn = strchr(content, '\n'); + p = strchr(content, '='); + if (p == NULL) { + if (pn) { + content = pn + 1; + continue; + } else + return NULL; + } + content = p; + //将变量以\0结束 + for (p--; *p == ' ' || *p == '\t'; p--) ; + *(p + 1) = '\0'; + //值的首地址 + for (content++; *content == ' ' || *content == '\t'; content++) ; + if (*content == '\0') + return NULL; + //双引号引起来的值支持换行 + if (*content == '"') { + *val_begin = content + 1; + *val_end = strstr(*val_begin, "\";"); + if (*val_end != NULL) + break; + } else + *val_begin = content; + *val_end = strchr(content, ';'); + if (pn && *val_end > pn) { + content = pn + 1; + continue; + } + break; + } + + if (*val_end) { + **val_end = '\0'; + val_len = *val_end - *val_begin; + lineEnd = *val_end; + } else { + val_len = strlen(*val_begin); + *val_end = lineEnd = *val_begin + val_len; + } + *val_end = *val_begin + val_len; + //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin); + return lineEnd; +} + +static void parse_global_module(char *content, conf * conf) +{ + char *var, *val_begin, *val_end, *lineEnd; + int val_begin_len; + + 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; + } + + 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; + } + + content = strchr(lineEnd + 1, '\n'); + } +} + +/* 在buff中读取模块(global http https httpdns httpudp)内容 */ +static char *read_module(char *buff, const char *module_name) +{ + int len; + char *p, *p0; + + len = strlen(module_name); + p = buff; + while (1) { + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (strncasecmp(p, module_name, len) == 0) { + p += len; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (*p == '{') + break; + } + if ((p = strchr(p, '\n')) == NULL) + return NULL; + } + + if ((p0 = strchr(++p, '}')) == NULL) + return NULL; + return strndup(p, p0 - p); +} + +void read_conf(char *filename, conf * configure) +{ + char *buff, *global_content; + FILE *file; + long file_size; + int return_val; + + file = fopen(filename, "r"); + if (file == NULL) + perror("cannot open config file."); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + buff = (char *)alloca(file_size + 1); + if (buff == NULL) + perror("out of memory."); + rewind(file); + if (1 > (return_val = fread(buff, file_size, 1, file))) + perror("fread"); + fclose(file); + buff[file_size] = '\0'; + + if ((global_content = read_module(buff, "global")) == NULL) { + perror("read global module error"); + } + parse_global_module(global_content, configure); + free(global_content); +} + +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); + + return; +} + +void ptintf_conf(conf *conf) +{ + 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); + printf("%d\n", conf->IS_QQMAIL); + printf("%s\n", conf->SEND_QQ); + printf("%s\n", conf->QQMAIL_KEY); + printf("%s\n", conf->RECV_MAIL); +} diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..75ba8be --- /dev/null +++ b/conf.h @@ -0,0 +1,32 @@ +#ifndef CONF_H +#define CONF_H + +#include +#include +#include +#include +#include + +typedef struct CONF { + char *DAEMON; + int TIME; + + int REFUSE_NUMBER; + + 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 free_conf(conf * conf); +void ptintf_conf(conf *conf); + +#endif \ No newline at end of file diff --git a/conf.o b/conf.o new file mode 100644 index 0000000..baef531 Binary files /dev/null and b/conf.o differ diff --git a/denyhosts.sh b/denyhosts.sh index fdf6db2..a3ed4c2 100644 --- a/denyhosts.sh +++ b/denyhosts.sh @@ -6,41 +6,46 @@ # Time: 20170909 # +source /etc/profile + function init() { - send_mail=0; - pwd_path="/root"; + SEND_MAIL=0 + PWD_PATH="/root"; TIME=`date +"%Y%m%d%H%M"`; - log_file="${pwd_path}/${TIME}.log"; - email_address="1605227279@qq.com"; + LOG_FILE="${PWD_PATH}/${TIME}.log"; + EMAIL_ADDRESS="1605227279@qq.com"; + IPTABLES=$(which iptables) + + IPTABLES_SAVE=$(which iptables-save) } function run() { - echo "Read-Only Memory,ROM:" &>> ${log_file} - df -am &>> ${log_file} + echo "Read-Only Memory,ROM:" &>> ${LOG_FILE} + df -am &>> ${LOG_FILE} - echo "random access memory,RAM:" &>> ${log_file} - free -hl &>> ${log_file} + echo "random access memory,RAM:" &>> ${LOG_FILE} + free -hl &>> ${LOG_FILE} - echo "System process:" &>> ${log_file} - ps -axjf &>> ${log_file} + echo "System process:" &>> ${LOG_FILE} + ps -axwwjf &>> ${LOG_FILE} - echo "Network Connections" &>> ${log_file} - netstat -tnulp &>> ${log_file} + echo "Network Connections" &>> ${LOG_FILE} + netstat -tnulp &>> ${LOG_FILE} - echo "System SSH authorization information:" &>> ${log_file} - /root/denyhosts/rhost | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${log_file} + echo "System SSH authorization information:" &>> ${LOG_FILE} + /root/denyhosts/rhost | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${LOG_FILE} - /sbin/iptables-save > /root/ipv4tables + $IPTABLES_SAVE > /root/ipv4tables - echo "" &>> ${log_file} - echo "Iptables filter table" &>> ${log_file} - /sbin/iptables -L -n --line-numbers &>> ${log_file} - echo "" &>> ${log_file} + echo "" &>> ${LOG_FILE} + echo "Iptables filter table" &>> ${LOG_FILE} + $IPTABLES -L -n --line-numbers &>> ${LOG_FILE} + echo "" &>> ${LOG_FILE} - if test $send_mail = 1; then - mail -s "System Log" ${email_address} < ${log_file} - rm ${log_file} + if test $SEND_MAIL = 1; then + mail -s "System Log" ${EMAIL_ADDRESS} < ${LOG_FILE} + rm ${LOG_FILE} fi sync diff --git a/libiptc.c b/libiptc.c new file mode 100644 index 0000000..8e5c457 --- /dev/null +++ b/libiptc.c @@ -0,0 +1,209 @@ +#include "libiptc.h" + + +int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4) +{ + int r=1; + const struct ipt_entry *entry; + + for (entry = iptc_first_rule(chain, handle); entry; entry = iptc_next_rule(entry, handle)) { + iptc_get_target(entry, handle); + + char addr[33]; + memset(addr, 0, 33); + inet_ntop(AF_INET, &(entry->ip.dst), addr, sizeof(addr)); + printf("%s\n", addr); + if (0 == strcmp(ipv4, addr)) + { + r=0; + break; + } + + } + + return r; + +} + +int show_all_rule(char *ipv4) +{ + int r; + 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)) + { + if (chain != NULL && handle != NULL) { + iptc_get_policy(chain, &counter, handle); + } + + r = x_get_rule(chain, handle, ipv4); + if (r==0){ + break; + } + } + + return r; +} + +static u_int16_t parse_port(const char *port) +{ + return atoi(port); +} + +static void parse_ports(const char *portstring, u_int16_t * ports) +{ + char *buffer; + char *cp; + + buffer = strdup(portstring); + if ((cp = strchr(buffer, ':')) == NULL) + ports[0] = ports[1] = parse_port(buffer); + else { + *cp = '\0'; + cp++; + + ports[0] = buffer[0] ? parse_port(buffer) : 0; + ports[1] = cp[0] ? parse_port(cp) : 0xFFFF; + } + free(buffer); +} + +struct ipt_entry_match *get_match(const char *sports, const char *dports, unsigned int *nfcache, char *protocol) +{ + struct ipt_entry_match *match; + struct ipt_udp *udpinfo; + size_t size; + + 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); + + udpinfo = (struct ipt_udp *)match->data; + udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF; + //printf("sports=%s,dports=%s\n", sports, dports); + if (sports) { + *nfcache |= NFC_IP_SRC_PT; + parse_ports(sports, udpinfo->spts); + } + if (dports) { + *nfcache |= NFC_IP_DST_PT; + parse_ports(dports, udpinfo->dpts); + } + + 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) +{ + struct xtc_handle *handle; + struct ipt_entry *chain_entry; + struct ipt_entry_match *entry_match = NULL; + struct ipt_entry_target *entry_target; + ipt_chainlabel labelit; + long match_size; + int result = 0; + + chain_entry = (struct ipt_entry *)calloc(1, sizeof(*chain_entry)); + + if (src != 0) { + chain_entry->ip.src.s_addr = src; + chain_entry->ip.smsk.s_addr = 0xFFFFFFFF; + } + if (dest != 0) { + chain_entry->ip.dst.s_addr = dest; + chain_entry->ip.dmsk.s_addr = 0xFFFFFFFF; + } + + if (iniface) + strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ); + if (outiface) + strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ); + + chain_entry->ip.proto = protocol; + if (IPPROTO_UDP == protocol) + entry_match = get_match(srcports, destports, &chain_entry->nfcache, "udp"); + if (IPPROTO_TCP == protocol) + entry_match = get_match(srcports, destports, &chain_entry->nfcache, "tcp"); + + if (strcmp(target, "") == 0 || strcmp(target, IPTC_LABEL_ACCEPT) == 0 || strcmp(target, IPTC_LABEL_DROP) == 0 || strcmp(target, IPTC_LABEL_QUEUE) == 0 || strcmp(target, IPTC_LABEL_RETURN) == 0) { + size_t size; + 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); + } + if (entry_match) { + match_size = entry_match->u.match_size; + } else + match_size = 0; + + struct ipt_entry *tmp_ipt = chain_entry; + chain_entry = (struct ipt_entry *)realloc(chain_entry, sizeof(*chain_entry) + match_size + entry_target->u.target_size); + 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)); + free(chain_entry); + free(entry_target); + if (entry_match) + free(entry_match); + return 1; + } + + strncpy(labelit, chain, sizeof(ipt_chainlabel)); + //printf("Chain name:%s\n", chain); + result = iptc_is_chain(chain, handle); + if (!result) { + printf("libiptc error: Chain %s does not exist!\n", chain); + free(chain_entry); + free(entry_target); + if (entry_match) + 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); + free(entry_target); + if (entry_match) + free(entry_match); + return 1; + } + result = iptc_commit(handle); + if (!result) { + printf("libiptc error: Commit error, %s\n", iptc_strerror(errno)); + free(chain_entry); + free(entry_target); + if (entry_match) + free(entry_match); + return 1; + } + + + if (entry_match) + free(entry_match); + free(entry_target); + free(chain_entry); + + return 0; +} \ No newline at end of file diff --git a/libiptc.h b/libiptc.h new file mode 100644 index 0000000..3d56ab3 --- /dev/null +++ b/libiptc.h @@ -0,0 +1,38 @@ +#ifndef LIBIPTC_H +#define LIBIPTC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Source port. */ +#define NFC_IP_SRC_PT 0x0200 +/* Dest port. */ +#define NFC_IP_DST_PT 0x0400 + + +#ifndef IPT_MIN_ALIGN +#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry)) +#endif + +#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1)) + +#define IPTC_ENTRY_SIZE XT_ALIGN(sizeof(struct ipt_entry)) +#define IPTC_MATCH_SIZE XT_ALIGN(sizeof(struct ipt_entry_match) + sizeof(struct ipt_udp)) +#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); + +#endif diff --git a/libiptc.o b/libiptc.o new file mode 100644 index 0000000..db649b9 Binary files /dev/null and b/libiptc.o differ diff --git a/rhost b/rhost index 90f79e1..f181f44 100644 Binary files a/rhost and b/rhost differ diff --git a/rhost.c b/rhost.c index 27fcbab..7c510ae 100644 --- a/rhost.c +++ b/rhost.c @@ -1,40 +1,8 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define CENTOS_SYSTEM 1 -#define DEBISN_SYSTEM 2 -#define UNKNOWN_SYSTEM 3 +#include "conf.h" +#include "rhost.h" +#include "libiptc.h" -#define BUFFER 1024 -#define LONG_BUFFER 1024*100 -#define TOP_IP 10 -#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" - -#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 "iptables -I INPUT -s %s -j DROP" -#define IPTABLES_CHECK "iptables -C INPUT -s %s -j DROP" - -#define TIME 60 - -#define IS_DIND 1 -#define PHONE "155659790" -#define DING_CURL "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e" - -#define IS_MAIL 0 - -#define IS_QQMAIL 0 -#define QQMAIL "qqMail -l smtp.qq.com -p 25 -f 1605227279 -e caczsjchvyibi -q NIUYULING -r 1605227279@QQ.COM -n NIUYULING -s \"System ban IP\" -t \"%s\"" // 存储公网IP char public_ip[BUFFER]; @@ -112,8 +80,14 @@ int strReplaceAll(char *str, char *sub, char *replace) } // 钉钉告警 -int dingding_warning(char *illegal_ip, char *public_ip) +int dingding_warning(char *illegal_ip, char *public_ip, conf *conf) { + FILE *fp; + if ((fp = fopen("libcurl_ding.log", "wt+")) == NULL){ + + return 1; + } + CURL *curl; CURLcode res; @@ -135,28 +109,30 @@ int dingding_warning(char *illegal_ip, char *public_ip) }"; strReplaceAll(jsonObj, "IP", illegal_ip); - strReplaceAll(jsonObj, "PHONE", PHONE); + strReplaceAll(jsonObj, "PHONE", conf->PHONE); strReplaceAll(jsonObj, "PUBLIC", public_ip); - printf("%s\n", jsonObj); + //printf("%s\n", jsonObj); struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Accept: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "charset: utf-8"); - curl_easy_setopt(curl, CURLOPT_URL, DING_CURL); + curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 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; } @@ -188,17 +164,18 @@ int mail_warning(char *illegal_ip, char *public_ip) } // 第三方邮箱告警 -int QQ_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访问!"; + char text[BUFFER] = "主机:HOST, 禁止IP访问"; strReplaceAll(text, "IP", illegal_ip); strReplaceAll(text, "HOST", public_ip); memset(string, 0, BUFFER+(sizeof(QQMAIL))); - sprintf(string, QQMAIL, text); + + sprintf(string, QQMAIL, conf->SEND_QQ, conf->QQMAIL_KEY, conf->RECV_MAIL, text); system(string); @@ -206,10 +183,10 @@ int QQ_mail_warning(char *illegal_ip, char *public_ip) } // 封禁非法IP -int rule() +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))]; + 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))]; time_t timep; struct tm *tp; @@ -220,7 +197,7 @@ int rule() memset(buffer, 0, BUFFER); memset(awk, 0, BUFFER); memset(iptables, 0, BUFFER+(sizeof(IPTABLES))); - memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES))); + memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES_CHECK))); fp = NULL; fc = NULL; @@ -263,54 +240,63 @@ int rule() strcat(splice_command, "\n"); } } - printf("%s", splice_command); // 打印所有非法IP + printf("%s", splice_command); // 打印所有非法IP // 拼接命令 - sprintf(awk, AWK, TOP_IP); + 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'; // 去除回车 + buffer[strlen(buffer) - 1] = '\0'; // 去除回车 sprintf(iptables, IPTABLES, buffer); sprintf(iptables_check, IPTABLES_CHECK, buffer); - - if (0 != system(iptables_check)) // 判断是否存在规则, 不存在时再添加规则 + //if (0 != system(iptables_check)) // 判断是否存在规则, 不存在时再添加规则 + if (0 != show_all_rule(buffer)) { - if (IS_DIND == 1) // 钉钉告警 + if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警 { - dingding_warning(buffer, public_ip); + dingding_warning(buffer, public_ip, conf); sleep(3); } - if (IS_MAIL == 1) // 邮件告警 + if (conf->IS_MAIL == 1) // 邮件告警 { mail_warning(buffer, public_ip); sleep(3); } - if (IS_QQMAIL == 1) // 邮件告警 + if (conf->IS_QQMAIL == 1) // 邮件告警 { - QQ_mail_warning(buffer, public_ip); + QQ_mail_warning(buffer, public_ip, conf); sleep(3); } - + + /* if ((fc = popen(iptables, "r")) == NULL) { perror("popen iptables"); return 1; } + */ + + + // libiptc 库插入规则 + 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); + } } @@ -336,16 +322,23 @@ static void sig_child(int signo) int main(int argc, char *argv[], char **env) { + conf *conf = (struct CONF *)malloc(sizeof(struct CONF)); + read_conf("rhost.conf", conf); + //ptintf_conf(conf); + memset(public_ip, 0, BUFFER); get_public_ip(public_ip); - - signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 + if (0 == strcmp(conf->DAEMON, "on")) + { + goto goto_daemon; + } if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) { +goto_daemon: if (daemon(1, 1)) // 守护进程 { perror("daemon"); @@ -353,17 +346,20 @@ int main(int argc, char *argv[], char **env) } while (1) { - rule(); + rule(conf); - sleep(TIME); + sleep(conf->TIME); } } else { - rule(); + rule(conf); } + free_conf(conf); + free(conf); + return 0; } diff --git a/rhost.conf b/rhost.conf new file mode 100644 index 0000000..13b007b --- /dev/null +++ b/rhost.conf @@ -0,0 +1,17 @@ +global { + DAEMON = "off"; // on开启后台运行,off不开启 + TIME = "60"; // 睡眠时间 + + 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邮箱告警 + SEND_QQ = "1605227279"; // 发送者QQ + QQMAIL_KEY = "caczsjchvyibiabe"; // 发送者QQ密钥 + RECV_MAIL = "1605227279"; // 接收者QQ +} diff --git a/rhost.h b/rhost.h new file mode 100644 index 0000000..38ad78a --- /dev/null +++ b/rhost.h @@ -0,0 +1,42 @@ +#ifndef RHOST_H +#define RHOST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CENTOS_SYSTEM 1 +#define DEBISN_SYSTEM 2 +#define UNKNOWN_SYSTEM 3 + +#define BUFFER 1024 +#define LONG_BUFFER 1024*100 + +#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" + +#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 "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\"" + + +extern void read_conf(char *filename, conf *configure); +extern void free_conf(conf * conf); +extern void ptintf_conf(conf *conf); + + +#endif \ No newline at end of file diff --git a/rhost.o b/rhost.o index ab1531c..3d47e35 100644 Binary files a/rhost.o and b/rhost.o differ