在EC2 Linux操作系统上部署ClamAV并开启实时防护、集中日志采集和统一告警

一、背景

计算机信息系统等级保护(俗称等保)的要求之一是应用服务器具有病毒防护手段,并定期升级病毒特征库。这个防护场景通常被称为Endpoint Detection and Response(EDR),也可简称终端防护。EDR一般是采用侵入性的防护方式。所谓侵入性意味着需要在EC2虚拟机内植入专门的Agent才可以进行安全防护。在亚马逊云科技上,可通过Marketplace方式订阅多个第三方厂家的EDR,也可以线下采购。

商用的EDR方案有完整的检测、识别、发现、预防、干预、强化、集中管控等一整套管理功能,不过相对带来的问题是成本较高。在一些非严格等保的场合,如果只是要求实现病毒扫描和防护能力,那么可使用本文介绍的ClamAV方案进行替代。

ClamAV是一个开源的引擎,用于检测病毒、木马、恶意软件和其他威胁。ClamAV支持Windows、Linux和MacOS等系统。Github官网在这里。ClamAV由Talos所有,后者又被Cisco收购,用于为Cisco供应威胁情报。ClamAV社区提供了免费的持续的病毒特征库升级。因此可实现一次部署,长期使用。

本文介绍如何在Amazon Linux 2操作系统上部署,其他系统如Ubuntu安装过程相仿请参考对应文档。

二、安装ClamAV并执行手工扫描

1、安装软件包

注意:ClamAV加载特征库和全盘扫描比较消耗CPU和内存资源,因此建议在不小于4GB内存的机型上安装部署。内存仅为1GB、2GB的机型运行速度可能较为缓慢,甚至出现部分时间假死的情况。

本文采用操作系统自带的软件源。执行如下命令安装。

yum update -y
amazon-linux-extras install epel
yum install clamav clamd -y 

安装好的ClamAV有几个主要组成部分:

  • clamscan:手工扫描程序
  • clamdscan:依赖后台服务的扫描程序
  • clamonacc:按需扫描程序(实时监控),对应配置文件/etc/clamd.d/scan.conf
  • clamd:按需扫描的后台进程,对应配置文件/etc/clamd.d/scan.conf
  • fleshclam:病毒库升级工具,对应配置文件/etc/fleshclam.conf
  • clamconf:配置文件生成工具

2、手工更新病毒库

首次安装后,必须先下载病毒库。执行如下命令更新病毒库:

freshclam

返回结果如下表示升级成功:

ClamAV update process started at Sat Dec  3 14:15:51 2022
daily database available for download (remote version: 26739)
Time:    0.7s, ETA:    0.0s [========================>]   57.54MiB/57.54MiB
Testing database: '/usr/local/share/clamav/tmp.645c56b964/clamav-293585c0119a1f028368c597169d1634.tmp-daily.cvd' ...
Database test passed.
daily.cvd updated (version: 26739, sigs: 2013388, f-level: 90, builder: raynman)
main database available for download (remote version: 62)
Time:    0.6s, ETA:    0.0s [========================>]  162.58MiB/162.58MiB
Testing database: '/usr/local/share/clamav/tmp.645c56b964/clamav-e66a7c48ee3b6ac03f488235d68bf206.tmp-main.cvd' ...
Database test passed.
main.cvd updated (version: 62, sigs: 6647427, f-level: 90, builder: sigmgr)
bytecode database available for download (remote version: 333)
Time:    0.0s, ETA:    0.0s [========================>]  286.79KiB/286.79KiB
Testing database: '/usr/local/share/clamav/tmp.645c56b964/clamav-12719bf9f9650a8a8000cad457a59542.tmp-bytecode.cvd' ...
Database test passed.
bytecode.cvd updated (version: 333, sigs: 92, f-level: 63, builder: awillia2)

设置后台自动升级病毒库:

systemctl start clamav-freshclam
systemctl enable clamav-freshclam

默认的升级频率是每2小时升级1次,折合每天12次。如果需要调整,可以编辑如下配置文件/etc/freshclam.conf,找到其中的如下一段,把数值改为1:

# Number of database checks per day.
# Default: 12 (every two hours)
Checks 1

重启服务,即可将升级频率设置为每天升级1次。

3、手工扫描特定文件夹

手工对某一个目录执行扫描。执行如下命令:

clamscan -r -i /

其中-r参数表示扫描子目录,-i参数表示只输出疑似病毒扫描结果。在启动后,首先ClamAV会验证特征库的签名,然后执行扫描。对根目录扫描的时间会很长,可能长达数分钟。

返回如下结果表示扫描完成。

----------- SCAN SUMMARY -----------
Known viruses: 8645335
Engine version: 1.0.0
Scanned directories: 4801
Scanned files: 43128
Infected files: 0
Data scanned: 1770.53 MB
Data read: 1315.73 MB (ratio 1.35:1)
Time: 420.401 sec (7 m 0 s)
Start Date: 2022:12:03 15:23:33
End Date:   2022:12:03 15:30:33

三、开启实时检测和定期检测

ClamAV在Linux系统上支持实时检测,也就是对当前系统读取和写入的文件进行检测,被称为on-access scanning

1、修改配置文件

实时检测需要启动clamd服务。这个服务的配置文件根据不同安装方式,可能配置文件路径和文件名不一样。本文使用的Amazon Linux 2的epel源安装后,配置文件是/etc/clamd.d/scan.conf。这其中要修改监听管道、启动用户等多处配置。

编辑/etc/clamd.d/scan.conf,修改如下的几个参数(排名和顺序可能所有不同,不影响效果)。

# Path to a local socket file the daemon will listen on.
# Default: disabled (must be specified by a user)
LocalSocket /tmp/clamd.socket

# Sets the group ownership on the unix socket.
# Default: disabled (the primary group of the user running clamd)
LocalSocketGroup clamscan

# Sets the permissions on the unix socket to the specified mode.
# Default: disabled (socket is world accessible)
LocalSocketMode 660

# Modifies fanotify blocking behaviour when handling permission events.
# If off, fanotify will only notify if the file scanned is a virus,
# and not perform any blocking.
# Default: no
OnAccessPrevention yes

# This option allows exclusions via user names when using the on-access
# scanning client. It can be used multiple times.
# It has the same potential race condition limitations of the
# OnAccessExcludeUID option.
# Default: disabled
OnAccessExcludeUname clamscan

# Set the include paths (all files inside them will be scanned). You can have
# multiple OnAccessIncludePath directives but each directory must be added
# in a separate line.
# Default: disabled
OnAccessIncludePath /home

# Uncomment this option to enable logging.
# LogFile must be writable for the user running daemon.
# A full path is required.
# Default: disabled
LogFile /var/log/clamd.scan

# Maximum size of the log file.
# Value of 0 disables the limit.
# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)
# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size
# in bytes just don't use modifiers. If LogFileMaxSize is enabled, log
# rotation (the LogRotate option) will always be enabled.
# Default: 1M
LogFileMaxSize 20M

# Log time with each message.
# Default: no
LogTime yes

名为LocalSocket的参数的是服务监听参数。启动有localsocket和网络监听两种模式,可独立使用,也可以同时使用。对于EC2的本机扫描而言,适用Unix管道的localsocket模式即可。

名为OnAccess的参数是实时扫描相关,分别表示:打开实时防护并拦截有风险的访问;设置要执行实施监控的路径(不建议对/根路径监控,建议只监控应用路径,本文以/home为例);实时检测要排除的用户名。由于clamd不能以root身份运行,而需要以普通用户身份运行,在本文使用操作系统安装源时候,会自动创建名为clamscan的新用户,然后以这个身份运行。因此在配置文件中,这里需要设置一个与clamd服务启动的用户名保持一致,否则会发生自己触发扫描自己的递归调用,造成不必要的资源消耗。

名为Log相关的参数是日志路径和日志大小配置。在刚安装好的配置文件中,默认配置LogSyslog yes这个参数的生效,因此扫描到的病毒结果会输出到系统日志中。本文为了便于查询,额外又设置了如上配置文件中的日志地址/var/log/clamd.scan并且配置了最大体积为20MB。

都修改完毕后,保存退出。

执行如下命令创建日志文件:

touch /var/log/clamd.scan
chown clamscan:clamscan /var/log/clamd.scan

2、启动clamd和clamonacc后台服务

以root身份执行如下命令启动clamd服务:

systemctl start clamd@scan
systemctl enable clamd@scan
systemctl start clamonacc
systemctl enable clamonacc

为了验证实时监控在运行,可执行clamdtop命令查看后台进程。显示结果类似如下:

        __                    ____
  _____/ /___ _____ ___  ____/ / /_____  ____
 / ___/ / __ `/ __ `__ \/ __  / __/ __ \/ __ \
/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /
\___/_/\__,_/_/ /_/ /_/\__,_/\__/\____/ .___/
                                     /_/
Connecting to: /run/clamd.scan/clamd.sock

然后即可进入类似Top命令的资源占用查看界面,即可证明clamd服务启动正常。

3、验证实时防护

为了验证实时防护的有效性,需要模拟一个病毒特征来触发告警。在云上请勿使用真实病毒来测试您的网络安全,如用真实病毒测试,可能会触发对外部网络的扫描等恶意行为,将导致您的云账号被投诉和甚至关停。因此这里引入一个测试特征码来测试。欧洲计算机防病毒研究所 (EICAR) 开发了一种测试特征码,他是一个惰性的文本文件,也就是一串字符串,并且不包含任何程序代码无法被执行。这个特征码包含在多数防病毒的特征中可以被识别出来。这里将它写入一个文本文件eicar.virus。由于前文配置Clamd后台进程是监控的/home目录,这里需要与之匹配,所以将这个病毒特征文件放到/home目录下。如果放在其他目录下则没有办法被扫描到。执行如下命令即可生成特征码。

cat > /home/eicar.virus <<'EOF'
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
EOF

现在以普通ec2-user用户的身份调用访问这个文件cat /home/eicar.virus,此时将会触发实时防护,访问将被拦截。此时的ec2-user用户的console上会有如下提示:

cat: eicar.virus: Operation not permitted

在操作系统日志/var/log/message中可看到实时防护的结果提示:

Dec 15 15:36:20 ip-172-31-29-112 clamd[2157]: /home/eicar.virus: Eicar-Signature FOUND

在配置文件中指定的日志文件/var/log/clamd.scan内,也可以看到:

Thu Dec 15 15:42:03 2022 -> /home/eicar.virus: Eicar-Signature FOUND

4、查看历史日志过滤结果

执行如下命令即可过滤结果只发现的病毒:

grep FOUND /var/log/clamd.scan

返回结果如下:

Thu Dec 15 15:42:03 2022 -> /home/eicar.virus: Eicar-Signature FOUND
Fri Dec 16 03:50:11 2022 -> /home/eicar.virus: Eicar-Signature FOUND
Wed Dec 21 10:33:07 2022 -> /home/eicar.virus: Eicar-Signature FOUND

5、设置定期扫描的计划任务

除了实时检测外,实现病毒防护另一个主要途径是定期进行全盘扫描,例如每晚对整个磁盘进行100%的手工扫描。这个步骤可以通过计划任务进行。

新建计划任务配置文件/etc/cron.daily/fullscan,添加如下:

#!/bin/sh
/bin/clamscan -r / -i -l /var/log/clamd.scan

以上命令中,-r /表示对本机根目录上所有文件、文件夹和子文件夹进行递归的扫描,-i表示只输出受影响的文件,-l /var/log/clamd.scan表示将扫描日志写入到特定文件中,下文将配置集中的日志上报。

然后将这个文件设置为可执行权限。

chmod +x /etc/cron.daily/fullscan

这样即可完成每日全盘扫描,并将日志输出到特定文件。

四、集中上报扫描结果

不管是手工发起的扫描,还是按需扫描(On-access scanning),其扫描结果都会写入/etc/clamd.d/scan.conf配置文件中指定的日志/var/log/clamd.scan。因此这意味着,只要对这个日志进行监控即可满足集中上报的需求。

1、安装CloudWatch Agent

这里以Amazon Linux 2系统为例,安装Cloudwatch Log Agent进行日志采集。Cloudwatch Log Agent的新一代被称为Unified Agent,前一代被称为Previously Agent。这两个版本的说明文档都在本文末尾的参考链接中。本文使用前一代Previously Agent进行配置。执行如下命令安装:

yum update -y
yum install -y awslogs

安装成功。

2、确保EC2有CloudWatch写入日志的权限

从EC2向CloudWatch上传日志需要AWS API操作权限。常见的方法有两种,1是安装AWSCLI并设置正确的密钥;2是通过EC2 IAM Profile的方式为EC2挂载对应权限。本文采用方法2。具体如何给EC2挂载IAM Profile可以参考这篇使用Session Manager登录EC2的文档

确定了当前EC2在使用的IAM Profile后,为当前这个IAM Role再增加一个新的policy,名为:

CloudWatchAgentServerPolicy

这个IAM Policy是AWS内置的托管Policy,所有AWS账号内都默认带有这个Policy。这个Policy赋予EC2创建日志组(CreateLogGroup)、创建日志流(CreateLogStream)和写入日志(PutLogEvents)的权限。

如果EC2之前已经具有了IAM Profile,那么挂载好的新的Policy后等待数秒钟,不需要重启EC2即可生效。如果之前EC2没有挂载过IAM Profile,那么完成挂载后可能要等待几分钟,如果长时间没有生效,可重启下EC2以确保新的IAM Profile立刻生效。

3、注释掉默认采集的系统日志以节约日志存储成本

按照前文通过yum方式安装的配置文件路径在/etc/awslogs/awslogs.conf。编辑这个配置文件。在这个配置文件的末尾已经有一段预设的参数负责上传/var/log/messages的日志。这一段建议都注释掉,减少从EC2上传的日志的体积,然后手工配置需要上传的ClamAV的扫描日志。

如下一段是建议注释掉的日志。

[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages

4、新加入ClamAV日志的配置段

前文配置中已经有生成日志/var/log/clamd.scan,因此可分析这个日志文件的输出格式,然后编写有针对性的如下一段:

[clamav]
log_group_name = clamav
log_stream_name = {instance_id}
initial_position = start_of_file
datetime_format = %a %b %d %H:%M:%S %Y
file = /var/log/clamd.scan
buffer_duration = 5000

将以上这一段配置文件加入配置文件/etc/awslogs/awslogs.conf的末尾,保存后继续下一步。

5、设置上报的Region然后启动服务

编辑配置文件/etc/awslogs/awscli.conf,修改默认region设置。如果不修改,默认会上传日志到us-east-1区域。因此需要改成应用所在的区域,例如本文是新加坡区域(ap-southeast-1)。

[plugins]
cwlogs = cwlogs
[default]
region = ap-southeast-1

配置文件调整好后,启动服务。

systemctl start awslogsd
systemctl enable awslogsd

6、通过CloudWatch日志组查看日志

进入CloudWatch Log Groups日志组界面,找到日志组的名称,按照上一步配置文件中名称是clamav。如下截图。

进入日志组后,如果有多个EC2都安装了CloudWatch Log Agent,那么这里会出现多个Log Streams,每一个的名字就是EC2的ID。

点击其中一台EC2的名称,向下滚动即可看到最新的日志。如下截图。

日志集中采集配置成功后,就可以进一步去配置统一告警。

注意:同一个病毒文件被多次访问,在日志中会形成多条FOUND记录,也会触发多个告警。

五、设置CloudWatch Log Groups发现病毒后的集中告警

CloudWatch Log Groups可以采集多个EC2的日志,对多个EC2的病毒扫描结果可以过滤关键字来触发告警。

本阶段配置,如果觉得跟上操作有难度,可观看这个视频

1、设置CloudWatch Log Groups Metrics

进入CloudWatch的Log Groups日志组界面,点击第二个标签页Metric filters,点击右侧按钮Create metric filter创建新的过滤器。如下截图。

在弹出的向导第一步,输入新建特征的关键字。这里在Filter pattern对话框内输入FOUND,注意是英文的全大写,与日志中找到病毒时候提示的关键信息一致。然后在Test pattern位置,从下拉框中选择当前已经有的几个EC2节点之一作为测试。选中节点ID名称后,下方的Log event message将自动带出来前一步配置的从EC2集中提取的/var/log/clamd.scan日志文件。这时候按下Test pattern按钮,在下方的Show test results部分也会打出来验证关键字的结果。通过测试可以看到,发现病毒后日志的关键字是FOUND。现在点击屏幕右下角的按钮Next进入下一步配置。如下截图。

在向导的第二步,设置Metric的名称,在页面上方Filter name的位置输入ClamAV,在下方Metric namespace的位置输入clamav/found,在Metric name的位置输入在VIRUSFOUND。然后向下滚动页面。如下截图。

将页面向下滚动后,继续输入信息。在Metric value位置输入值是1,表示每次遇到FOUND关键字则统计值加1。在Default value位置输入默认值0,在Unit单位的下拉框中选择计数单位是 Count 。然后点击右下角的Next按钮继续。如下截图。

在向导的最后一步,点击Create metric filter按钮完成创建。如一下截图。

创建Metric完成。点击名字即可跳转到CloudWatch Metric界面查看详情。如下截图。

点击Metrics可加载数据。如下截图。

点击第一个标签页浏览Browse,然后从下方选择自定义的名称VIRUSFOUND,然后再点击第三个标签页Graphed metrics。如下截图。

进入第三个标签页Graphed metrics后,从下方找到统计Statistic列,点击下拉框,将页面上默认的average平均值改为Sum求和。如下截图。

对于一个新创建的Metric,可能只有一个数据点显示为0,因为缺少历史数据而不是特别直观。当运行了一段时间后,如果不定期的间隔发现了病毒,其显示效果如下截图。

上图的阅读方法是:在FOUND指标不为零的时间点即表示发现了病毒。基于这样的统计数据,就可以进一步定义告警了。为了后续查询方便起见,当前浏览器地址栏的全路径可以被加入到收藏夹,便于以后查询。

2、创建Alarm告警

创建告警的发起界面从CloudWatch Log Groups的界面,点击第二个标签页Metric filters,点击选中之前步骤新建的metric,然后点击右上角的Create alarm。如下截图。

在创建告警向导的第一步,在Metric name位置系统自动带出了之前输入的VIRUSFOUND名称,在Statistic位置自动带出了Sum表示求和,在Period位置自动带出了选项5 minutes五分钟内。确认这些选项正确,然后向下滚动页面继续。如下截图。

在创建向导的下半部分,选择Threshold typeStatic静态,选择值是Greater表示大于,选择than的数字是0。由此表示,只要此值大于0,就意味着发现了病毒,然后发出告警。点击下一步继续。如下截图。

在配置告警向导的第二步,选择Alarm state triggerIn alarm,选择通过SNS Topic的方式是Create new topic新建一个SNS Topic。在下方Create a new topic的位置输入新的SNS Topic名字clamavfound (注意不要有空格),然后下方输入要订阅这个Topic的邮箱用于接收告警。输入完成后,点击Create topic按钮创建SNS Topic。如下截图。

点击创建SNS Topic后,页面上的显示信息会发生变化,这里会自动刷新加载出来刚创建的SNS Topic并显示刚才订阅SNS的邮箱。接下来继续将页面向下滚动,跳过本页上其他配置,点击下一步。如下截图。

在向导第三步,输入告警的名称,输入友好显示信息。此信息只能在AWS控制台界面显示,告警邮件将是默认的文本信息。输入完毕后点击下一步继续。如下截图。

在向导的第四步,预览下刚才输入的配置,无需修改。将页面向下滚动到最下方,点击右下角的Create alarm按钮完成创建。如下截图。

创建完成后,页面就会显示出来刚才新配置的告警信息ClamAV VIRUS FOUND。此外页面上方还会有蓝色信息提示,提示刚才订阅SNS Topic的邮箱尚未进行验证。

接下来完成邮箱验证,即可接收告警信息。

3、验证SNS Topic订阅的邮箱地址并收取告警信息

在本地计算机上访问订阅上一步订阅SNS Topic时候输入的邮箱,邮箱内会收到如下一封英文邮件。

You have chosen to subscribe to the topic: arn:aws:sns:ap-southeast-1:1234567890123:clamavfound

To confirm this subscription, click or visit the link below (If this was in error no action is necessary): Confirm subscription

Please do not reply directly to this email. If you wish to remove yourself from receiving all future SNS subscription confirmation requests please send an email to sns-opt-out

这个邮件中会提供一个带有超链接的Confirm subscription按钮,点击这个网址,即可打开默认浏览器完成邮箱地址的确认。

确认后浏览器显示信息如下截图。

至此确认订阅完成。

如果希望查看CloudWatch告警配置,可以通过CloudWatch的All alarms菜单进入。点击上一步配置的告警名称ClamAV VIRUS FOUND后,即可在右侧加载出来告警信息。如下截图。

当有出发告警信息时候,去检查邮箱,可以看到告警邮件。

告警邮件中可以看到,指示是否发现病毒的Metric即clamav/found的数值大于0,因此触发了告警。

由此即实现了通过CloudWatch Log Groups、Metric和SNS Topic组合,在ClamAV发现病毒进行统一告警。

六、参考文档

Github软件源代码仓库:

https://github.com/Cisco-Talos/clamav

ClamAV On-access scanning配置说明:

https://docs.clamav.net/manual/OnAccess.html

安装前一代Cloudwatch Logs Agent(本文使用此版本部署)

https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html

前一代Cloudwatch Logs Agent配置文件参数说明:

https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/logs/AgentReference.html

新一代Cloudwatch Logs Agent统一日志(本文未采用此版本仅供参考):

https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/logs/UseCloudWatchUnifiedAgent.html

示例:CloudWatch Log对字词的出现次数进行计数

https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/logs/CountOccurrencesExample.html


全文完。