denyhosts/rhost.c

1230 lines
33 KiB
C
Raw Normal View History

2023-02-14 09:30:32 +08:00
#include "conf.h"
#include "rhost.h"
#include "libiptc.h"
#include "libclamav.h"
#include "clamscan.h"
#include "ccronexpr.h"
// 存储公网IP
char *public_ip;
struct MemoryStruct
{
char *memory;
size_t size;
};
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;
}
2023-02-14 09:30:32 +08:00
cJSON *cjson_init = cJSON_Parse(buff);
if (cjson_init == NULL) {
perror("cJSON_Parse");
return NULL;
}
if ((p = strstr(api, "baidu")) != NULL) { // baidu Api
2023-02-14 09:30:32 +08:00
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);
2023-02-14 09:30:32 +08:00
area = (char *)alloca(area_len + 1);
if (area == NULL)
2023-02-14 09:30:32 +08:00
perror("out of memory.");
memset(area, 0, area_len + 1);
snprintf(area, area_len+1, "%s", location->valuestring);
2023-02-14 09:30:32 +08:00
}
} else {
return NULL;
2023-02-14 09:30:32 +08:00
}
}
else
{
cJSON_Delete(cjson_init);
return NULL;
}
2023-02-14 09:30:32 +08:00
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)
{
2023-02-21 11:43:14 +08:00
fclose(fp);
2023-02-14 09:30:32 +08:00
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);
}
// 第三方邮箱告警, 磁盘使用率
int QQ_mail_warning_Disk_Use(char *local_ip, int disk_use, 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, Disk usage reaches threshold!, Please handle!", temp);
snprintf(command, BUFFER, QQMAIL_DISK_USE, 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 *remove_space(const char *str)
{
unsigned int i = 0, j = 0;
unsigned int uLen = strlen(str);
char *strRet;
if (0 == uLen)
{
return '\0';
}
strRet = (char *)malloc(uLen + 2);
memset(strRet, 0, uLen + 2);
for (i = 0; i < uLen; i++)
{
if (str[i] != ' ')
{
strRet[j++] = str[i];
}
}
strRet[j] = '\0';
return strRet;
}
// 磁盘使用率
int disk_waring(int threshold)
{
FILE *fp = NULL;
char buffer[BUFFER];
char command[BUFFER];
int is = 0;
#define DF "for u in `df -mh | grep -E -e \".:.\" -e \"^/dev\" | awk '{print $5}' | sed 's|%%||g'`; do if test \"$u\" -ge %d; then echo \"$u\"; fi done"
memset(buffer, 0, BUFFER);
memset(command, 0, BUFFER);
snprintf(command, BUFFER, DF, threshold);
//printf("%s\n", command);
fp = popen(command, "r");
while(fgets(buffer, BUFFER, fp) != NULL)
{
printf("%s", buffer);
is = 1;
break;
}
pclose(fp);
return is;
}
// 封禁非法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);
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");
2023-02-21 11:43:14 +08:00
sscanf(temp, "rhost=%64s", temp);
2023-02-14 09:30:32 +08:00
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;
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);
2023-02-21 11:43:14 +08:00
snprintf(awk, BUFFER, AWK, conf->REFUSE_NUMBER); // 拼接命令
memcpy(command, "echo \"", 7);
2023-02-14 09:30:32 +08:00
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("白名单IPV4:%s\n", 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);
2023-02-21 11:43:14 +08:00
snprintf(URL, conf->REGION_URL_LEN+32, conf->REGION_URL, buffer);
2023-02-14 09:30:32 +08:00
2023-02-14 09:30:32 +08:00
if (conf->IP2REGION == 1) { // ip2region 地址定位库
printf("Use ip2region !!!\n");
2023-02-14 09:30:32 +08:00
if (-1 == access(xdb_path, F_OK)) // 判断 ip2region 地址定位库是否存在
{
xdb_path = "ip2region/ip2region.xdb";
if (-1 == access(xdb_path, F_OK)) {
printf("ip2region.xdb DOESN'T EXISIT!\n");
goto AREA;
}
}
area = ip2region(xdb_path, buffer);
if (area == NULL) {
printf("ip2region解析地域错误\n");
goto BLOCKED;
}
} else {
AREA:
location_json = GET_PUBLIC_IP(URL);
if (location_json == NULL) {
printf("获取地域错误\n");
goto BLOCKED;
}
2023-02-14 09:30:32 +08:00
area = process_json(location_json, conf->REGION_URL);
if (area == NULL) {
printf("解析地域错误\n");
goto BLOCKED;
}
}
if (isregion(area, region_list) == 1) {
printf("Ip Address: %s, 地域白名单: %s\n", buffer, area);
2023-02-14 09:30:32 +08:00
continue;
}
}
printf("攻击者IP地址:%s, %s\n", buffer, area);
2023-02-14 09:30:32 +08:00
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 xxxx -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);
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)
2023-02-21 11:43:14 +08:00
sscanf(temp, "Infected files: %32s", temp);
2023-02-14 09:30:32 +08:00
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); // 创建捕捉子进程退出信号
/*
// ip2region 离线IP地址定位库
char *area = NULL;
area = ip2region("ip2region/ip2region.xdb", "1.1.1.1");
printf("%s\n", area);
free(area);
exit(0);
*/
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);
// 更新病毒库
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 } };
//printf("%d\n", argc);
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; i<head_argc; i++)
{
printf("%s %d\n", head_argvs[i], i);
}
_clamscan(head_argc, head_argvs);
*/
now_next_time *t = (now_next_time *)malloc(sizeof(struct now_next_time));
memset(t, 0, sizeof(struct now_next_time));
// 获取公网IP
public_ip = GET_PUBLIC_IP(conf->PUBLIC_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 (daemon(1, 1)) // 守护进程
{
perror("daemon");
return -1;
}
*/
// 守护进程
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");
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;
2023-02-21 11:43:14 +08:00
//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);
2023-02-14 09:30:32 +08:00
// 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);
2023-02-14 09:30:32 +08:00
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)
{
if (disk_waring(conf->DISK_USE) == 1)
{
printf("Disk usage reaches threshold!, Please handle!\n");
if (conf->IS_QQMAIL == 1)
{
QQ_mail_warning_Disk_Use(public_ip, 0, conf);
sleep(3);
}
}
else
{
printf("Disk usage does not reach threshold!\n");
}
}
_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); // 跳过这一分钟
}
}
}
rule(conf);
sleep(conf->TIME);
}
}
else
{
rule(conf);
}
free(t);
free_conf(conf);
free(conf);
free(public_ip);
for(i=1; i<head_argc; i++)
{
//printf("%s %d\n", head_argvs[i], i);
if (head_argvs[i])
free(head_argvs[i]);
}
return 0;
}