diff --git a/IP_region_query/response.json b/IP_region_query/response.json index 092c372..c55bc31 100644 --- a/IP_region_query/response.json +++ b/IP_region_query/response.json @@ -6,3 +6,4 @@ {"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.6"} {"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.7"} {"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.8"} +{"code":"Success","data":{"continent":"亚洲","country":"中国","zipcode":"999077","owner":"Censys, Inc.","isp":"Censys, Inc.","adcode":"810000","prov":"中国香港","city":"中国香港","district":""},"ip":"199.45.154.152"} diff --git a/cap.c b/cap.c index e1dd178..9c96a9c 100644 --- a/cap.c +++ b/cap.c @@ -3,33 +3,94 @@ #include "libipset.h" #include "libcurl.h" - pcap_if_t *alldevs, *device; -pcap_t *handle; // 会话句柄 -struct bpf_program fp; // 编译后的过滤器 +pcap_t *handle; // 会话句柄 +struct bpf_program fp; // 编译后的过滤器 -pid_t pid = -1; // 子进程全局PID +pid_t pid = -1; // 子进程全局PID -#define SHM_SIZE 1024 // 共享内存大小 -#define SHM_KEY 0124 // 共享内存键值 +#define SHM_SIZE 1024 // 共享内存大小 +#define SHM_KEY 0124 // 共享内存键值 int shmid = -1; -int RULE_NAME_NUMBER = 0; // ipset 集合集合数 -char *RULE_NAME = NULL; // 共享内存 -char *ip2region_area = NULL; // ip2region 解析结果 -char *command_result = NULL; // 执行命令的结果 +int RULE_NAME_NUMBER = 0; // ipset 集合集合数 +char *RULE_NAME = NULL; // 共享内存 +char *ip2region_area = NULL; // ip2region 解析结果 +char *command_result = NULL; // 执行命令的结果 -#define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟) -#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址 -struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点 -int cache_size = 0; // 当前缓存中的 IP 数量 +#define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟) +#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址 +struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点 +int cache_size = 0; // 当前缓存中的 IP 数量 // 定义链表结构,用于缓存 IP 地址 struct ip_cache_node { - char ip[INET_ADDRSTRLEN]; // 存储 IP 地址 - time_t timestamp; // 记录缓存时间 - struct ip_cache_node *next; // 指向下一个节点 + char ip[INET_ADDRSTRLEN]; // 存储 IP 地址 + time_t timestamp; // 记录缓存时间 + struct ip_cache_node *next; // 指向下一个节点 }; +#define MAXIPSET_ 100 +#define MAXIPLEN 32 +char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 }; + +// 添加一个 IP 到集合(如果已存在则不添加) +int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip) +{ + if (ip == NULL || strlen(ip) >= MAXIPLEN) { + return -1; // 错误:无效的 IP 地址或过长 + } + // 检查是否已存在 + for (int i = 0; i < MAXIPSET_; i++) { + if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) { + return 1; // IP 已存在,返回特殊代码 + } + } + // 查找空位并添加 + for (int i = 0; i < MAXIPSET_; i++) { + if (cn_ip[i][0] == '\0') { // 检查是否为空 + strcpy(cn_ip[i], ip); + return 0; // 成功添加 + } + } + return -1; // 错误:集合已满 +} + +// 判断给定的IP地址是否在集合中 +int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip) +{ + if (ip == NULL) { + return 0; // 错误:无效的IP地址指针 + } + for (int i = 0; i < MAXIPSET_; i++) { + if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) { + return 1; // 找到匹配的IP地址 + } + } + return 0; // 没有找到匹配的IP地址 +} + +// 计算集合中非空IP的数量 +int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN]) +{ + int count = 0; // 用于计数非空IP + for (int i = 0; i < MAXIPSET_; i++) { + if (cn_ip[i][0] != '\0') { + count++; // 非空IP计数 + } + } + return count; +} + +// 安全的清理IP地址集合,将所有位置置为空字符串 +void clear_ip_set(char cn_ip[MAXIPSET_][MAXIPLEN]) +{ + if (cn_ip == NULL) { + return; // 如果指针无效,则直接返回 + } + for (int i = 0; i < MAXIPSET_; i++) { + memset(cn_ip[i], '\0', MAXIPLEN); + } +} // 检查 IP 是否已在缓存中并是否过期 int is_ip_in_cache(const char *ip) @@ -117,14 +178,14 @@ void free_ip_cache() // 回调函数,在捕获到每个数据包时调用 void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { - int ethernet_header_len = 14; - struct ip *ip_header = (struct ip *)(packet + ethernet_header_len); - char src_ip[INET_ADDRSTRLEN] = { 0 }; + int ethernet_header_len = 14; + struct ip *ip_header = (struct ip *)(packet + ethernet_header_len); + char src_ip[INET_ADDRSTRLEN] = { 0 }; // 地域白名单 - char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; - char _REGION_LIST[BUFFER] = { 0 }; - const char *REGION_ENV = NULL; + char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; + char _REGION_LIST[BUFFER] = { 0 }; + const char *REGION_ENV = NULL; char ipset_query_command[256] = { 0 }; //char ip_query_command[256] = { 0 }; @@ -132,12 +193,7 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char // 定义 Response 结构体 Response response; - int r = 0; - //char *t = _time(); - inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN); - //_printf("%s\n", src_ip); - // 如果 IP 地址已在缓存中且未过期,则跳过查询 if (is_ip_in_cache(src_ip)) { @@ -152,6 +208,25 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char return; } + if (1 == is_ip_in_set(cn_ip, src_ip)) { + _printf(RED "IP:%s 已经标记为国内,跳过!!!\n" REDEND, src_ip); + + for (int i = 0; i < MAXIPSET_; i++) { + if (cn_ip[i][0] != '\0') { + printf("%s ", cn_ip[i]); + } + } + + if (cn_ip_len(cn_ip) >= 100) { // 清理集合 + clear_ip_set(cn_ip); + } + + printf("cn_ip_len(cn_ip): %d\n", cn_ip_len(cn_ip)); + + + return; + } + // 执行查询并添加到缓存 ip2region_area = ip2region("ip2region/ip2region.xdb", src_ip); if (ip2region_area == NULL) { @@ -172,32 +247,24 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char if (isregion(ip2region_area, _region_list) == 1) { // 返回1表示在白名单列表 ; } else { - + if (cache_size < MAX_CACHE_SIZE) // 缓存IP数不够预备设定值 { sleep(1); _printf("缓存 IP 数 %d\n", cache_size); } + add_ip_to_cache(src_ip); // 添加到缓存 char *p = curl_get_area(src_ip); - //puts(p); - if (parse_json_to_struct(p, &response) == 0) { // 解析 JSON 到结构体 - // 输出解析结果 - /* - printf("Code: %s\n", response.code); - printf("IP: %s\n", response.ip); - printf("Continent: %s\n", response.data.continent); - printf("Country: %s\n", response.data.country); - printf("ISP: %s\n", response.data.isp); - printf("Region: %s\n", response.data.region); - */ - - char *p1 = strstr(response.continent_country, "中国"); - if (p1 == NULL) { + if (parse_json_to_struct(p, &response) == 0) { // 解析 JSON 到结构体 + + if (NULL == strstr(response.continent_country, "中国")) { // 这时是国外IP _printf(RED "%s %s\n" REDEND, src_ip, response.continent_country); - r = add_ip_to_ipset(RULE_NAME, src_ip); - //_printf("add_ip_to_ipset() return %d\n", r); + add_ip_to_ipset(RULE_NAME, src_ip); + } else { // 这时是国内IP + add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存 + _printf("IP: %s 离线库为国外, API 判断为国内, 标记为已处理!!!\n", src_ip); } } else { @@ -206,38 +273,13 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char free(p); - - /* - //go 执行命令方法 - snprintf(ip_query_command, sizeof(ip_query_command), "./IP_region_query/ipquery %s", src_ip); - command_result = _execute_command(ip_query_command); - if (command_result != NULL) { - add_ip_to_cache(src_ip); // 添加 IP 到缓存 - - char *p = strstr(command_result, "中国"); - if (p == NULL) { - _printf(RED "%s %s\n" REDEND, src_ip, command_result); - r = add_ip_to_ipset(RULE_NAME, src_ip); - _printf("add_ip_to_ipset() return %d\n", r); - } - - free(command_result); - command_result = NULL; - } else { - ; - } - - if (command_result != NULL) - free(command_result); - */ } - - if (ip2region_area != NULL) - { + + if (ip2region_area != NULL) { free(ip2region_area); ip2region_area = NULL; } - return ; + return; } void usage() @@ -268,7 +310,7 @@ void cleanup_(int signum) if (pid > 0) { kill(pid, SIGTERM); } - + // 释放共享内存 if (RULE_NAME != NULL) { shmdt(RULE_NAME); @@ -292,7 +334,6 @@ void cleanup_(int signum) pcap_freealldevs(alldevs); // 释放设备列表 //pcap_close(handle); // 关闭会话句柄 - // 退出主进程 exit(0); @@ -304,11 +345,11 @@ int main(int argc, char **argv) // 注册 SIGTERM 信号处理函数 signal(SIGTERM, cleanup_); - int opt; - char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; // 错误缓冲区 - char protocol[] = "tcp"; - char interface[256] = "{ 0 }"; - char Ipset_Command[BUFFER] = { 0 }; + int opt; + char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; // 错误缓冲区 + char protocol[] = "tcp"; + char interface[256] = "{ 0 }"; + char Ipset_Command[BUFFER] = { 0 }; strcpy(interface, "eth0"); memset(&alldevs, 0, sizeof(alldevs)); @@ -327,8 +368,7 @@ int main(int argc, char **argv) { 0, 0, 0, 0 } }; - while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) - { + while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) { switch (opt) { case 'd': if (daemon(1, 1)) { @@ -346,17 +386,13 @@ int main(int argc, char **argv) if (strcmp(optarg, "start") == 0) { memset(Ipset_Command, 0, BUFFER); // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 - snprintf(Ipset_Command, sizeof(Ipset_Command), - "for n in $(seq 0 %d); do iptables -A INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done", - MAXIPSET_RULT_NAME_NUM); + snprintf(Ipset_Command, sizeof(Ipset_Command), "for n in $(seq 0 %d); do iptables -A INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done", MAXIPSET_RULT_NAME_NUM); system(Ipset_Command); exit(0); } else if (strcmp(optarg, "stop") == 0) { memset(Ipset_Command, 0, BUFFER); // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 - snprintf(Ipset_Command, sizeof(Ipset_Command), - "for n in $(seq 0 %d); do iptables -D INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done", - MAXIPSET_RULT_NAME_NUM); + snprintf(Ipset_Command, sizeof(Ipset_Command), "for n in $(seq 0 %d); do iptables -D INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done", MAXIPSET_RULT_NAME_NUM); system(Ipset_Command); exit(0); } else { @@ -377,7 +413,6 @@ int main(int argc, char **argv) } } - // 创建共享内存 shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666); if (shmid < 0) { @@ -392,25 +427,23 @@ int main(int argc, char **argv) exit(1); } - pid = fork(); // 创建子进程 if (pid == 0) // 子进程 { - - int count = 0; + + int count = 0; snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER); if (create_ipset(RULE_NAME) != 0) { _printf("创建 IPSet %s 失败\n", RULE_NAME); } - while (1) - { + while (1) { //_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME); count = get_ip_count_in_ipset(RULE_NAME); if (count >= 0) { - _printf("子进程当前 Ipset Rule 名 %s, 数量: %d\n", RULE_NAME, count); + _printf("子进程当前 Ipset Rule 名 %s, 数量: %d \n", RULE_NAME, count); if (count >= MAXIPSET && RULE_NAME_NUMBER <= MAXIPSET_RULT_NAME_NUM) // RULE_中的IP数量不超过MAXIPSET,并且集合不能超过 MAXIPSET_RULT_NAME_NUM 个 { RULE_NAME_NUMBER++; @@ -436,7 +469,6 @@ int main(int argc, char **argv) sleep(9); // 每 3 秒检查一次 } } - // 查找可用的网络设备 if (pcap_findalldevs(&alldevs, errbuf) == -1) { diff --git a/cap.h b/cap.h index 121155b..352a1ef 100644 --- a/cap.h +++ b/cap.h @@ -28,4 +28,7 @@ #define _VERSION "0.2" + + + #endif diff --git a/ip2region/a.out b/ip2region/a.out index 8afbd08..0d66ff2 100644 Binary files a/ip2region/a.out and b/ip2region/a.out differ diff --git a/ip2region/main.c b/ip2region/main.c index b53eb39..9efbb3b 100644 --- a/ip2region/main.c +++ b/ip2region/main.c @@ -6,7 +6,7 @@ int main() { // 执行查询并添加到缓存 - char *area = ip2region("ip2region.xdb", "1.1.1.1"); + char *area = ip2region("ip2region.xdb", "199.45.154.152"); if (area == NULL) { return -1; }