denyhosts/nginx.c
2024-05-22 11:36:50 +08:00

157 lines
4.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "nginx.h"
#define EVENT_SIZE (sizeof(struct inotify_event))
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
#define INITIAL_BUFFER_SIZE 8192
void nginx_iptc(char *ip)
{
unsigned int srcIp;
inet_pton(AF_INET, ip, &srcIp);
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
}
int IP_location(char *string, conf *config)
{
char *area = NULL;
char *xdb_path = "ip2region.xdb";
char *p = strchr(string, ' ');
char IP[64];
memset(IP, 0, 64);
char *t = _time();
char nginx_region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
char NGINX_REGION_LIST_COPY[config->NGINX_REGION_LIST_LEN + 1];
memset(NGINX_REGION_LIST_COPY, 0, config->NGINX_REGION_LIST_LEN + 1);
memcpy(NGINX_REGION_LIST_COPY, config->NGINX_REGION_LIST, config->NGINX_REGION_LIST_LEN); // 复制配置字符串split_string()会改变原数据
split_string(NGINX_REGION_LIST_COPY, " ", nginx_region_list);
// IP 地理位置获取
if ((p - string) > 0) {
memmove(IP, string, p - string);
} else {
printf("Invalid IP string format.\n");
return -1;
}
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;
}
}
area = ip2region(xdb_path, IP);
if (area == NULL) {
printf("ip2region解析地域错误\n");
return -1;
}
my_printf("IP地址:%s, %s\n", IP, area);
//printf("%s, %s\n", config->NGINX_LOG_FILE, config->NGINX_REGION_LIST);
if (config->NGINX == 1) // 开启Nginx防御
{
if (isregion(area, nginx_region_list) == 1) { // 返回1表示在白名单列表
printf(RED "%s Nginx Ip Address: %s, 属于地域白名单: %s\n" COLOR_NONE, t, IP, area);
} else {
my_printf(RED "%s Nginx 封禁 Ip Address: %s, 地址: %s!!!\n" COLOR_NONE, t, IP, area);
nginx_iptc(IP);
}
}
return 0;
}
int nginx_read_log(const char *filename, conf *p)
{
int fd = open(p->NGINX_LOG_FILE, O_RDONLY);
if (fd == -1) {
perror("open");
return -1;
}
// Move to the end of the file
if (lseek(fd, 0, SEEK_END) == -1) {
perror("lseek");
close(fd);
return -1;
}
int inotify_fd = inotify_init();
if (inotify_fd < 0) {
perror("inotify_init");
close(fd);
return -1;
}
int wd = inotify_add_watch(inotify_fd, p->NGINX_LOG_FILE, IN_MODIFY);
if (wd == -1) {
perror("inotify_add_watch");
close(inotify_fd);
close(fd);
return -1;
}
char buffer[EVENT_BUF_LEN];
// Set the file descriptor to non-blocking mode
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl F_GETFL");
inotify_rm_watch(inotify_fd, wd);
close(inotify_fd);
close(fd);
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl F_SETFL");
inotify_rm_watch(inotify_fd, wd);
close(inotify_fd);
close(fd);
return -1;
}
// Initial dynamic buffer allocation
size_t buffer_size = INITIAL_BUFFER_SIZE;
char *read_buf = alloca(buffer_size);
if (!read_buf) {
perror("alloca");
inotify_rm_watch(inotify_fd, wd);
close(inotify_fd);
close(fd);
return -1;
}
while (1) {
int length = read(inotify_fd, buffer, EVENT_BUF_LEN);
if (length < 0) {
perror("read");
break;
}
for (int i = 0; i < length;) {
struct inotify_event *event = (struct inotify_event *)&buffer[i];
if (event->mask & IN_MODIFY) {
int bytes_read;
while ((bytes_read = read(fd, read_buf, buffer_size - 1)) > 0) {
read_buf[bytes_read] = '\0';
IP_location(read_buf, p);
}
if (bytes_read == -1 && errno != EAGAIN) {
perror("read");
break;
}
}
i += EVENT_SIZE + event->len;
}
}
inotify_rm_watch(inotify_fd, wd);
close(inotify_fd);
close(fd);
return 0;
}