#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); } static int Handle_IP(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); } } if (t) free(t); 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'; Handle_IP(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; }