ClamAV
Clam AntiVirus 是一款适用于 UNIX 的开源 (GPL) 反病毒工具包。它提供了一系列实用程序,包括灵活且可扩展的多线程守护进程、命令行扫描器以及用于自动更新数据库的高级工具。由于 ClamAV 主要用于文件/邮件服务器,它主要通过内置签名来检测恶意软件,而非传统的终端安全套件。
由于多种因素,Linux 上反恶意软件产品的现状并不理想:
- 品种有限:与 Windows 相比,用户/客户端较少,导致公司开发 Linux 产品的兴趣有限。
- 自满:许多人认为 Linux 天生安全,导致缺乏意识和对恶意软件防护的关注。这造成了主动防御机制的缺失。
- 功能匮乏:现有的工具往往缺乏 Windows 反恶意软件产品中常见的高级功能,导致它们在 Linux 上的效果较差。
这一点尤其严重,因为随着基于 Linux 的服务器和物联网设备数量的增加,Linux 上的恶意软件数量以及潜在的攻击面也在随之扩大。
目前在 Linux 上,少数几个现存且积极开发的方案之一就是 ClamAV。
安装
这将安装以下工具:
clamd: ClamAV Daemon clamonacc: On-Access real-time protection clamdscan: A simple scanning client clamdtop: A resource monitoring interface for clamd freshclam: Daemon for virus signature updates clamconf: Tool to create and check configuration files
所有 ClamAV 相关的工具、服务和守护进程都通过套接字与 clamd 通信。
默认情况下,这是通过本地套接字 "LocalSocket" 完成的。
ClamAV 还提供了通过 网络套接字(配置并命名为 "TCPSocket")实现远程位置通信的可能性。
另一个需要注意的重要事项是,使用 LocalSocket 时,clamd 需要以拥有足够权限的用户身份运行,才能扫描您计划纳入监控范围的文件。
配置
默认配置文件通常已经存在。如果没有,您可以使用 clamconf 手动创建它们。
# clamconf -g freshclam.conf > freshclam.conf # clamconf -g clamd.conf > clamd.conf # clamconf -g clamav-milter.conf > clamav-milter.conf
以下文件包含相关的配置选项:
- freshclam:
/etc/clamav/freshclam.conf - clamd:
/etc/clamav/clamd.conf - clamd 邮件过滤:
/etc/clamav/clamav-milter.conf
最后,您可以通过运行 clamconf 来检查您的配置文件。
默认安装将创建“合理”的默认配置,例如:一个 clamav 系统用户、一个 clamav 用户组以及所需的 clamd 配置文件。
可以设置额外的推荐配置。
/etc/clamav/clamd.conf
# Log time with each message. # Default: no LogTime yes # Log additional information about the infected file, such as its # size and hash, together with the virus name. ExtendedDetectionInfo yes # Run as another user (clamd must be started by root for this option to work) # Default: don't drop privileges User clamav # Maximum depth directories are scanned at. # Default: 15 MaxDirectoryRecursion 20 DetectPUA yes HeuristicAlerts yes ScanPE yes ScanELF yes ScanOLE2 yes ScanPDF yes ScanSWF yes ScanXMLDOCS yes ScanHWP3 yes ScanOneNote yes ScanMail yes ScanHTML yes ScanArchive yes Bytecode yes AlertBrokenExecutables yes AlertBrokenMedia yes AlertEncrypted yes AlertEncryptedArchive yes AlertEncryptedDoc yes AlertOLE2Macros yes AlertPartitionIntersection yes
启用实时防护 OnAccessScan
访问时扫描(On-access scanning)是实时防护守护进程,会在读取、写入或执行文件时对其进行扫描。它可以被配置为检测到威胁时通知用户或阻止/拒绝操作。
OnAccessScan 的配置通过编辑 /etc/clamav/clamd.conf 配置文件完成。
要使 OnAccessScan 生效,需要进行以下更改:
/etc/clamav/clamd.conf
# Exclude the UID of the scanner itself from checking, to prevent loops OnAccessExcludeUname clamav
建议进行以下附加更改,将访问时扫描器置于仅通知模式:
/etc/clamav/clamd.conf
# Set the mount point where to recursively perform the scan, # this could be every path or multiple path (one line for path) OnAccessMountPath / # Alternatively, add some directories instead of mount points # OnAccessIncludePath /home # Prevention doesn't work with OnAccessMountPath. # It works with OnAccessIncludePath, as long as /usr and /etc are not included. # Including /var while activating prevention is also not recommended, because # this would slow down package installation by a factor of 1000. OnAccessPrevention no # Perform scans on newly created, moved, or renamed files OnAccessExtraScanning yes # Optionallyexclude root-owned processes # OnAccessExcludeRootUID true
为警报创建桌面通知
到目前为止,ClamAV 会静默记录任何检测结果,但不会提醒用户。可以添加一个弹出窗口来在检测到威胁时提醒用户。
首先,将以下行添加到您的 clamd 配置中:
/etc/clamav/clamd.conf
VirusEvent /etc/clamav/virus-event.bash
接下来,允许 clamav 用户通过 sudo 以任何用户身份运行 notify-send,并使用自定义环境变量。
/etc/sudoers.d/clamav
clamav ALL = (ALL) NOPASSWD: SETENV: /usr/bin/notify-send
接下来,创建文件 /etc/clamav/virus-event.bash,使其成为 可执行文件,并添加以下内容:
/etc/clamav/virus-event.bash
#!/bin/bash
PATH=/usr/bin
ALERT="Signature detected by clamav: $CLAM_VIRUSEVENT_VIRUSNAME in $CLAM_VIRUSEVENT_FILENAME"
# Send an alert to all graphical users.
for ADDRESS in /run/user/*; do
USERID=${ADDRESS#/run/user/}
/usr/bin/sudo -u "#$USERID" DBUS_SESSION_BUS_ADDRESS="unix:path=$ADDRESS/bus" PATH=${PATH} \
/usr/bin/notify-send -u critical -i dialog-warning "Virus found!" "$ALERT"
done
这允许您在 clamd 的访问时扫描服务检测到病毒时更改/指定消息内容。
默认情况下,clamonacc 会将刚访问的文件名传给 clamav 进行扫描。这是一个问题,因为 clamav 用户无法访问的文件无法通过这种方式扫描。相反,可以指示 clamonacc(它始终以 root 身份运行)使用文件描述符传递。 编辑 clamav-clamonacc.service 并添加以下内容:
[Service] ExecStart= ExecStart=/usr/sbin/clamonacc -F --fdpass --log=/var/log/clamav/clamonacc.log
最后,您需要 启动/启用 或 重启 clamav-clamonacc.service 以及 clamav-daemon.service。
请参阅:#启动 ClamAV + OnAccessScanning 守护进程
如果您收到有关 clamd 的 AppArmor 拒绝访问信息,请将配置文件的模式设置为仅抱怨(complain-only)。
# aa-complain clamd
更新数据库
更新病毒定义:
# freshclam
如果您位于代理服务器后面,请编辑 /etc/clamav/freshclam.conf 并更新 HTTPProxyServer、HTTPProxyPort、 HTTPProxyUsername 和 HTTPProxyPassword。
数据库文件保存在:
/var/lib/clamav/daily.cvd /var/lib/clamav/main.cvd /var/lib/clamav/bytecode.cvd
对于自动更新,首先创建并设置所需的 freshclam.log 文件:
touch /var/log/clamav/freshclam.log chmod 600 /var/log/clamav/freshclam.log chown clamav /var/log/clamav/freshclam.log
启动/启用 clamav-freshclam.service 或 clamav-freshclam-once.timer 以保持病毒定义为最新。
clamav-freshclam.service 会以守护进程模式启动 freshclam,默认每天检查 12 次(每 2 小时一次)。频率可以在 /etc/clamav/freshclam.conf 中更改。
clamav-freshclam-once.timer 每天启动一次 freshclam 检查。频率可以在 /usr/lib/systemd/system/clamav-freshclam-once.timer 中更改。
- 守护进程模式下的 Freshclam 会在每次(服务)启动时检查。
- 每小时超过 1 次检查会导致被 CDN 封禁 24 小时。
.timer单元遵循设定的时间表,无论重启或服务重启如何。- 您可以按照 #添加更多数据库/签名存储库 添加额外的病毒签名数据库。
启动 ClamAV + OnAccessScanning 守护进程
这将把所有病毒签名加载到内存中。截至 2024 年 2 月,这些签名至少需要 1.6GB 的可用内存。在定期更新签名期间,内存使用量会短暂翻倍。
- 您需要在首次启动服务之前运行
freshclam,否则会遇到错误导致 ClamAV 无法正确启动。 - 如果您只想执行独立扫描,则不需要守护进程。请参阅下文的 扫描病毒。
- 守护进程对于访问时扫描(见:#启用实时防护 OnAccessScan)以及
clamav-milter(见:#使用 milter)是必需的。
该服务名为 clamav-daemon.service。 启动 并 启用 它以便在启动时运行。
此外,启动 并 启用 clamav-clamonacc.service 以实现实时访问时防护。
测试软件
为了确保 ClamAV 和定义安装正确,使用 clamscan 扫描 EICAR 测试文件(一个不含病毒代码的无害签名)。
$ curl https://secure.eicar.org/eicar.com.txt | clamscan -
输出结果必须包含:
stdin: Eicar-Test-Signature FOUND
实时防护
您可以下载并保存 eicar 文件到您配置 clamonacc 监控的目录之一中。例如:
$ cd /home/user/Downloads/ $ wget https://secure.eicar.org/eicar.com.txt $ cat eicar.com.txt
添加更多数据库/签名存储库
ClamAV 可以使用来自其他存储库或安全厂商的数据库/签名。
要通过单个步骤添加最重要的存储库,请安装 python-fangfrischAUR(参见 在线文档)。它将添加来自主流提供商的签名/数据库,例如 MalwarePatrol、SecuriteInfo、Yara、Linux Malware Detect 等。
设置 Fangfrisch
作为现已废弃的 clamav-unofficial-sigs 的替代品,Fangfrisch 更安全、灵活、便捷,且只需要 极少的配置 (/etc/fangfrisch/fangfrisch.conf)。
最重要的是,与 clamav-unofficial-sigs 不同,Fangfrisch 永远不需要以 root 权限运行。
通过运行以下命令创建数据库结构:
[clamav]$ /usr/bin/fangfrisch --conf /etc/fangfrisch/fangfrisch.conf initdb
启用 fangfrisch.timer (系统级)。
扫描病毒
按需扫描有两种选择:
使用独立扫描器
clamscan 可用于扫描特定文件、主目录或整个系统:
$ clamscan myfile $ clamscan --recursive --infected /home/$USER # clamscan --recursive --infected --exclude-dir='^/sys|^/dev' /
如果您希望 clamscan 删除受感染的文件,请在命令中添加 --remove 选项,或者您可以使用 --move=/dir 将其隔离。
您可能还需要 clamscan 扫描更大的文件。在这种情况下,请在命令中附加选项 --max-filesize=4000M 和 --max-scansize=4000M。'4000M' 是最大可能值,可根据需要调低。
使用 -l /path/to/file 选项将 clamscan 日志打印到文本文件中,以便查找报告的感染。
使用守护进程
clamdscan 与上述类似,但利用了守护进程,该命令正常工作必须确保守护进程处于运行状态。大多数选项会被忽略,因为守护进程会读取 /etc/clamav/clamd.conf 中指定的设置。
使用 milter
Milter 将扫描您的邮件服务器以查找包含病毒的电子邮件。请根据需要调整 /etc/clamav/clamav-milter.conf。例如:
/etc/clamav/clamav-milter.conf
MilterSocket /var/spool/postfix/private/clamav-milter MilterSocketMode 660 FixStaleSocket yes User clamav MilterSocketGroup clamav PidFile /run/clamav/clamav-milter.pid TemporaryDirectory /tmp ClamdSocket unix:/run/clamav/clamd.ctl LogSyslog yes LogInfected Basic
创建 /etc/systemd/system/clamav-milter.service:
/etc/systemd/system/clamav-milter.service
[Unit] Description='ClamAV Milter' After=clamav-daemon.service [Service] Type=forking ExecStart=/usr/bin/clamav-milter --config-file /etc/clamav/clamav-milter.conf Restart=Always [Install] WantedBy=multi-user.target
您的系统可能需要不同的 Restart= 指令。例如,当 logrotate 等自动工具停止服务时,需要这样做。
启用 并 启动 clamav-milter.service。
对于 Postfix,将以下行添加到 /etc/postfix/main.cf:
/etc/postfix/main.cf
smtpd_milters = unix:private/clamav-milter milter_default_action = shutdown
postfix 用户必须添加到 clamav 组中,才能访问 clamav-milter unix 套接字。
# usermod -aG clamav postfix
技巧与提示
多线程运行
使用 clamscan
在命令行中使用 clamscan 扫描文件或目录时,仅使用单个 CPU 线程。虽然这会导致较低的资源负载(这在后台运行扫描时很有用),但也会导致扫描时间变长,特别是在扫描大目录或外部驱动器时。因此,您可能希望通过利用尽可能多的 CPU 线程来加快此过程。
clamscan 被设计为单线程,因此可以使用 xargs 并行运行扫描:
$ find /home/$USER -type f -print0 | xargs -0 -P $(nproc) clamscan
在此示例中,xargs 的 -P 参数可以同时运行与 CPU 数量(由 nproc 报告)相同数量的 clamscan 进程。--max-lines 和 --max-args 选项允许更精细地控制跨线程的任务批处理。
由于所有进程都是独立的并且会加载签名文件,这将消耗大量内存。单个线程将消耗约 1G(或更多)内存,如果不触发 OOM 机制可能会挂起您的计算机。您可能需要考虑改用 clamdscan。
使用 clamdscan
如果您已经运行了 clamd 守护进程,则可以使用 clamdscan 代替(见 #启动 ClamAV + OnAccessScanning 守护进程)。
$ clamdscan --multiscan --fdpass /home/$USER
此处 --multiscan 参数使 clamd 能够使用可用线程并行扫描目录内容。需要 --fdpass 参数将文件描述符权限传递给 clamd,因为守护进程是以 clamav 用户和组身份运行的。
clamdscan 的可用线程数由 /etc/clamav/clamd.conf 中的 MaxThreads 参数决定 clamd.conf(5)。尽管您可能会看到指定的 MaxThreads 数量大于 1(当前默认值为 10),但当您从命令行使用 clamdscan 启动扫描且未指定 --multiscan 选项时,只会使用一个有效的 CPU 线程进行扫描。
TCPSocket — 为 clamd 启用网络访问
clamd TCP 端口提供无身份验证和无加密保护。切勿将其暴露在不受信任的网络中。请务必使用 防火墙 规则将访问权限严格限制为本地主机或受信任的本地网络接口。有关背景信息,请参见 ClamAV 安全博客文章 和 官方文档。默认情况下,clamd 通过 Unix 域套接字 (/run/clamav/clamd.ctl) 进行通信,这对于同一主机上的本地客户端来说已经足够了。启用 TCP 套接字允许本地网络上的远程客户端提交文件进行扫描 — 这对于集中式扫描架构很有用。
Architecture
推荐的方法是让 clamd 通过 clamd.conf 自行绑定 TCP,而不是依赖 systemd 套接字激活 TCP 套接字。TCP 套接字激活在绑定到非回环地址时会引入排序问题:systemd 的 sockets.target 在网络可用之前启动,导致套接字单元失败并显示 Cannot assign requested address。任何尝试将 After=network-online.target 添加到套接字单元的操作都会通过 systemd 的 basic.target 产生排序循环。
Unix 域套接字将继续像以前一样使用套接字激活。只有 TCP 的处理方式不同。
配置
步骤 1 — 将 TCP 绑定添加到 /etc/clamav/clamd.conf
对于回环地址(仅限同一主机):
/etc/clamav/clamd.conf
TCPSocket 3310 TCPAddr 127.0.0.1
对于特定的本地网络接口(例如受信任的 LAN 或管理网络):
/etc/clamav/clamd.conf
TCPSocket 3310 TCPAddr 192.168.0.199
将 192.168.0.199 替换为您希望 clamd 监听的接口的 IP 地址。除非所有接口都受到 防火墙 的保护,否则切勿使用 0.0.0.0。
步骤 2 — 创建 systemd 服务覆盖文件(drop-in):
/etc/systemd/system/clamav-daemon.service.d/override.conf
[Unit] After=network-online.target Wants=network-online.target Requires= [Service] UnsetEnvironment=LISTEN_FDS LISTEN_PID LISTEN_FDNAMES
这三个指令有不同的目的:
After=/Wants=network-online.target
确保clamd仅在网络接口完全启动且 IP 地址可用后才启动。Requires=
清除了对clamav-daemon.socket的硬依赖,允许clamd独立启动。UnsetEnvironment=
抑制 systemd 的套接字传递协议。如果没有此项,clamd会检测到由 systemd 设置的环境变量LISTEN_FDS、LISTEN_PID和LISTEN_FDNAMES,并进入套接字激活模式,从而静默忽略clamd.conf中的TCPSocket/TCPAddr,并记录:TCP: No tcp AF_INET/AF_INET6 SOCK_STREAM socket received from systemd.
步骤 3 — 重新加载并 重启:
$ sudo systemctl daemon-reload $ sudo systemctl restart clamav-daemon.service
步骤 4 — 验证:
$ ss -tlnp | grep 3310
预期输出(clamd 拥有该套接字,systemd 未列出):
tcp LISTEN 0 200 192.168.0.199:3310 0.0.0.0:* users:(("clamd",...))
防火墙
绑定到非回环地址时,请在 防火墙 级别将对 3310 端口的访问限制在允许的范围内。
故障排除
clamscan 的用户对数据库文件 (/var/lib/clamav/*.c?d) 具有读取权限。错误:Clamd 未收到通知
如果您在运行 freshclam 后收到以下消息:
WARNING: Clamd was NOT notified: Cannot connect to clamd through /var/lib/clamav/clamd.sock connect(): No such file or directory
为 ClamAV 添加一个 sock 文件:
# touch /run/clamav/clamd.ctl # chown clamav:clamav /run/clamav/clamd.ctl
然后,编辑 /etc/clamav/clamd.conf - 取消注释此行:
LocalSocket /run/clamav/clamd.ctl
保存文件并 重启 clamav-daemon.service。
错误:未找到支持的数据库文件
如果您在启动守护进程时收到以下错误:
LibClamAV Error: cli_loaddb(): No supported database files found in /var/lib/clamav ERROR: Not supported data format
这是因为 /etc/clamav/freshclam.conf 中的 DatabaseDirectory 设置与 /etc/clamav/clamd.conf 中的 DatabaseDirectory 设置不匹配。/etc/clamav/freshclam.conf 指向 /var/lib/clamav,而 /etc/clamav/clamd.conf(默认目录)指向 /usr/share/clamav 或其他目录。在 /etc/clamav/clamd.conf 中编辑并将其替换为与 /etc/clamav/freshclam.conf 中相同的 DatabaseDirectory。之后,clamav 将成功启动。
错误:无法创建临时目录
如果您收到以下错误,且提示中包含 UID 和 GID 号码:
# can't create temporary directory
更正权限:
# chown UID:GID /var/lib/clamav && chmod 755 /var/lib/clamav
ClamOnAcc 日志文件膨胀至巨大体积并塞满了拒绝访问错误
这是因为自带的 clamav-clamonacc systemd 单元存在问题。修改 /lib/modules/systemd/system/clamav-clamonacc.service 为:
ExecStart=/usr/sbin/clamonacc --fdpass -F --log=/var/log/clamav/clamonacc.log --move=/root/quarantine
这指示 clamonacc 将文件描述符传递给 clamd,由后者代为执行扫描。