This commit is contained in:
2025-01-16 16:32:39 +08:00
parent a79a59bd97
commit a3712fde22
5 changed files with 133 additions and 97 deletions

View File

@@ -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.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.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":"","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"}

152
cap.c
View File

@@ -3,7 +3,6 @@
#include "libipset.h" #include "libipset.h"
#include "libcurl.h" #include "libcurl.h"
pcap_if_t *alldevs, *device; pcap_if_t *alldevs, *device;
pcap_t *handle; // 会话句柄 pcap_t *handle; // 会话句柄
struct bpf_program fp; // 编译后的过滤器 struct bpf_program fp; // 编译后的过滤器
@@ -30,6 +29,68 @@ struct ip_cache_node {
struct ip_cache_node *next; // 指向下一个节点 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 是否已在缓存中并是否过期 // 检查 IP 是否已在缓存中并是否过期
int is_ip_in_cache(const char *ip) int is_ip_in_cache(const char *ip)
@@ -132,12 +193,7 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
// 定义 Response 结构体 // 定义 Response 结构体
Response response; Response response;
int r = 0;
//char *t = _time();
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
//_printf("%s\n", src_ip);
// 如果 IP 地址已在缓存中且未过期,则跳过查询 // 如果 IP 地址已在缓存中且未过期,则跳过查询
if (is_ip_in_cache(src_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; 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); ip2region_area = ip2region("ip2region/ip2region.xdb", src_ip);
if (ip2region_area == NULL) { if (ip2region_area == NULL) {
@@ -179,25 +254,17 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
_printf("缓存 IP 数 %d\n", cache_size); _printf("缓存 IP 数 %d\n", cache_size);
} }
add_ip_to_cache(src_ip); // 添加到缓存
char *p = curl_get_area(src_ip); char *p = curl_get_area(src_ip);
//puts(p);
if (parse_json_to_struct(p, &response) == 0) { // 解析 JSON 到结构体 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 (NULL == strstr(response.continent_country, "中国")) { // 这时是国外IP
if (p1 == NULL) {
_printf(RED "%s %s\n" REDEND, src_ip, response.continent_country); _printf(RED "%s %s\n" REDEND, src_ip, response.continent_country);
r = add_ip_to_ipset(RULE_NAME, src_ip); add_ip_to_ipset(RULE_NAME, src_ip);
//_printf("add_ip_to_ipset() return %d\n", r); } else { // 这时是国内IP
add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存
_printf("IP: %s 离线库为国外, API 判断为国内, 标记为已处理!!!\n", src_ip);
} }
} else { } else {
@@ -206,34 +273,9 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
free(p); 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); if (ip2region_area != NULL) {
command_result = NULL;
} else {
;
}
if (command_result != NULL)
free(command_result);
*/
}
if (ip2region_area != NULL)
{
free(ip2region_area); free(ip2region_area);
ip2region_area = NULL; ip2region_area = NULL;
} }
@@ -292,7 +334,6 @@ void cleanup_(int signum)
pcap_freealldevs(alldevs); // 释放设备列表 pcap_freealldevs(alldevs); // 释放设备列表
//pcap_close(handle); // 关闭会话句柄 //pcap_close(handle); // 关闭会话句柄
// 退出主进程 // 退出主进程
exit(0); exit(0);
@@ -327,8 +368,7 @@ int main(int argc, char **argv)
{ 0, 0, 0, 0 } { 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) { switch (opt) {
case 'd': case 'd':
if (daemon(1, 1)) { if (daemon(1, 1)) {
@@ -346,17 +386,13 @@ int main(int argc, char **argv)
if (strcmp(optarg, "start") == 0) { if (strcmp(optarg, "start") == 0) {
memset(Ipset_Command, 0, BUFFER); memset(Ipset_Command, 0, BUFFER);
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
snprintf(Ipset_Command, sizeof(Ipset_Command), 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);
"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); system(Ipset_Command);
exit(0); exit(0);
} else if (strcmp(optarg, "stop") == 0) { } else if (strcmp(optarg, "stop") == 0) {
memset(Ipset_Command, 0, BUFFER); memset(Ipset_Command, 0, BUFFER);
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
snprintf(Ipset_Command, sizeof(Ipset_Command), 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);
"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); system(Ipset_Command);
exit(0); exit(0);
} else { } else {
@@ -377,7 +413,6 @@ int main(int argc, char **argv)
} }
} }
// 创建共享内存 // 创建共享内存
shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666); shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666);
if (shmid < 0) { if (shmid < 0) {
@@ -392,7 +427,6 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
pid = fork(); // 创建子进程 pid = fork(); // 创建子进程
if (pid == 0) // 子进程 if (pid == 0) // 子进程
{ {
@@ -404,8 +438,7 @@ int main(int argc, char **argv)
_printf("创建 IPSet %s 失败\n", RULE_NAME); _printf("创建 IPSet %s 失败\n", RULE_NAME);
} }
while (1) while (1) {
{
//_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME); //_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME);
count = get_ip_count_in_ipset(RULE_NAME); count = get_ip_count_in_ipset(RULE_NAME);
@@ -437,7 +470,6 @@ int main(int argc, char **argv)
} }
} }
// 查找可用的网络设备 // 查找可用的网络设备
if (pcap_findalldevs(&alldevs, errbuf) == -1) { if (pcap_findalldevs(&alldevs, errbuf) == -1) {
fprintf(stderr, "无法找到设备: %s\n", errbuf); fprintf(stderr, "无法找到设备: %s\n", errbuf);

3
cap.h
View File

@@ -28,4 +28,7 @@
#define _VERSION "0.2" #define _VERSION "0.2"
#endif #endif

Binary file not shown.

View File

@@ -6,7 +6,7 @@
int main() int main()
{ {
// 执行查询并添加到缓存 // 执行查询并添加到缓存
char *area = ip2region("ip2region.xdb", "1.1.1.1"); char *area = ip2region("ip2region.xdb", "199.45.154.152");
if (area == NULL) { if (area == NULL) {
return -1; return -1;
} }