删除不必要文件

This commit is contained in:
2024-10-28 15:52:58 +08:00
parent b97b4b212e
commit d439dbc26d
13 changed files with 2 additions and 763 deletions

View File

@@ -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)

BIN
a.out

Binary file not shown.

1
cap.h
View File

@@ -18,7 +18,6 @@
#include <string.h>
#include "ip2region/ip2region.h"
#include "qqwry/qqwry.h"
#define RED "\033[31m"
#define REDEND "\033[0m"

BIN
cap.o

Binary file not shown.

BIN
denyip

Binary file not shown.

317
main.c
View File

@@ -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;
}

27
main.h
View File

@@ -1,27 +0,0 @@
#ifndef MAIN_H
#define MAIN_h
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/resource.h>
#include <signal.h>
#include <sys/prctl.h>
#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

BIN
main.o

Binary file not shown.

View File

@@ -1,18 +0,0 @@
#
#include <stdio.h>
#include <stdlib.h>
#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;
}

View File

@@ -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(&regex, pattern, 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
return 0;
}
/* Execute regular expression */
reti = regexec(&regex, subject, 0, NULL, 0);
if (!reti) {
ret = 1;
} else if (reti == REG_NOMATCH) {
ret = 0;
} else {
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
ret = 0;
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(&regex);
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;
}

Binary file not shown.

View File

@@ -1,31 +0,0 @@
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <math.h>
#include <stdio.h>
#include <iconv.h>
#include <errno.h>
#include <regex.h>
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);

Binary file not shown.