使用clamav模块对数据流进行病毒检测
准备工作:linux下安装clamav成功,启动clamav并打开本地socket监听"/tmp/clamav.socket"
clamav开源工程目录:/usr/local/
修改配置文件:/usr/local/clamav/etc/clamd.conf
# Path to a local socket file the daemon will listen on.
# Default: disabled (must be specified by a user)
LocalSocket /tmp/clamd.socket
保存配置文件后,执行命令:
[root@ext sbin]# /usr/local/clamav/sbin/clamd &
[1] 25102
[root@ext sbin]# LibClamAV Warning: **************************************************
LibClamAV Warning: *** The virus database is older than 7 days! ***
LibClamAV Warning: *** Please update it as soon as possible. ***
LibClamAV Warning: **************************************************
[root@ext sbin]#
查看服务监听:
netstat -an|grep cla
unix 2 [ ACC ] STREAM LISTENING 53748 /tmp/clamd.socket
该程序实现方式是通过读取文件内容,然后将文件内容以流的方式发送至clamav服务,通过对clamav服务的返回结果,来判断该文件是否存在病毒;
流程:
①、创建与clamav.socket的连接;
②、发送字符串 "zINSTREAM"到clamav,表示开始对数据流进行检查;
③、开始读取文件内容,然后讲文件内容以流的方式发送至clamav,发送内容 <= 10M ;(为了提高效率定为 10M ,可以根据自己实际情况调整该值大小)
④、数据发送完成后,发送 4 个字节的空字节至clamav,通过该方式通知clamav该次数据发送完成,可以开始返回检测结果;
⑤、读取clamav返回内容,其中包含内容 “stream: OK”时,表示该次检测的流中没有检测到病毒;否则,将会返回该病毒信息;
代码示例:
#define MAX_DATA_LEN 8000 #define MAX_FILE_LEN 1024*1024*10 #define START_CHECK_VIRUS "zINSTREAM" int virus_check(const char *szFileName){ int sock,fd; int tmperror = 0; int len; int revl = 0; unsigned long int todo = MAX_FILE_LEN; char rbuf[256]; uint32_t buf[MAX_DATA_LEN/sizeof(uint32_t)]; sock = CreateConnectLocaleSocket("/tmp/clamd.socket", &tmperror); if (sock < 0){ zlog_debug(cat,"CreateConnectLocaleSocket error"); return -1; } fd = open (szFileName, O_RDONLY|0); if (fd < 0){ zlog_debug(cat,"open [%s] err!",szFileName); return -1; } if(sendln(sock,START_CHECK_VIRUS, 10)){ zlog_debug(cat,"sendln zINSTREAM erro \n"); close(sock); return -1; } while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0){ if((unsigned int)len > todo) len = todo; buf[0] = htonl(len); if(sendln(sock, (const char *)buf, len+sizeof(uint32_t))){ close(fd); close(sock); return -1; } todo -= len; if(!todo){ len = 0; break; } } close(fd); *buf=0; sendln(sock, (const char *)buf, 4); memset(rbuf,0x00,sizeof(rbuf)); revl = recv(sock, rbuf, sizeof(rbuf), 0); close(sock); return parse_Check_results(rbuf,revl); } int parse_Check_results(const char *bufdata,int bufLen){ zlog_debug(cat,"parse_Check_results = [%s] ----------",bufdata); if(!strcmp(bufdata,"stream: OK")){ return 0; } else{ zlog_error(cat, "parse_Check_results err, info = [%s]",bufdata); } return -2; } int sendln(int sockd, const char *line, unsigned int len){ while(len) { int sent = send(sockd, line, len, 0); if(sent <= 0) { if(sent && errno == EINTR) { continue; } return 1; } line += sent; len -= sent; } return 0; } int CreateConnectLocaleSocket(char *pszHostString, int *pnResCode){ int nConnectFd = 0; struct sockaddr_un struInAddr;//���� socket if((nConnectFd=socket(AF_UNIX,SOCK_STREAM,0))==-1){ zlog_error(cat, "CreateConnectLocaleSocket err, errno = [%d] strerror(errno) = [%s]", errno,strerror(errno)); *pnResCode=errno; return -1; } struInAddr.sun_family = AF_UNIX; strcpy(struInAddr.sun_path, pszHostString); if(connect(nConnectFd,(struct sockaddr *)&struInAddr,sizeof(struct sockaddr_un))==-1) { zlog_error(cat, "CreateConnectLocaleSocket connect err, errno = [%d] strerror(errno) = [%s]", errno,strerror(errno)); close(nConnectFd); *pnResCode=errno; return -1; } return nConnectFd; }
转载请注明出处