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 ;
2023-02-15 13:48:08 +08:00
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 ;
}
2023-02-15 13:48:08 +08:00
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-15 13:48:08 +08:00
2023-02-14 09:30:32 +08:00
area = ( char * ) alloca ( area_len + 1 ) ;
2023-02-15 13:48:08 +08:00
if ( area = = NULL )
2023-02-14 09:30:32 +08:00
perror ( " out of memory. " ) ;
memset ( area , 0 , area_len + 1 ) ;
2023-02-15 13:48:08 +08:00
snprintf ( area , area_len + 1 , " %s " , location - > valuestring ) ;
2023-02-14 09:30:32 +08:00
}
} else {
2023-02-15 13:48:08 +08:00
return NULL ;
2023-02-14 09:30:32 +08:00
}
}
2023-02-15 13:48:08 +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-15 13:48:08 +08:00
2023-02-14 09:30:32 +08:00
if ( conf - > IP2REGION = = 1 ) { // ip2region 地址定位库
2023-02-15 13:48:08 +08:00
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 :
2023-02-15 13:48:08 +08:00
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 ) {
2023-02-15 13:48:08 +08:00
printf ( " Ip Address: %s, 地域白名单: %s \n " , buffer , area ) ;
2023-02-14 09:30:32 +08:00
continue ;
}
}
2023-02-15 13:48:08 +08:00
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-15 13:48:08 +08:00
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 ;
}