#include "rhost.h" #include "libiptc.h" #include "libclamav.h" #include "clamscan.h" #include "ccronexpr.h" #include "nginx.h" #include "disk.h" #include "./cJSON/cJSON.h" #include "ip2region/ip2region.h" // CRON #define MAX_SECONDS 60 #define CRON_MAX_MINUTES 60 #define CRON_MAX_HOURS 24 #define CRON_MAX_DAYS_OF_WEEK 8 #define CRON_MAX_DAYS_OF_MONTH 32 #define CRON_MAX_MONTHS 12 #define INVALID_INSTANT ((time_t) -1) #define DATE_FORMAT "%Y-%m-%d_%H:%M:%S" #ifndef ARRAY_LEN #define ARRAY_LEN(x) sizeof(x)/sizeof(x[0]) #endif #ifdef CRON_TEST_MALLOC static int cronAllocations = 0; static int cronTotalAllocations = 0; static int maxAlloc = 0; void *cron_malloc(size_t n) { cronAllocations++; cronTotalAllocations++; if (cronAllocations > maxAlloc) { maxAlloc = cronAllocations; } return malloc(n); } void cron_free(void *p) { cronAllocations--; free(p); } #endif // CRON END // 自定义 printf 函数 void my_printf(const char *format, ...) { va_list args; va_start(args, format); // 打印到控制台 vprintf(format, args); va_end(args); // 结束对变参列表的处理 // 重新启动变参列表 va_start(args, format); // 打开日志文件(追加模式) FILE *log_file = fopen(LOG_FILE, "a"); if (log_file != NULL) { // 获取当前时间 time_t now = time(NULL); struct tm local_time; localtime_r(&now, &local_time); char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time); // 打印时间戳到日志文件 fprintf(log_file, "[%s] ", time_str); // 打印内容到日志文件 vfprintf(log_file, format, args); // 关闭日志文件 fclose(log_file); } else { perror("Unable to open log file"); } va_end(args); // 结束对变参列表的处理 } // 存储公网IP char *public_ip; struct MemoryStruct { char *memory; size_t size; }; // 计算字符串长度 int _strlen(char *str) { char *_p = NULL; if (str == NULL) return 0; _p = strchr(str, '\0'); if (_p == NULL) return 0; return _p - str; } static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; // 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小 char *ptr = realloc(mem->memory, mem->size + realsize + 1); if (ptr == NULL) { /* 内存不足! */ printf("not enough memory (realloc returned NULL)\n"); return 0; } mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } // 获取公网IP static char *GET_PUBLIC_IP(char *URL) { CURL *curl_handle; CURLcode res; struct curl_slist *headers = NULL; struct MemoryStruct chunk; chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */ chunk.size = 0; /* 此时没有数据 */ curl_global_init(CURL_GLOBAL_ALL); /* 初始化curl会话 */ curl_handle = curl_easy_init(); char *p = NULL; char *buff; p = strstr(URL, "-H"); if (p) { buff = (char *)alloca(p - URL + 1); if (buff == NULL) perror("out of memory."); memset(buff, 0, p - URL + 1); memcpy(buff, URL, (int)(p - URL - 1)); // 赋值header值 headers = curl_slist_append(headers, p + 3); // 设置header curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl_handle, CURLOPT_URL, buff); } else { /* 指定要获取的URL */ curl_easy_setopt(curl_handle, CURLOPT_URL, URL); } /* 将所有数据发送到此函数 */ //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); /* 将"chunk"结构传递给回调函数 */ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); //对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { //printf("%lu bytes retrieved\n", (unsigned long)chunk.size); //printf("%s", chunk.memory); ; } curl_easy_cleanup(curl_handle); curl_global_cleanup(); return chunk.memory; } // 解析Json char *process_json(char *buff, char *api) { char *area = NULL; int area_len = 0; char *p = NULL; if (buff == NULL) { return NULL; } cJSON *cjson_init = cJSON_Parse(buff); if (cjson_init == NULL) { perror("cJSON_Parse"); return NULL; } if ((p = strstr(api, "baidu")) != NULL) { // baidu Api int i; cJSON *data = cJSON_GetObjectItem(cjson_init, "data"); if (data != NULL) { for (i = 0; i < cJSON_GetArraySize(data); i++) { cJSON *svalue = cJSON_GetArrayItem(data, i); cJSON *location = cJSON_GetObjectItem(svalue, "location"); area_len = _strlen(location->valuestring); area = (char *)alloca(area_len + 1); if (area == NULL) perror("out of memory."); memset(area, 0, area_len + 1); snprintf(area, area_len + 1, "%s", location->valuestring); } } else { return NULL; } } else { cJSON_Delete(cjson_init); return NULL; } cJSON_Delete(cjson_init); return strdup(area); } // 检测系统 int check_system() { if (0 == access("/etc/debian_version", F_OK)) { return DEBISN_SYSTEM; } else if (0 == access("/etc/centos-release", F_OK)) { return CENTOS_SYSTEM; } return UNKNOWN_SYSTEM; } // 钉钉告警 int dingding_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf) { FILE *fp; char temp[64]; char jsonObj[BUFFER]; memset(jsonObj, 0, BUFFER); memset(temp, 0, 64); strcpy(temp, public_ip); temp[_strlen(public_ip) - 1] = '\0'; if ((fp = fopen("libcurl.log", "wt+")) == NULL) { return 1; } CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if (curl == NULL) { fclose(fp); return 1; } #define JSIN "{ \ \"msgtype\": \"text\", \ \"text\": { \ \"content\": \"Alert @%s 服务器地址:%s,封禁非法入侵主机:(%s%s)\" \ }, \ \"at\": { \ \"atMobiles\": [\"%s\"], \ \"isAtAll\": false \ } \ }" snprintf(jsonObj, BUFFER, JSIN, conf->PHONE, temp, ip, illegal_ip, conf->PHONE); printf("%s\n", jsonObj); struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Accept: application/json"); headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "charset: utf-8"); curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj); curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1"); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); res = curl_easy_perform(curl); curl_easy_cleanup(curl); curl_global_cleanup(); fclose(fp); return res; } // 邮件告警 int mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf) { FILE *fp = NULL; char buff[BUFFER]; char text[BUFFER]; char temp[64]; memset(buff, 0, BUFFER); memset(text, 0, BUFFER); memset(temp, 0, 64); strcpy(temp, public_ip); temp[_strlen(public_ip) - 1] = '\0'; snprintf(text, BUFFER, "echo \"主机:%s, 禁止(%s%s)访问\" | mail -s \"System ban IP\" %s", temp, ip, illegal_ip, conf->RECV_MAIL); if (NULL == (fp = popen(text, "r"))) { perror("popen text"); } while (fgets(buff, BUFFER, fp) != NULL) { buff[_strlen(buff) - 1] = '\0'; } if (NULL != fp) pclose(fp); return 0; } // 第三方邮箱告警 int QQ_mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf) { char string[BUFFER + (sizeof(QQMAIL)) + 1]; char text[BUFFER]; char temp[32]; memset(string, 0, BUFFER + (sizeof(QQMAIL)) + 1); memset(text, 0, BUFFER); memset(temp, 0, 32); strcpy(temp, public_ip); temp[_strlen(public_ip) - 1] = '\0'; snprintf(text, BUFFER, "主机:%s, 禁止(%s%s)访问!", temp, ip, illegal_ip); snprintf(string, BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL, conf->RECV_MAIL, text); return system(string); } // 第三方邮箱告警, 感染病毒邮件提醒 int QQ_mail_warning_Virus_files(char *local_ip, int Virus_number, conf *conf) { char *command; char *text; char temp[32]; command = (char *)alloca(BUFFER + (sizeof(QQMAIL)) + 1); text = (char *)alloca(BUFFER); memset(command, 0, BUFFER + (sizeof(QQMAIL)) + 1); memset(text, 0, BUFFER); memset(temp, 0, 32); strcpy(temp, local_ip); temp[_strlen(local_ip) - 1] = '\0'; snprintf(text, BUFFER, "Host:%s, Infected files: %d, Please handle!", temp, Virus_number); snprintf(command, BUFFER + BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL_Virus, conf->RECV_MAIL, text); return system(command); } // IP段白名单对比 int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM]) { int i; for (i = 1; i < WHITELIST_IP_NUM - 1; i++) { if (strcmp(whitelist_ip[i], "\0") == 0) // 如果字符串为空就跳出循环 { break; } if ((strncmp(client_ip, whitelist_ip[i], _strlen(whitelist_ip[i]))) == 0) // 对比client_ip长度, { return 1; } } return 0; } // 地域段白名单对比 int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM]) { int i; char *p; for (i = 1; i < WHITELIST_IP_NUM - 1; i++) { if (strcmp(region_list[i], "\0") == 0) // 如果字符串为空就跳出循环 { break; } //printf("%s %s\n", str, region_list[i]); // 在str中查找region_list[i] p = strstr(str, region_list[i]); if (p != NULL) { return 1; } } return 0; } char *_time() { char temp[BUFFER]; char *wday[] = { "0", "1", "2", "3", "4", "5", "6" }; time_t t; struct tm *p; time(&t); p = localtime(&t); // 取得当地时间 memset(temp, 0, BUFFER); snprintf(temp, BUFFER, "[%d/%02d/%02d %s %02d:%02d:%02d] ", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec); return strdup(temp); } // 封禁非法IP int rule(conf *conf) { char whitelist_ip[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; char region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; char REGION_LIST_COPY[conf->REGION_LIST_LEN + 1]; char IPV4_WHITE_LIST_COPY[conf->IPV4_WHITE_LIST_LEN + 1]; char p_two[2], *command, *splice_command, *temp, buffer[BUFFER], awk[BUFFER]; FILE *fp, *fc; time_t timep; struct tm *tp; long int ip_length = 1; fp = NULL; fc = NULL; timep = time(NULL); tp = localtime(&timep); memset(buffer, 0, BUFFER); memset(awk, 0, BUFFER); memset(p_two, 0, 2); char *t = NULL; t = _time(); if (DEBISN_SYSTEM == check_system()) // Debian 系统规则 { if (tp->tm_mday >= 10) { if ((fp = popen(GE_10, "r")) == NULL) { perror("GE_10"); return -1; } } else { if ((fp = popen(LE_10, "r")) == NULL) { perror("LE_10"); return -1; } } } else if (CENTOS_SYSTEM == check_system()) // Centos 7系统规则 { if (tp->tm_mday >= 10) { if ((fp = popen(CENTOS_GE_10, "r")) == NULL) { perror("CENTOS_GE_10"); return -1; } } else { if ((fp = popen(CENTOS_LE_10, "r")) == NULL) { perror("CENTOS_LE_10"); return -1; } } } else { return UNKNOWN_SYSTEM; } splice_command = (char *)malloc(ip_length); if (splice_command == NULL) { free(splice_command); return -1; } memset(splice_command, 0, ip_length); while (fgets(buffer, BUFFER, fp) != NULL) { char *new_splice_command; temp = strstr(buffer, "rhost"); sscanf(temp, "rhost=%64s", temp); if (atoi(strncpy(p_two, temp, 1)) > 0) { ip_length += _strlen(temp) + 1; new_splice_command = (char *)realloc(splice_command, ip_length + 32); if (new_splice_command == NULL) { free(splice_command); return -1; } splice_command = new_splice_command; //printf(RED"Hello World\n"COLOR_NONE); printf(RED "%s Illegal IP: %s\n" COLOR_NONE, t, temp); strcat(splice_command, temp); strcat(splice_command, "\n"); } } //printf("%s", splice_command); // 打印所有非法IP //printf("%ld\n", ip_length); command = (char *)malloc(ip_length + BUFFER); if (command == NULL) { free(command); return -1; } memset(command, 0, ip_length + BUFFER); snprintf(awk, BUFFER, AWK, conf->REFUSE_NUMBER); // 拼接命令 memcpy(command, "echo \"", 7); strcat(command, splice_command); strcat(command, "\""); strcat(command, awk); if ((fc = popen(command, "r")) == NULL) // 执行命令 { perror("popen command"); return -1; } if (splice_command != NULL) { free(splice_command); } if (command != NULL) { free(command); } while (fgets(buffer, BUFFER, fc) != NULL) // 执行命令后, 为空时就不会 { buffer[_strlen(buffer) - 1] = '\0'; // 去除回车 memset(REGION_LIST_COPY, 0, conf->REGION_LIST_LEN + 1); memset(IPV4_WHITE_LIST_COPY, 0, conf->IPV4_WHITE_LIST_LEN + 1); memcpy(REGION_LIST_COPY, conf->REGION_LIST, conf->REGION_LIST_LEN); // 复制配置字符串,split_string()会改变原数据 memcpy(IPV4_WHITE_LIST_COPY, conf->IPV4_WHITE_LIST, conf->IPV4_WHITE_LIST_LEN); // split_string(IPV4_WHITE_LIST_COPY, " ", whitelist_ip); split_string(REGION_LIST_COPY, " ", region_list); if (conf->IPV4_RESTRICTION == 1) // 是否启用白名单 { if (whitelist(buffer, whitelist_ip) == 1) { printf("%s 白名单IPV4:%s\n", t, buffer); continue; } } if (0 != show_all_rule(buffer)) // libiptc库判断否存在规则 { char *location_json = NULL; char *area = NULL; char URL[conf->REGION_URL_LEN + 32]; char *xdb_path = "ip2region.xdb"; // 地域白名单 if (conf->REGION == 1) { memset(URL, 0, conf->REGION_URL_LEN + 32); snprintf(URL, conf->REGION_URL_LEN + 32, conf->REGION_URL, buffer); if (conf->IP2REGION == 1) { // ip2region 地址定位库 printf("%s Use ip2region !!!\n", t); if (-1 == access(xdb_path, F_OK)) // 判断 ip2region 地址定位库是否存在 { xdb_path = "ip2region/ip2region.xdb"; if (-1 == access(xdb_path, F_OK)) { printf("%s ip2region.xdb DOESN'T EXISIT!\n", t); goto AREA; } } area = ip2region(xdb_path, buffer); if (area == NULL) { printf("%s ip2region解析地域错误\n", t); goto BLOCKED; } } else { AREA: location_json = GET_PUBLIC_IP(URL); if (location_json == NULL) { printf("%s 获取地域错误\n", t); goto BLOCKED; } area = process_json(location_json, conf->REGION_URL); if (area == NULL) { printf("%s 解析地域错误\n", t); goto BLOCKED; } } if (isregion(area, region_list) == 1) { printf(RED "%s Ip Address: %s, 地域白名单: %s\n" COLOR_NONE, t, buffer, area); continue; } } printf(RED "%s 攻击者IP地址:%s, %s\n" COLOR_NONE, t, buffer, area); if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警 { dingding_warning(area, public_ip, buffer, conf); sleep(3); } if (conf->IS_MAIL == 1) // 邮件告警 { mail_warning(area, public_ip, buffer, conf); sleep(3); } if (conf->IS_QQMAIL == 1) // 邮件告警 { QQ_mail_warning(area, public_ip, buffer, conf); sleep(3); } BLOCKED: // 是否封禁攻击IP if (conf->IS_BLOCKED == 1) { // libiptc 库插入规则 // iptables -t filter -A INPUT -p tcp -m tcp -s 47.110.180.35 -j DROP // libiptc 库删除规则 // iptables -t filter -D INPUT -p tcp -m tcp -s 47.110.180.35 -j DROP unsigned int srcIp; inet_pton(AF_INET, buffer, &srcIp); iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1); } if (location_json != NULL) free(location_json); if (area != NULL) free(area); } } if (fp != NULL) pclose(fp); if (fc != NULL) pclose(fc); if (t) free(t); return 0; } static void sig_child(int signo) { pid_t pid; int stat; // 处理僵尸进程 while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) ; return; } static int get_executable_path(char *processdir, char *processname, int len) { char *processname_ptr; if (readlink("/proc/self/exe", processdir, len) <= 0) return -1; if ((processname_ptr = strrchr(processdir, '/')) == NULL) return -1; processname_ptr++; strcpy(processname, processname_ptr); *processname_ptr = '\0'; return (int)(processname_ptr - processdir); } // 处理参数 int process_argv(int argc, char *argv[], char **argvs) { argvs[0] = argv[0]; int i; int j; for (i = 0; i <= argc - 1; i++) { if (i == 1) { for (j = i; j <= argc - 2; j++) { argvs[j] = argv[j + 1]; } } } return 0; } int _crontab(struct tm **calnext, char *string) { const char *err = NULL; time_t cur; time_t datenext; time(&cur); cron_expr parsed; cron_parse_expr(string, &parsed, &err); datenext = cron_next(&parsed, cur); *calnext = localtime(&datenext); assert(*calnext); return 0; } static int get_clamav_log(char *file) { FILE *fp = NULL; char buffer[BUFFER], *temp = NULL, *command = NULL; command = (char *)alloca(BUFFER); memset(buffer, 0, BUFFER); memset(command, 0, BUFFER); memcpy(command, "tail -n 12 ", 11); strcat(command, file); fp = popen(command, "r"); if (fp == NULL) { perror("popen"); return -1; } while (fgets(buffer, BUFFER, fp) != NULL) { //printf("%s", buffer); temp = strstr(buffer, "Infected"); if (temp) sscanf(temp, "Infected files: %32s", temp); if (temp != NULL) { //printf("%s\n", temp); break; } } pclose(fp); if (temp != NULL) { printf("%d\n", atoi(temp)); return atoi(temp); } else { return -1; } return 0; } int update_freshclam(int argc, char *argv[]) { if (DEBISN_SYSTEM == check_system() || CENTOS_SYSTEM == check_system()) { char **fre_argv; int fre_argc = 0; char *fre_argvss[ARGS_NUM] = { NULL }; fre_argvss[0] = argv[0]; fre_argvss[1] = "--user=root"; fre_argvss[2] = "--quiet"; fre_argvss[3] = "--no-warnings"; fre_argv = &(fre_argvss[0]); fre_argc = 2; // freshclam配置文件 if (access("/etc/clamav/freshclam.conf", F_OK) == -1) { system("mkdir -p /etc/clamav/"); system("cp freshclam.conf /etc/clamav/"); } // 打印clamav参数 for (int i = 0; i < fre_argc; i++) { printf("%s %d\n", fre_argv[i], i); } pid_t pid; pid = fork(); if (pid < 0) { printf("fork error.\n"); return -1; } else if (pid == 0) // child process { int r = 0; r = _freshclam(fre_argc, fre_argv); _exit(r); } else { int status = 0; wait(&status); // wait the end of child process if (WIFEXITED(status)) { ; printf("child process return %d\n", WEXITSTATUS(status)); } sleep(3); return 0; } } return -1; } static char help_information(void) { static const char name[] = "Rhost"; static const char subject[] = "Reject host&scan for viruses (Rhost 拒绝主机并扫描病毒)"; static const struct { const char *email; const char *version; } author = { "AIXIAO@AIXIAO.ME", "1.0", }; static const char usage[] = "Usage: [-?h] [-d]"; static const char *s_help[] = { "", "Options:", " -d : Background running", " -? -h --help : help information", " The configuration file needs to be in the same directory as the executable file!", " 配置文件需要与可执行文件位于同一目录中!", "", "", 0 }; fprintf(stderr, " %s %s\n", name, subject); fprintf(stderr, "Author: %s\n", author.email); fprintf(stderr, "Version: %s\n", author.version); fprintf(stderr, "%s\n", usage); int l; for (l = 0; s_help[l]; l++) { fprintf(stderr, "%s\n", s_help[l]); } BUILD("Compile、link.\n"); puts(""); return 0; } int main(int argc, char *argv[], char **env) { signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号 int pid; int i; char move[BUFFER]; // 读取配置 char path[BUFFER] = { 0 }; char executable_filename[BUFFER] = { 0 }; (void)get_executable_path(path, executable_filename, sizeof(path)); strcat(executable_filename, ".conf"); strcat(path, executable_filename); if (NULL != argv[1]) { if (0 == strcmp(argv[1], "-v") || 0 == strcmp(argv[1], "--version") || 0 == strcmp(argv[1], "-h") || 0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-?")) { help_information(); exit(0); } } if (1 == access(path, F_OK)) { printf("配置文件不存在!\n"); } conf *conf = (struct CONF *)malloc(sizeof(struct CONF)); read_conf(path, conf); //ptintf_conf(conf); if (0 >= conf->CLAMAV_ARG_LEN) { printf("\033[31mError reading configuration file, please check the configuration file!\033[0m\n"); exit(-1); } // 更新病毒库 update_freshclam(argc, argv); // 创建移除目录 if (conf->CLAMAV_ARG) { char temp[BUFFER]; char *p, *p1; memset(temp, 0, BUFFER); memset(move, 0, BUFFER); p = strstr(conf->CLAMAV_ARG, "--move="); if (p != NULL) { p1 = strstr(p, " "); if ((p1 - p) > 7) { memcpy(temp, p, p1 - p); p = strstr(temp, "="); strcpy(move, "mkdir -p "); strcat(move, p + 1); //printf("%s %ld \n", move, _strlen(move)); system(move); } } } // 处理clamav参数 char **head_argvs; int head_argc = 0; char *argvs[ARGS_NUM] = { NULL }; char args[ARGS_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; if (argc > 3) // 手动输入参数(如果手动输入参数个数大于3个, 则使用用户输入的参数) { process_argv(argc, argv, &(argvs[0])); head_argvs = &(argvs[0]); // head_argvs指向argvs[0] head_argc = argc - 1; // 改变argc数 } else // 读取配置文件参数 { argvs[0] = argv[0]; split_string(conf->CLAMAV_ARG, " ", args); for (i = 1; i < ARGS_NUM; i++) { if (args[i][0] == '\0') { continue; } else { argvs[i] = strdup(args[i]); head_argc++; } } head_argvs = &(argvs[0]); head_argc += 1; } /* // 打印clamav参数 for(int i=0; iPUBLIC_IP); //printf("%s", public_ip); if (0 == strcmp(conf->DAEMON, "on")) { goto goto_daemon; } if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) { goto_daemon: // 守护进程 if ((pid = fork()) < 0) { return 0; } else if (0 != pid) { for (i = 1; i < head_argc; i++) { if (head_argvs[i]) free(head_argvs[i]); } free(t); free_conf(conf); free(conf); free(public_ip); exit(0); } if (setsid() < 0) { return 0; } signal(SIGHUP, SIG_IGN); if ((pid = fork()) < 0) { return 0; } else if (0 != pid) { for (i = 1; i < head_argc; i++) { if (head_argvs[i]) free(head_argvs[i]); } free(t); free_conf(conf); free(conf); free(public_ip); exit(0); } // 进程优先级 if (-1 == (nice(-20))) perror("nice"); // 处理Nginx pid_t pid = fork(); // 创建子进程 if (pid == 0) { printf("The parent process processes Nginx logs!!!\n"); while (1) { nginx_read_log(conf->NGINX_LOG_FILE, conf); sleep(1); } } while (1) { // Cron struct tm *calnext; //取得Cron规则时间 calnext = (struct tm *)malloc(sizeof(struct tm)); memset(calnext, 0, sizeof(struct tm)); _crontab(&calnext, conf->CLAMAV_TIME); t->next_year = 1900 + calnext->tm_year; t->next_mon = 1 + calnext->tm_mon; t->next_day = calnext->tm_mday; t->next_hour = calnext->tm_hour; t->next_min = calnext->tm_min; t->next_sec = calnext->tm_sec; // 取得现在时间 time_t timep; struct tm *p; timep = time(NULL); p = localtime(&timep); t->now_year = 1900 + p->tm_year; t->now_mon = 1 + p->tm_mon; t->now_day = p->tm_mday; t->now_hour = p->tm_hour; t->now_min = p->tm_min; t->now_sec = p->tm_sec; //printf("当前时间 %d%d%d %d:%d:%d\n", t->now_year, t->now_mon, t->now_day, t->now_hour, t->now_min, t->now_sec); //printf("CRON %d%d%d %d:%d:%d\n", t->next_year, t->next_mon, t->next_day, t->next_hour, t->next_min, t->next_sec); // Clamav call if (1 == conf->CLAMAV) { if (t->now_year == t->next_year && t->now_mon == t->next_mon && t->now_day == t->next_day && \ t->now_hour == t->next_hour && t->now_min == t->next_min) { //printf("%d%d%d %d:%d:%d\n", t->now_year, t->now_mon, t->now_day, t->now_hour, t->now_min, t->now_sec); //printf("%d%d%d %d:%d:%d\n", t->next_year, t->next_mon, t->next_day, t->next_hour, t->next_min, t->next_sec); pid_t pid; pid = fork(); if (pid < 0) { printf("fork error.\n"); return -1; } else if (pid == 0) // child process { int r = 0; int virus_files = -1; // 扫描病毒前,更新病毒库 update_freshclam(argc, argv); r = _clamscan(head_argc, head_argvs); virus_files = get_clamav_log("clamscan.log"); if (virus_files > 0) { if (conf->IS_QQMAIL == 1) { QQ_mail_warning_Virus_files(public_ip, virus_files, conf); sleep(3); } } // 磁盘告警 if (1 == conf->IS_DISK) { disk_usage(conf, public_ip, conf->DISK_USE); } _exit(r); } else { int status = 0; wait(&status); // wait the end of child process if (WIFEXITED(status)) { ; //printf("child process return %d\n", WEXITSTATUS(status)); } sleep(60); // 跳过这一分钟 } } } // 封禁非法IP rule(conf); sleep(conf->TIME); } } else { ; } free(t); free_conf(conf); free(conf); free(public_ip); for (i = 1; i < head_argc; i++) { if (head_argvs[i]) free(head_argvs[i]); } return 0; }