diff --git a/Makefile b/Makefile index 5c96863..db50bf8 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ CROSS_COMPILE ?= CC := $(CROSS_COMPILE)gcc STRIP := $(CROSS_COMPILE)strip CFLAGS += -g -Wall -Iip2region -LIBS = -BIN := a.out +LIBS = -static +BIN := denyip # 使用shell命令获取库的链接选项 LIBPCAP := $(shell pkg-config --libs --static libpcap) diff --git a/a.out b/a.out deleted file mode 100644 index fb8d58f..0000000 Binary files a/a.out and /dev/null differ diff --git a/cap.h b/cap.h index 5c04d32..7a20ef0 100644 --- a/cap.h +++ b/cap.h @@ -18,7 +18,6 @@ #include #include "ip2region/ip2region.h" -#include "qqwry/qqwry.h" #define RED "\033[31m" #define REDEND "\033[0m" diff --git a/cap.o b/cap.o index da9de13..5358400 100644 Binary files a/cap.o and b/cap.o differ diff --git a/denyip b/denyip index 9b725cd..1afe21b 100644 Binary files a/denyip and b/denyip differ diff --git a/main.c b/main.c deleted file mode 100644 index 804818e..0000000 --- a/main.c +++ /dev/null @@ -1,317 +0,0 @@ -#include "main.h" - -char IPSET_LIST[256] = {0}; - -void denyip_help() -{ - puts(" DenyIp"); - puts("Linux system firewall, reject non-Chinese IP"); - puts("Email: aixiao@aixiao.me"); - puts("Version: 0.1"); - puts("Usage: ./denyip [-i eth0|-h|-?] [start|stop] "); - puts("Options:"); - puts(" stop Enable firewall rules"); - puts(" start Disable firewall rules"); - - puts("Parameters:"); - puts(" -h|? Help info "); - puts(" -i interface name"); - puts(""); - puts(""); - - exit(0); -} - -/* 处理僵尸进程 */ -void sigchld_handler(int signal) -{ - while (waitpid(-1, NULL, WNOHANG) > 0) ; -} - -void kill_tcpdump_processes() -{ - int result = system("pkill tcpdump"); // 用 pkill 命令终止所有 tcpdump 进程 - if (result == -1) { - perror("Failed to kill tcpdump processes"); - } - - return ; -} - -// 进程重启功能 -void restart_process(pid_t pid1, pid_t pid2, char *argv[]) -{ - // 发送 SIGTERM 信号终止两个子进程 - kill(pid1, SIGTERM); - kill(pid2, SIGTERM); - - // 等待子进程完全退出 - waitpid(pid1, NULL, 0); - waitpid(pid2, NULL, 0); - - // 终止 tcpdump 进程 - kill_tcpdump_processes(); - - // 使用 execvp 重新启动程序自身 - printf("重启进程...\n"); - execvp(argv[0], argv); // 重新启动程序 - perror("execvp failed"); // 如果 execvp 出错 - exit(EXIT_FAILURE); - - return ; -} - -void cleanup_(int signum) -{ - int r; - printf("Received signal %d, cleaning up...\n", signum); - - // 终止子进程 - if (pid1 > 0) { - kill(pid1, SIGTERM); - } - if (pid2 > 0) { - kill(pid2, SIGTERM); - } - - // 终止所有 tcpdump 进程 - r = system("pkill tcpdump"); - if (r == 0) { - puts("pkill tcpdump"); - } - - // 退出主进程 - exit(0); - - return ; -} - -int main(int argc, char *argv[]) -{ - signal(SIGCHLD, sigchld_handler); // 防止子进程变成僵尸进程 - - // 主进程设置 - //prctl(PR_SET_PDEATHSIG, SIGTERM); - - // 注册 SIGTERM 信号处理函数 - signal(SIGTERM, cleanup_); - - char interface[BUFFER] = { 0 }; - strcpy(interface, "eth0"); - - int r; - - // 参数处理 - if (argc == 2) { - if (0 == strcmp(argv[1], "start")) { - if ((r = system("iptables -A INPUT -p tcp -m set --match-set root src -j DROP")) == -1) { - puts("\"iptables -A INPUT -p tcp -m set --match-set root src -j DROP\" Error!"); - } - exit(0); - } else if (0 == strcmp(argv[1], "stop")) { - if ((r = system("iptables -D INPUT -p tcp -m set --match-set root src -j DROP")) == -1) { - puts("\"iptables -D INPUT -p tcp -m set --match-set root src -j DROP\" Error!"); - } - exit(0); - } else if (0 == strcmp(argv[1], "-h")) { - denyip_help(); - } else if (0 == strcmp(argv[1], "-?")) { - denyip_help(); - } - } - if (argc == 3) { - if (0 == strcmp(argv[1], "-i")) { - strcpy(interface, argv[2]); - } - } - // 判断运行用户禁止非root用户运行 - if (geteuid() == 0) { - ; - } else { - printf("This process is not running as root.\n"); - printf("\n"); - exit(-1); - } - - // 判断网卡是否存在 - char command_ifconfig[BUFFER + 20] = { 0 }; - snprintf(command_ifconfig, BUFFER + 20, "ifconfig %s", interface); - // 判断必要命令是否存在 - if (command_exists(command_ifconfig)) { - ; - } else { - puts("The network card does not exist!"); - exit(-1); - } - - // 后台运行 - if (daemon(1, 1)) { - perror("daemon"); - return -1; - } - - // 进程优先级 - if (-1 == (nice_(-20))) - perror("nice_"); - - // 哈希集合 - if ((r = system("ipset create root hash:ip > /dev/null 2>&1")) != -1) { - ; - } - - // 判断必要命令是否存在 - if (command_exists("which tcpdump")) { - ; - } else { - r = system("yum -y install tcpdump > /dev/null 2>&1"); - r = system("apt -y install tcpdump > /dev/null 2>&1"); - } - - - // 子进程 - pid1 = fork(); // 创建子进程 - if (pid1 == 0) { - while (1) { - - FILE *fp = popen("ipset list root | grep \"Number of entries\" | cut -d : -f 2 | xargs", "r"); - char line[BUFFER] = { 0 }; - while (fgets(line, sizeof(line), fp) != NULL) { - line[strcspn(line, "\n")] = '\0'; - } - - if (atoi(line) >= MAXIPSET) { - r = system("ipset flush root"); - } - - printf("%s\n", line); - pclose(fp); - sleep(3); - } - } - - // 子进程 - pid2 = fork(); // 创建子进程 - if (pid2 == 0) { - // 缓冲区用于存储每行的输出 - char line[BUFFER]; - // 要执行的命令 - char command_tcpdump[BUFFER + 256] = { 0 }; - snprintf(command_tcpdump, BUFFER + 256, "tcpdump -i %s -n 'tcp' | awk '{print $3}' | cut -d '.' -f 1-4", interface); - - // 地域白名单 - char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; - char qqwry_region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; - char _REGION_LIST_COPY[BUFFER] = { 0 }; - char QQWRY_REGION_LIST_COPY[BUFFER] = { 0 }; - - if (access(xdb_path, F_OK) == -1) { // 判断 ip2region 地址定位库是否存在 - xdb_path = "ip2region/ip2region.xdb"; - if (access(xdb_path, F_OK) == -1) { - printf("ip2region.xdb DOESN'T EXIST!\n"); - return -1; - } - } - - // 打开管道来执行命令 - FILE *fp = popen(command_tcpdump, "r"); - if (fp == NULL) { - perror("popen failed"); - return 1; - } - - // 逐行读取命令输出 - while (fgets(line, sizeof(line), fp) != NULL) { - line[strcspn(line, "\n")] = '\0'; - - if (is_valid_ip(line)) { - - char *qqwry_region = qqwry_(line); - if (qqwry_region == NULL) { - printf("qqwry 解析地域错误\n"); - continue; - } - - char *area = ip2region(xdb_path, line); - if (area == NULL) { - printf("ip2region 解析地域错误\n"); - continue; - } - - // 取环境变量 - const char *REGION_ENV = getenv("REGION"); - if (REGION_ENV != NULL) { - printf("REGION: %s\n", REGION_ENV); - strcpy(_REGION_LIST_COPY, REGION_ENV); - strcpy(QQWRY_REGION_LIST_COPY, REGION_ENV); - } else { - strcpy(_REGION_LIST_COPY, "局域网 内网 中国 "); - strcpy(QQWRY_REGION_LIST_COPY, "局域网 内网 中国 "); - } - //printf("REGION_LIST : %s\n", _REGION_LIST_COPY); - - split_string(QQWRY_REGION_LIST_COPY, " ", qqwry_region_list); // 分割后存储在 qqwry_region_list - if (isregion(qqwry_region, qqwry_region_list) == 1) { // 返回1表示在白名单列表 - ; - } else { - split_string(_REGION_LIST_COPY, " ", _region_list); - if (isregion(area, _region_list) == 1) { // 返回1表示在白名单列表 - ; - } else { - char ipquery_command[BUFFER + 100] = { 0 }; - snprintf(ipquery_command, BUFFER + 100, "./IP_region_query/ipquery %s", line); - FILE *fp = popen(ipquery_command, "r"); - if (fp == NULL) { - perror("popen failed"); - return 1; - } - - // 创建足够大的缓冲区来存储命令输出 - char buffer[1024 * 2]; // 2KB 缓冲区 - size_t bytesRead = fread(buffer, 1, sizeof(buffer) - 1, fp); - buffer[bytesRead] = '\0'; - - pclose(fp); - sleep(1); - - char *p = strstr(buffer, "中国"); - if (p == NULL) { - printf("%s %s", line, buffer); - - char command_ipset[BUFFER + 256] = { 0 }; - snprintf(command_ipset, sizeof(command_ipset), "ipset add root %s > /dev/null 2>&1", line); - int r = system(command_ipset); - if (r == -1) { - perror("system command failed"); - } - } - } - } - free(qqwry_region); - free(area); - - } else { // 是正确IP - printf("%s is not a valid IPv4 address.\n", line); - } - } // while - - // 关闭管道 - pclose(fp); - } - - - // 父进程 主进程循环,检查子进程运行情况 - int iteration = 0; - while (1) { - iteration++; - - if (iteration >= 3600*3) { - iteration = 0; - printf("准备重启进程...\n"); - restart_process(pid1, pid2, argv); - } - - sleep(1); // 每次检查间隔1秒 - } - - return 0; -} diff --git a/main.h b/main.h deleted file mode 100644 index f006f2c..0000000 --- a/main.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef MAIN_H -#define MAIN_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ip2region.h" -#include "qqwry.h" -#include "common.h" - -#define RED "\033[31m" -#define RESET "\033[0m" -#define WHITELIST_IP_NUM 1024 -#define MAXIPSET 65534 - - -char *xdb_path = "ip2region.xdb"; -pid_t pid1, pid2; // 保存子进程的 PID - -#endif diff --git a/main.o b/main.o deleted file mode 100644 index c951df2..0000000 Binary files a/main.o and /dev/null differ diff --git a/qqwry/main.c b/qqwry/main.c deleted file mode 100644 index b4b190a..0000000 --- a/qqwry/main.c +++ /dev/null @@ -1,18 +0,0 @@ -# -#include -#include -#include "qqwry.h" - -int main() -{ - char *qqwry_region = qqwry_("qqwry.dat", "1.1.1.1"); - if (qqwry_region == NULL) { - printf("qqwry 解析地域错误\n"); - } - puts(qqwry_region); - - free(qqwry_region); - return 0; - - -} diff --git a/qqwry/qqwry.c b/qqwry/qqwry.c deleted file mode 100644 index e543060..0000000 --- a/qqwry/qqwry.c +++ /dev/null @@ -1,367 +0,0 @@ - -#include "qqwry.h" - -ip_data ip_defaults = {.parent_data = NULL,.child_data = NULL,.index_size = 7,.isp = 1 }; - -int qqwry_init(char *file) -{ - int buff; - - ip_defaults.fp = fopen(file, "r"); - if (ip_defaults.fp == NULL) { - fprintf(stderr, "failed to open %s\n", file); - return -1; - } - - readvalue(4, &buff); //first 4 bytes represents the offset of first index - ip_defaults.first_item = buff; - readvalue(4, &buff); - ip_defaults.last_item = buff; - ip_defaults.item_number = (ip_defaults.last_item - ip_defaults.first_item) / ip_defaults.index_size; - - return 0; -} - -int qqwry_match(char *pattern, char *subject) -{ - regex_t regex; - int reti, ret; - char msgbuf[100]; - - /* Compile regular expression */ - reti = regcomp(®ex, pattern, 0); - if (reti) { - fprintf(stderr, "Could not compile regex\n"); - return 0; - } - - /* Execute regular expression */ - reti = regexec(®ex, subject, 0, NULL, 0); - if (!reti) { - ret = 1; - } else if (reti == REG_NOMATCH) { - ret = 0; - } else { - regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); - fprintf(stderr, "Regex match failed: %s\n", msgbuf); - ret = 0; - } - - /* Free memory allocated to the pattern buffer by regcomp() */ - regfree(®ex); - return ret; -} - -iconv_t initialize_iconv(const char *target, const char *src) -{ - // 创建转换描述符 - iconv_t iconvDesc = iconv_open(target, src); - - // 检查 iconv_open 是否成功 - if (iconvDesc == (iconv_t) - 1) { - // 如果失败,打印错误信息并返回 NULL - fprintf(stderr, "Error: Conversion from '%s' to '%s' is not available.\n", src, target); - return (iconv_t) NULL; - } - // 成功时返回 iconv_t 描述符 - return iconvDesc; -} - -int gbk2utf8(char *utf8_str, char *gbk_str) -{ - iconv_t iconvDesc = initialize_iconv("UTF-8//TRANSLIT//IGNORE", "GBK"); - size_t iconv_value, len, utf8len; - //int len_start; - - len = strlen(gbk_str) + 1; - if (!len) { - fprintf(stderr, "iconvISO2UTF8: input String is empty."); - return -1; - } - - /* Assign enough space to put the UTF-8. */ - utf8len = 3 * len; - if (!utf8_str) { - fprintf(stderr, "iconvISO2UTF8: Calloc failed."); - return -1; - } - - iconv_value = iconv(iconvDesc, &gbk_str, &len, &utf8_str, &utf8len); - /* Handle failures. */ - if (iconv_value == (size_t)-1) { - switch (errno) { - /* See "man 3 iconv" for an explanation. */ - case EILSEQ: - fprintf(stderr, "iconv failed: Invalid multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len); - break; - case EINVAL: - fprintf(stderr, "iconv failed: Incomplete multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len); - break; - case E2BIG: - fprintf(stderr, "iconv failed: No more room, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len); - break; - default: - fprintf(stderr, "iconv failed, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len); - } - return -1; - } - - if (iconv_close(iconvDesc) != 0) { - fprintf(stderr, "libicon close failed: %s", strerror(errno)); - return -1; - } - - return utf8len; -} - -int readbyte(int size, int offset, int *buff) -{ - int count; - int nbytes = 1; - *buff = 0; - if (ip_defaults.fp != NULL) { - //if offset is negative,keep the current offset unchanged - if (offset >= 0) { - qqwry_seek(offset); - } else { - int curr_pos = ftell(ip_defaults.fp); - fseek(ip_defaults.fp, curr_pos, SEEK_SET); - } - - if ((count = fread(buff, nbytes, size, ip_defaults.fp)) != size) { - return -1; - } - return count; - } - return -1; -} - -int readvalue(unsigned int size, int *buff) -{ - return readbyte(size, -1, buff); -} - -void set_ip_range(unsigned int offset) -{ - readbyte(4, offset, (int *)(&ip_defaults.startip)); - //skip 3 bytes to read the next ip - qqwry_forward(3); - readvalue(4, (int *)(&ip_defaults.endip)); -} - -void qqwry_seek(int offset) -{ - fseek(ip_defaults.fp, offset, SEEK_SET); -} - -void qqwry_forward(unsigned int byte) -{ - fseek(ip_defaults.fp, byte, SEEK_CUR); -} - -void qqwry_back(unsigned int byte) -{ - int currPos = ftell(ip_defaults.fp); - qqwry_seek(currPos - byte); -} - -char *long2ip(int ip) -{ - // 分配16字节内存用于存储IP字符串 - char *ip_str = malloc(16 * sizeof(char)); - - if (ip_str == NULL) { - // 如果内存分配失败,返回NULL - fprintf(stderr, "Memory allocation failed\n"); - return NULL; - } - // 将IP转换为字符串 - snprintf(ip_str, 16, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); - - return ip_str; -} - -unsigned int ip2long(char *ip) -{ - int nip = 0, tmp = 0, step = 24; - char *copy = strdup(ip); - char *token = strtok(copy, "."); - - while (token) { - tmp = (unsigned int)atoi(token); - tmp <<= step; - nip += tmp; - step -= 8; - token = strtok(NULL, "."); - } - free(copy); - return nip; -} - -int search_record(char *ip) -{ - int numeric_ip = ip2long(ip); - int low = 0; - int high = ip_defaults.item_number; - return binary_search(low, high, numeric_ip); -} - -int binary_search(int low, int high, int ip) -{ - unsigned int mid, offset, startip, endip; - - if (low <= high) { - mid = low + (high - low) / 2; - offset = round(ip_defaults.first_item + mid * ip_defaults.index_size); - set_ip_range(offset); - startip = ip_defaults.startip; - endip = ip_defaults.endip; - if (ip >= startip && ip <= endip) { - return offset; - } - //if ip is below the lower limit, decrease the upper limit - if (ip < startip) { - return binary_search(low, mid - 1, ip); - } - //if ip is above the lower limit, increase the lower limit - return binary_search(mid + 1, high, ip); - } - return ip_defaults.last_item; -} - -static char *get_string() -{ - unsigned int buff = 0; - char *str = realloc(NULL, sizeof(char)); - char *tmp; - int i = 0, c = 0; - - if ((c = readvalue(1, (int *)(&buff))) != 1) { - return NULL; - } - - for (i = 0; buff != 0; i++) { - str[i] = buff; - tmp = realloc(str, (sizeof(char)) * (i + 2)); - str = tmp; - readvalue(1, (int *)(&buff)); - } - str[i] = '\0'; - return str; -} - -static char *get_child_data() -{ - unsigned int flag, offset; - readvalue(1, (int *)(&flag)); - if (flag == 0) { //no child data - return 0; - } else if (flag == 1 || flag == 2) { // redirection for child data - readvalue(3, (int *)(&offset)); - qqwry_seek(offset); - return get_string(); - } - // no redirection for child data - qqwry_back(1); - return get_string(); -} - -int convert_data(char *parent_data, char *child_data) -{ - ip_defaults.parent_data = malloc(strlen(parent_data) * 3); //in utf8,one chinese character could consume up to 3 bytes - gbk2utf8(ip_defaults.parent_data, parent_data); - ip_defaults.child_data = malloc(strlen(child_data) * 3); - gbk2utf8(ip_defaults.child_data, child_data); - - if (qqwry_match("移动", ip_defaults.child_data)) { - ip_defaults.isp = 0x03; - } else if (qqwry_match("联通", ip_defaults.child_data)) { - ip_defaults.isp = 0x02; - } else { - ip_defaults.isp = 0x01; - } - free(parent_data); - free(child_data); - - return 0; -} - -int qqwry_redirect(int bytes) -{ - int redirect_offset; - readvalue(bytes, &redirect_offset); - qqwry_seek(redirect_offset); - return redirect_offset; -} - -int get_data(int offset) -{ //get record data - int flag, redirect_offset; - char *parent_data, *child_data; - readbyte(1, offset + 4, &flag); //get the flag value to see if the data is stored elsewhere - - if (flag == 1) { //this means we should look elsewhere for both - redirect_offset = qqwry_redirect(3); //read 3 bytes to get a new offset and redirect there - readvalue(1, &flag); - if (flag == 2) { - // child data is elsewhere - qqwry_redirect(3); - parent_data = get_string(); - qqwry_seek(redirect_offset + 4); - child_data = get_child_data(); - } else { // no redirection for parent data - qqwry_back(1); - parent_data = get_string(); - child_data = get_child_data(); - } - } else if (flag == 2) { //redirection for only parent - qqwry_redirect(3); - parent_data = get_string(); - qqwry_seek(offset + 8); - child_data = get_child_data(); - } else { // no redirection for both parent and child - qqwry_back(1); - parent_data = get_string(); - child_data = get_string(); - } - - convert_data(parent_data, child_data); - - return 0; -} - -int get_location(char *ip) -{ - //offset is the address where the ip is found. first 4 bytes is the start ip address of the ip range and the following 3 bytes is the offset pointing to the actual record data; - unsigned int offset = search_record(ip); - unsigned int tmp_offset; - qqwry_seek(offset + 4); // skip 4 byte to get the offset value pointing to record data - readvalue(3, (int *)(&tmp_offset)); // the offset pointing to the data - get_data(tmp_offset); - - return 0; -} - -char *qqwry_(char *dat, char *ip) -{ - qqwry_init(dat); - - get_location(ip); - //printf("%s-%s %d\n", ip_defaults.parent_data, ip_defaults.child_data, ip_defaults.isp); - //printf("QQWRY %s %s-%s\n", ip, ip_defaults.parent_data, ip_defaults.child_data); - - // 计算拼接后的字符串所需的长度 - size_t len = strlen(ip_defaults.parent_data) + strlen(ip_defaults.child_data) + 2; // +2 for the hyphen and null terminator - char *result = malloc(len); - - if (result) { - // 拼接字符串,格式为 "parent_data-child_data" - snprintf(result, len, "%s-%s", ip_defaults.parent_data, ip_defaults.child_data); - } - - free(ip_defaults.parent_data); - free(ip_defaults.child_data); - fclose(ip_defaults.fp); - - return result; -} diff --git a/qqwry/qqwry.dat b/qqwry/qqwry.dat deleted file mode 100644 index 977f115..0000000 Binary files a/qqwry/qqwry.dat and /dev/null differ diff --git a/qqwry/qqwry.h b/qqwry/qqwry.h deleted file mode 100644 index 6c0995c..0000000 --- a/qqwry/qqwry.h +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - FILE *fp; - unsigned int index_size; - unsigned int first_item, last_item; - unsigned int item_number, startip, endip, curr_data_offset; - char *parent_data, *child_data; - int isp; -} ip_data; - -int search_record(char *ip); -int binary_search(int low, int high, int ip); -int readbyte(int size, int offset, int *buff); -int readvalue(unsigned int size, int *buff); -void qqwry_seek(int offset); -void qqwry_forward(unsigned int byte); -void qqwry_back(unsigned int byte); -int get_location(char *ip); -int gbk2utf8(char *utf8_str, char *gbk_str); - -extern char *qqwry_(char *dat, char *ip); diff --git a/qqwry/qqwry.o b/qqwry/qqwry.o deleted file mode 100644 index fdb87a4..0000000 Binary files a/qqwry/qqwry.o and /dev/null differ