增加白名单支持,还未大量测试

This commit is contained in:
2025-07-24 15:05:03 +08:00
parent 62013fbab9
commit c27df40923
5 changed files with 156 additions and 31 deletions

View File

@@ -1,5 +1,7 @@
#include "cache.h"
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点
int cache_size = 0; // 当前缓存中的 IP 数量
@@ -88,7 +90,7 @@ void free_ip_cache()
cache_size = 0;
}
char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 };
// 添加一个 IP 到集合(如果已存在则不添加)
int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip)

View File

@@ -47,7 +47,7 @@ extern void add_ip_to_cache(const char *ip);
extern int is_ip_in_cache(const char *ip);
extern void free_ip_cache();
extern char cn_ip[MAXIPSET_][MAXIPLEN];
extern char (*cn_ip)[MAXIPLEN];
extern int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip);
extern int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip);
extern int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN]);

130
cap.c
View File

@@ -6,17 +6,22 @@
#include "leak_detector_c/leak_detector_c.h"
pcap_if_t *alldevs, *device;
pcap_t *handle; // 会话句柄
struct bpf_program fp; // 编译后的过滤器
pcap_t *handle; // 会话句柄
struct bpf_program fp; // 编译后的过滤器
pid_t pids[MAX_CHILDREN] = {-1}; // 子进程全局PID
#define SHM_SIZE 1024 // 共享内存大小
#define SHM_KEY 0124 // 共享内存键值
int shmid = -1;
int RULE_NAME_NUMBER = 0; // ipset 集合集合数
pid_t pids[MAX_CHILDREN] = {-1}; // 子进程全局PID
char *ip2region_area = NULL; // ip2region 解析结果
// 共享内存
#define SHM_SIZE (MAXIPSET_ * MAXIPLEN)
int shmid[3] = {-1};
char (*cn_ip)[MAXIPLEN] = NULL; // 用于存储国内 IP 地址
char (*whitelist_ip)[MAXIPLEN] = NULL; // 最终要这样定义
char *RULE_NAME = NULL; // 共享内存
int RULE_NAME_NUMBER = 0; // ipset 集合集合数
char *ip2region_area = NULL; // ip2region 解析结果
void Processing_IP_addresses(char *src_ip)
{
@@ -28,6 +33,15 @@ void Processing_IP_addresses(char *src_ip)
// 定义 Response 结构体
Response response;
if (1 == is_ip_in_set(whitelist_ip, src_ip)) {
_printf(RED "IP:%s 白名单IP, 跳过!\n" REDEND, src_ip);
//printf("%s %d\n", whitelist_ip[0], cn_ip_len(whitelist_ip));
return;
}
// 如果 IP 地址已在缓存中且未过期,则跳过查询
if (is_ip_in_cache(src_ip)) {
_printf(RED "IP:%s 已在缓存中,跳过查询\n" REDEND, src_ip);
@@ -37,7 +51,7 @@ void Processing_IP_addresses(char *src_ip)
// 如果ipset规则已经存在则跳过查询
snprintf(ipset_query_command, sizeof(ipset_query_command), "ipset test %s %s 2>/dev/null", RULE_NAME, src_ip);
if (system(ipset_query_command) == 0) {
//_printf(RED "Ipset 规则内已经存在 %s\n" REDEND, src_ip);
_printf(RED "Ipset 规则内已经存在 %s\n" REDEND, src_ip);
return;
}
@@ -67,13 +81,13 @@ void Processing_IP_addresses(char *src_ip)
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 = CurlGetIpArea(src_ip);
@@ -136,6 +150,8 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
// INET_ADDRSTRLEN: 缓冲区的长度
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
Processing_IP_addresses(src_ip);
return;
@@ -161,6 +177,16 @@ void usage()
exit(0);
}
void detach_and_delete_shm(void *addr, int shmid, int delete_flag) {
if (addr && addr != (void *)-1) {
shmdt(addr);
}
if (delete_flag && shmid >= 0) {
shmctl(shmid, IPC_RMID, NULL);
}
}
void cleanup_(int signum)
{
@@ -178,10 +204,9 @@ void cleanup_(int signum)
}
// 释放共享内存
if (RULE_NAME != NULL) {
shmdt(RULE_NAME);
shmctl(shmid, IPC_RMID, NULL);
}
detach_and_delete_shm(RULE_NAME, shmid[0], 1);
detach_and_delete_shm(whitelist_ip, shmid[1], 1);
detach_and_delete_shm(cn_ip, shmid[2], 1);
// 在程序结束时,清理缓存链表
free_ip_cache();
@@ -195,7 +220,8 @@ void cleanup_(int signum)
// 清理
pcap_freecode(&fp);
pcap_freealldevs(alldevs); // 释放设备列表
//pcap_close(handle); // 关闭会话句柄
if (handle)
pcap_close(handle);
// 退出主进程
exit(0);
@@ -203,6 +229,30 @@ void cleanup_(int signum)
return;
}
void *create_and_attach_shm(const char *path, int proj_id, size_t size, int *shmid_out) {
key_t key = ftok(path, proj_id);
if (key == -1) {
perror("ftok");
exit(1);
}
int shmid = shmget(key, size, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
void *addr = shmat(shmid, NULL, 0);
if (addr == (void *)-1) {
perror("shmat");
exit(1);
}
if (shmid_out) *shmid_out = shmid;
return addr;
}
int main(int argc, char **argv)
{
atexit(report_mem_leak);
@@ -284,17 +334,24 @@ int main(int argc, char **argv)
}
// 创建共享内存
shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
RULE_NAME = (char *)create_and_attach_shm("/tmp", 'A', 1024, &shmid[0]);
whitelist_ip = (char (*)[MAXIPLEN])create_and_attach_shm("/tmp", 'B', SHM_SIZE, &shmid[1]);
cn_ip = (char (*)[MAXIPLEN])create_and_attach_shm("/tmp", 'C', SHM_SIZE, &shmid[2]);
// 连接共享内存到进程地址空间
RULE_NAME = (char *)shmat(shmid, NULL, 0);
if (RULE_NAME == (char *)-1) {
perror("shmat");
exit(1);
// 读取白名单
if (1 == file_exists_access("whitelist.txt")) {
int line_count = 0;
int result = read_file_to_array("whitelist.txt", whitelist_ip, &line_count);
if (result != 0) {
fprintf(stderr, "Failed to read file with error code: %d\n", result);
return 1;
}
for (int i = 0; i < line_count; i++) {
printf("Line %d: %s\n", i + 1, whitelist_ip[i]);
}
}
// 读取缓存
@@ -330,6 +387,21 @@ int main(int argc, char **argv)
if ( 0 == pids[0] ) // 子进程
{
while(1) {
if (1 == file_exists_access("whitelist.txt")) {
clear_ip_set(whitelist_ip); // 清空白名单IP集合
int line_count = 0;
int result = read_file_to_array("whitelist.txt", whitelist_ip, &line_count);
if (result != 0) {
fprintf(stderr, "Failed to read file with error code: %d\n", result);
return 1;
}
for (int i = 0; i < line_count; i++) {
printf("Line %d: %s\n", i + 1, whitelist_ip[i]);
}
}
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] != '\0') {
printf("%s ", cn_ip[i]);
@@ -342,7 +414,7 @@ int main(int argc, char **argv)
truncate_file("cn.txt"); // 清空文件
}
sleep(60); // 每 60 秒检查一次
sleep(10); // 每 60 秒检查一次
}
}
@@ -356,8 +428,8 @@ int main(int argc, char **argv)
_printf("创建 IPSet %s 失败\n", RULE_NAME);
}
while (1) {
//_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME);
while (1)
{
count = get_ip_count_in_ipset(RULE_NAME);
if (count >= 0) {
_printf("子进程当前 Ipset Rule 名 %s, 数量: %d \n", RULE_NAME, count);

View File

@@ -150,6 +150,53 @@ int add_ip_to_ipset(char *set_name, char *ip)
return 0; // 始终返回 0表示执行成功
}
// 向指定的 ipset 删除 IP
int del_ip_to_ipset(char *set_name, char *ip)
{
struct ipset *ipset = NULL;
struct ipset_session *session = NULL;
// 初始化 ipset 和 session
ipset = ipset_init();
if (!ipset) {
fprintf(stderr, "初始化 IPSet 失败\n");
return -1; // 返回 -1但不退出
}
ipset_load_types();
session = ipset_session(ipset);
if (!session) {
fprintf(stderr, "创建 IPSet 会话失败\n");
ipset_fini(ipset);
return -1; // 返回 -1但不退出
}
// 设置 IPSet 名称
if (ipset_session_data_set(session, IPSET_SETNAME, set_name) != 0) {
fprintf(stderr, "设置 IPSet 名称失败\n");
ipset_session_fini(session);
ipset_fini(ipset);
return -1; // 返回 -1但不退出
}
// 设置自定义错误和输出处理函数
if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) {
fprintf(stderr, "设置自定义打印函数失败。\n");
ipset_fini(ipset);
return -1;
}
// 将ip添加到集合
char *args[] = { "ipset", "del", set_name, ip, NULL };
if (ipset_parse_argv(ipset, 4, args) != 0) {
ipset_fini(ipset);
return -1;
}
ipset_session_fini(session);
ipset_fini(ipset);
return 0; // 始终返回 0表示执行成功
}
// 定义一个函数来清空指定名称的 ipset 集合
int flush_ipset(char *set_name)
{

4
whitelist.txt Normal file
View File

@@ -0,0 +1,4 @@
127.0.0.1
13.125.223.189
158.101.117.243
52.221.186.101