一、实施背景与核心架构
档案软件单机版通常部署在物理隔离或内网环境中,主要风险来源于U盘介质导入、光盘挂载以及历史数据恢复。传统的杀毒软件往往无法针对档案软件特定的挂载目录进行精细化拦截。本文将采用ClamAV开源杀毒引擎配合Python实时监控脚本,构建一套零成本、高可用的文件级实时防护体系。
该架构的核心逻辑是:利用ClamAV作为后端扫描引擎,通过Python的watchdog库监控档案软件的接收目录(如C:\Archives\Incoming),一旦有新文件写入,立即触发扫描,发现病毒直接隔离或删除,并记录详细日志。
二、ClamAV服务端安装与配置
ClamAV是开源界最成熟的反病毒引擎,病毒库更新及时。我们需要先在Windows服务器上安装并配置它。
1. 下载并安装ClamAV
直接访问ClamAV官方Windows版本发布页下载稳定版安装包。为了避免兼容性问题,请务必下载.msi安装包。
下载地址:https://www.clamav.net/downloads
双击安装包,保持默认路径(通常为C:\Program Files\ClamAV)。安装完成后,不要立即启动服务,我们需要先修改配置文件以适应单机版环境。
2. 修改配置文件
进入安装目录,复制clamd.conf.sample并重命名为clamd.conf,使用记事本或VS Code打开。以下是必须修改的关键配置项,请删除对应行前面的注释符号并修改值:
- LogFile:指定日志路径,方便排错。
LogFile C:\Program Files\ClamAV\clamd.log
- LogTime:开启日志时间戳。
LogTime yes
- TCPSocket:开启TCP端口供Python调用,默认3310。
TCPSocket 3310
- DatabaseDirectory:确保指向病毒库目录。
DatabaseDirectory C:\Program Files\ClamAV\database
注意:配置文件中不能有多余的空行或无效字符,否则服务无法启动。
3. 注册并启动服务
打开命令提示符(CMD)并以管理员身份运行。执行以下命令将ClamAV注册为系统服务:
sc create ClamAV binPath= "C:\Program Files\ClamAV\clamd.exe --run-service -c C:\Program Files\ClamAV\clamd.conf" DisplayName= "ClamAV Daemon" start= auto
注意:命令中binPath=和start=后面必须有一个空格。
执行启动命令:
sc start ClamAV
此时,ClamAV后台服务已运行,监听3310端口等待扫描指令。接着更新病毒库,在CMD中执行:
"C:\Program Files\ClamAV\freshclam.exe"
三、Python实时监控脚本开发
我们需要编写一个Python脚本,充当“守门员”的角色。它需要监控指定目录,并将文件流发送给ClamAV检测。
1. 环境依赖安装
确保服务器已安装Python 3.8或更高版本。在CMD中执行以下命令安装必要的库:
pip install pyclamd watchdog
- pyclamd:用于与ClamAV的TCP端口通信。
- watchdog:用于监控文件系统事件(创建、修改、移动)。
2. 隔离目录准备
在D盘(或其他盘)创建一个隔离文件夹,用于存放带毒文件,防止直接删除导致无法追溯:

路径:D:\VirusQuarantine
3. 编写核心防护脚本
在C:\ArchivesGuard目录下新建文件guard.py,完整代码如下。请根据实际情况修改WATCH_PATH(档案软件接收目录)和QUARANTINE_PATH(隔离目录)。
```python
import os
import sys
import time
import shutil
import logging
import pyclamd
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
配置区域
档案软件的文件导入/接收目录,请修改为实际路径
WATCH_PATH = r'C:\Archives\Incoming'
病毒文件隔离目录
QUARANTINE_PATH = r'D:\VirusQuarantine'
ClamAV 连接配置
CLAMAV_HOST = '127.0.0.1'
CLAMAV_PORT = 3310
-
初始化日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(r'C:\ArchivesGuard\guard.log', encoding='utf-8'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class VirusHandler(FileSystemEventHandler):
def __init__(self, cd):
self.cd = cd
def on_created(self, event):
if event.is_directory:
return
self.scan_file(event.src_path)
def on_modified(self, event):
if event.is_directory:
return
防止重复扫描,简单判断文件是否写入完成(通过检查文件大小不再变化)
实际生产中建议加锁或延时,这里做简单延时处理
time.sleep(1)
self.scan_file(event.src_path)
def scan_file(self, file_path):
try:
if not os.path.exists(file_path):
return
logger.info(f"检测到文件变动: {file_path}, 开始扫描...")
调用ClamAV扫描文件
scan_result = self.cd.scan_file(file_path)
if scan_result is None:
logger.info(f"扫描通过: {file_path}")
else:
scan_result 返回格式为 { 'filepath': 'VIRUS_NAME' }
logger.warning(f"发现病毒威胁! 文件: {file_path}, 结果: {scan_result}")
self.quarantine_file(file_path)
except Exception as e:
logger.error(f"扫描过程出错: {e}")
def quarantine_file(self, file_path):
try:
filename = os.path.basename(file_path)
timestamp = time.strftime("%Y%m%d_%H%M%S")
target_name = f"{timestamp}_{filename}"
target_path = os.path.join(QUARANTINE_PATH, target_name)
移动文件到隔离区
shutil.move(file_path, target_path)
logger.info(f"已隔离病毒文件至: {target_path}")
可选:在此处调用API通知管理员
except Exception as e:
logger.error(f"隔离文件失败: {e}")
if __name__ == "__main__":
检查路径
if not os.path.exists(WATCH_PATH):
logger.error(f"监控目录不存在: {WATCH_PATH}")
sys.exit(1)
if not os.path.exists(QUARANTINE_PATH):
os.makedirs(QUARANTINE_PATH)
初始化ClamAV连接
try:
cd = pyclamd.ClamAV(host=CLAMAV_HOST, port=CLAMAV_PORT)
if not cd.ping():
logger.error("无法连接到ClamAV服务,请检查服务是否启动。")
sys.exit(1)
logger.info("成功连接ClamAV引擎。")
except Exception as e:
logger.error(f"ClamAV连接初始化失败: {e}")
sys.exit(1)
启动监控
event_handler = VirusHandler(cd)
observer = Observer()
observer.schedule(event_handler, WATCH_PATH, recursive=True)
observer.start()
logger.info(f"档案病毒防护引擎已启动,正在监控目录: {WATCH_PATH}")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
```
四、部署为Windows系统服务
为了保证脚本开机自启且稳定运行,我们不能只开一个CMD窗口。使用NSSM (Non-Sucking Service Manager)将Python脚本注册为系统服务是最佳实践。
1. 下载NSSM
下载地址:https://nssm.cc/download
下载解压后,将64位的nssm.exe复制到C:\Windows\System32\目录下,或直接在解压目录打开CMD。
2. 注册服务
在nssm.exe所在目录打开CMD,执行:
nssm install ArchiveGuard
此时会弹出NSSM配置窗口,按以下步骤填写:
- Path:选择Python的
pythonw.exe路径(使用pythonw可以避免弹出黑框,通常在C:\Users\[用户名]\AppData\Local\Programs\Python\Python39\pythonw.exe)。
- Startup directory:填写脚本所在目录,即
C:\ArchivesGuard。
- Arguments:填写脚本名称,即
guard.py。
点击“Install service”按钮。
3. 启动服务
在CMD中执行以下命令启动防护服务:
nssm start ArchiveGuard
若需查看运行日志,请打开C:\ArchivesGuard\guard.log。
五、效果验证与故障排查
部署完成后,必须进行有效性测试。我们使用标准的EICAR测试字符串,它本身无害,但会被所有杀毒软件识别为病毒。
1. 模拟病毒文件测试
在监控目录C:\Archives\Incoming下,新建一个文本文件,命名为eicar.com.txt,并粘贴以下内容:
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H
保存文件后,观察C:\ArchivesGuard\guard.log日志文件。你应该能在几秒钟内看到“发现病毒威胁”的日志,并且该文件会自动从Incoming目录消失,出现在D:\VirusQuarantine目录中。
2. 常见故障排查
现象:日志显示“无法连接到ClamAV服务”
排查:打开CMD执行netstat -an | findstr 3310。如果没有结果,说明ClamAV服务未启动。检查C:\Program Files\ClamAV\clamd.conf配置,确保TCPSocket未被注释,并尝试手动执行sc start ClamAV。
现象:文件未被隔离
排查:检查Python脚本的运行权限。确保档案软件写入文件时,Python脚本有权限读取该文件,且有权限移动该文件到隔离目录。建议将ArchiveGuard服务的登录身份设置为“Local System”。
现象:误报正常文件
排查:档案软件可能生成特定的临时文件或加密数据库文件。如果ClamAV频繁误报,可以在ClamAV配置中添加白名单,或者在Python脚本的scan_file方法中增加文件后缀名判断逻辑,直接跳过.tmp或.db文件。