Qmail-Scanner 和 ClamAV 使用指南

Steve Peace

Gregory L. Porter -

版本 1.0 版

编辑

Todd Hawley

09/19/2004

修订历史
修订 1.009/19/2004修订者: glp
初始版本,由 TLDP 审核
修订 0.908/01/2004修订者: glp
转换为 DocBook 格式
修订 0.407/01/2004修订者: srp
第一个 HTML 公开草案

本 HOWTO 描述了如何将 ClamAV(一个反病毒附件扫描器)和 Qmail-Scanner(一个反病毒消息内容扫描器)与现有的 qmail 电子邮件服务器安装集成。


目录
1. 简介
1.1. 本文档是什么:
1.2. 本文档不是什么:
1.3. 致谢
1.4. 版权
1.5. 免责声明
1.6. 新闻
2. 先决条件
3. ClamAV
3.1. 什么是 ClamAV?
3.2. 安装 ClamAV
3.3. 测试
3.4. 更新病毒库
3.5. 设置 Clamd 并与 Daemontools 一起使用
4. Qmail-Scanner
4.1. 什么是 Qmail-Scanner?
4.2. 安装 Qmail-Scanner 的先决条件
4.3. 安装 Qmail-Scanner
4.4. 所有权
4.5. 测试
5. 配置 qmail 以使用 qmail-scanner-queue.pl
5.1. 更改您的 Tcp 规则
5.2. 增加您的 Softlimit
6. 结论
A. 推荐阅读和其他资源
B. 脚本
C. 软件
D. GNU 自由文档许可证
D.1. 序言
D.2. 适用性和定义
D.3. 逐字复制
D.4. 批量复制
D.5. 修改
D.6. 合并文档
D.7. 文档集合
D.8. 与独立作品的聚合
D.9. 翻译
D.10. 终止
D.11. 本许可证的未来修订
D.12. 附录:如何在您的文档中使用本许可证

第 1 章. 简介

1.1. 本文档是什么

本文档最初是我记录为我的雇主的电子邮件系统重新创建 Qmail-Scanner 和 ClamAV 部署的过程和所需阅读材料的方式。我不是作家,也不是程序员。我只是一个卑微的系统管理员,在网上查找所有使 Qmail-Scanner 与 ClamAV 一起工作的信息时感到沮丧。本 HOWTO 将记录我为使 Qmail-Scanner 和 ClamAV 协同工作而采取的步骤。这是正确的方法吗?谁知道呢,它对我有效。我从许多来源“提取”了大量信息片段。请参阅致谢。本文档的最新版本可以在 http://stevepeace.no-ip.org 找到。


1.2. 本文档不是什么

本文档不是 ClamAV、Qmail-Scanner、qmail、daemontools、Linux、Un*x、FreeBSD、Perl 等的综合信息来源。我不声称自己了解所有的一切。就像我之前说过的,这对我有用,但可能对你无效。如果您不知道如何使用特定的操作系统、工具或软件,本 HOWTO 将无法帮助您!我坚信 RTFM(阅读他妈的手册)。因此,请务必在遵循本 HOWTO 之前查看附录 A 和免责声明。


1.3. 致谢

我要感谢以下人员和团体

Jason Haar(Qmail-Scanner 作者)
Jesse D. Guardiani(原始 clamd+daemontools HOWTO 作者)
整个 ClamAV 团队(ClamAV 作者)
Dan Bernstein(qmail 和 daemontools 作者)
Dave Sill(lfwq 作者)
Bruce Guenter(qmailqueue 补丁作者)
Mark Simpson(TNEF 解包器作者)
Double Precision Inc. (maildrop 作者)
CPAN.org (Perl 模块)


1.4. 版权

版权所有 (c) 2004 Steven R. Peace。

根据 GNU 自由文档许可证 1.2 版或自由软件基金会发布的任何后续版本的条款,允许复制、分发和/或修改本文档;不包含不变部分,不包含封面文本,也不包含封底文本。许可证副本包含在题为“GNU 自由文档许可证”的部分中。

本 HOWTO 是自由文档;您可以根据 GNU 自由文档许可证的条款重新分发和/或修改它。本文档的发布目的是希望它有用,但不作任何担保;甚至不包含适销性或特定用途适用性的暗示保证。


1.5. 免责声明

我声明对本文档的内容不承担任何潜在责任。使用本文档的概念、示例和/或任何其他信息或内容完全由您自行承担风险。

所有版权均归其所有者所有,除非另有明确说明。本文档中术语的使用不应被视为影响任何商标或服务标志的有效性。

特定产品或品牌的命名不应被视为认可。

强烈建议您在进行重大安装之前备份系统,并在定期备份。


1.6. 新闻

文档主页可以在 http://stevepeace.no-ip.org 找到。请在此处查看最新版本。


第 2 章. 先决条件

您应该已经安装了一个运行正常的 qmail 服务器和 daemontools。您的服务器还需要

ClamAV 先决条件

Zlib 和 zlib-devel 软件包
Gcc 编译器(2.9x 或 3.x)
Bzip2 库(推荐)

Qmail-Scanner 先决条件

qmail 1.03
来自 Maildrop 1.3.8+ 的 Reformmime
Perl 5.005_03+
Perl 模块 Time::HiRes
Perl 模块 DB_File
Perl 模块 Sys::Syslog
Mark Simpson 的 TNEF 解包器
Bruce Guenter 的 QMAILQUEUE 补丁


第 3 章. ClamAV

3.1. 什么是 ClamAV?

来自 ClamAV 网站

“Clam AntiVirus 是一个用于 UNIX 的 GPL 反病毒工具包。该软件的主要目的是与邮件服务器集成(附件扫描)。该软件包提供了一个灵活且可扩展的多线程守护程序、一个命令行扫描器和一个用于通过 Internet 自动更新的工具。这些程序基于与 Clam AntiVirus 软件包一起分发的共享库,您可以将其与您自己的软件一起使用。最重要的是,病毒数据库会保持更新。”


3.2. 安装 ClamAV

http://www.clamav.net 下载 ClamAV 源代码。在编写本 HOWTO 时,最新版本是 0.65。

#tar -xvzf clamav-0.65.tar.gz 
#cd clamav-0.65 #groupadd clamav
#useradd clamav -g clamav -c "Clam AntiVirus" -s /nonexistent .
#/configure
#make 
#make install 
#cd ..
			

3.3. 测试

只要 make 和 make install 在没有错误的情况下完成,您现在就可以测试您的安装了(如果您遇到错误,请查看 tar 包中包含的 ClamAV 文档。您也可以访问 ClamAV 网站以获取一些有用的提示)。要测试您的安装,请输入

#clamscan -r -l scan.txt clamav-0.65

Clamscan 应该在 clamav-0.65/test 目录中找到一个测试病毒(这不是真正的病毒),并将其记录到 scan.txt 日志文件中。

现在您需要配置 ClamAV 守护程序 clamd 以进行测试。

#vi /usr/local/etc/clamav.conf

注释掉 clamav.conf 中的“Example”行并保存。

#clamdscan -l scan.txt clamav-0.65

这应该提供类似于您上面输入的 clamscan 命令的输出。


3.4. 更新病毒库

现在我们需要更新我们的病毒定义。Clamscan 包含一个实用程序 freshclam 来处理这个问题。Freshclam 会自动从 root 用户更改为您在安装期间创建的 clamav 用户。首先,创建一个 freshclam 可以记录的日志文件。

#touch /var/log/clam-update.log
#chmod 600 /var/log/clamupdate.log
#chown clamav /var/log/clamupdate.log

现在启动 freshclam

#freshclam -d -c 6 -l /var/log/clam-update.log
			

这将每天检查六 (6) 次新的病毒定义数据库。检查 /var/log/clam-update.log 文件。它应该看起来像这样

-----------------------------------------------------------------------------------------------------
ClamAV update process started at Wed Jan 28 17:49:48 2004
main.cvd is up to date (version: 19, sigs: 19987, f-level: 1, builder: ddm)
daily.cvd updated (version: 111, sigs: 597, f-level: 1, builder: tomek)
Database updated (20584 signatures) from database.clamav.net (81.4.91.185).
-----------------------------------------------------------------------------------------------------
			

现在将 freshclam -d -c 6 -l /var/log/clam-update.log 添加到您的启动脚本中。

如果您愿意,您还可以设置一个 cron 作业,每 6 小时更新一次病毒库。

#vi /etc/crontab
			
0 6 * * * root /usr/local/bin/clamscan
			

3.5. 设置 Clamd 并与 Daemontools 一起使用

编辑 /etc/clamd.conf 并进行以下更改。

#vi /etc/clamd.conf

取消注释“LogSyslog”
取消注释“StreamSaveToDisk”
取消注释“MaxThreads”并将值更改为“30”
取消注释“User”并将值更改为“qscand”
取消注释“Foreground”
取消注释“ScanMail”

创建 clamav 目录。

#mkdir -p /usr/local/clamav/bin

现在为 clamd 创建一个启动/关闭脚本。复制并粘贴下面显示的脚本。此脚本由 Jesse D. Guardiani 编写。

     
#vi /usr/local/clamav/bin/clamdctl

#!/bin/sh

# For Red Hat chkconfig
# chkconfig: - 80 30
# description: the ClamAV clamd daemon

PATH=/usr/local/clamav/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin
export PATH

case "$1" in
  start)
    echo "Starting clamd"
    if svok /service/clamd ; then
      svc -u /service/clamd
    else
      echo clamd supervise not running
    fi  
    if [ -d /var/lock/subsys ]; then
      touch /var/lock/subsys/clamd
    fi
    ;;
  stop)
    echo "Stopping clamd..."
    echo "  clamd"
    svc -d /service/clamd
    if [ -f /var/lock/subsys/clamd ]; then
      rm /var/lock/subsys/clamd
    fi
    ;;
  stat)
    svstat /service/clamd
    svstat /service/clamd/log
    ;;
  restart)
    echo "Restarting clamd:"
    echo "* Stopping clamd."
    svc -d /service/clamd
    echo "* Sending clamd SIGTERM and restarting."
    svc -t /service/clamd
    echo "* Restarting clamd."
    svc -u /service/clamd
    ;;
  hup)
    echo "Sending HUP signal to clamd."
    svc -h /service/clamd
    ;;
  help)
    cat <<HELP
   stop -- stops clamd service (smtp connections refused, nothing goes out)
  start -- starts clamd service (smtp connection accepted, mail can go out)
   stat -- displays status of clamd service
restart -- stops and restarts the clamd service
    hup -- same as reload
HELP
    ;;
  *)
    echo "Usage: $0 {start|stop|stat|restart|hup|help}"
    exit 1
    ;;
esac

exit 0


			

使 clamdctl 可执行并链接到路径

#chmod 755 /usr/local/clamav/bin/clamdctl
#chown clamav /usr/local/clamav/bin/clamdctl
#ln -s /usr/local/clamav/bin/clamdctl /usr/local/bin

为 clamd 服务创建 supervise 目录

#mkdir -p /usr/local/clamav/supervise/clamd/log

现在您必须创建 /usr/local/clamav/supervise/clamd/run 文件,或者只需复制并粘贴下面显示的脚本。此脚本也是由 Jesse D. Guardiani 创建的

vi /usr/local/clamav/supervise/clamd/run

#!/bin/sh
#
# --------------------------------------------------
# run
#
# Purpose     - Start the clamd daemon/service.
#                               
# Author      - Jesse D. Guardiani
# Created     - 09/10/03
# Modified    - 09/25/03
# --------------------------------------------------
# This script is designed to be run under DJB's
# daemontools package.
#         
#  ChangeLog
#  ---------
#
#  09/25/03 - JDG
#  --------------
#  - Changed clamd user to qscand in compliance with
#    the change to qmail-scanner-1.20rc3
#
#  09/10/03 - JDG
#  --------------
#  - Created
# --------------------------------------------------
# Copyright (C) 2003 WingNET Internet Services
# Contact: Jesse D. Guardiani (jesse at wingnet dot net)
# --------------------------------------------------

lockfile="/tmp/clamd"   # Location of clamd lock file
path_to_clamd="/usr/local/sbin/clamd"
                        # Location of the clamd binary
BAD_EXIT_CODE=1         # The exit code we use to announce that something bad has happened

# The following pipeline is designed to return the pid of each
# clamd process currently running.
get_clam_pids_pipeline=`ps -ax | grep -E "${path_to_clamd}\$" | grep -v grep | awk '{print $1}'`


# --------------------------------------------------
# Generic helper functions
# --------------------------------------------------

# Basic return code error message function
die_rcode() {
	EXIT_CODE=$1
	ERROR_MSG=$2

	if [ $EXIT_CODE -ne '0' ]; then
		echo "$ERROR_MSG" 1>&2
		echo "Exiting!" 1>&2
		exit "$BAD_EXIT_CODE"
	fi
}


# --------------------------------------------------
# Main
# --------------------------------------------------

ps_clamd=""
ps_clamd="$get_clam_pids_pipeline"

if [ -n "$ps_clamd" ]; then
	pid_count="0"
	for pid in $ps_clamd
	do
		pid_count=`expr $pid_count + 1`
	done
	
	die_rcode $BAD_EXIT_CODE "Error: $pid_count clamd process(es) already running!"

fi

if [ -e "$lockfile" ]; then
	rm "$lockfile"
	exit_code="$?"
	die_rcode $exit_code "Error: 'rm $lockfile' call failed."
fi

exec /usr/local/bin/setuidgid qscand $path_to_clamd

# --
# END /usr/local/clamav/supervise/clamd/run file.
# --

Create the /usr/local/clamav/supervise/clamd/log/run file:

#vi /usr/local/clamav/supervise/clamd/log/run

#!/bin/sh
exec /usr/local/bin/setuidgid qscand /usr/local/bin/multilog t /var/log/clamd
			

使 run 文件可执行

#chmod 755 /usr/local/clamav/supervise/clamd/run
#chmod 755 /usr/local/clamav/supervise/clamd/log/run

现在设置日志目录

#mkdir -p /var/log/clamd
chown qscand /var/log/clamd

最后,将 supervise 目录链接到 /service

#ln -s /usr/local/clamav/supervise/clamd /service

* 注意:clamd 脚本将在创建这些链接后不久自动启动。如果您不想让它运行,请执行以下操作

#clamdctl stop

要启动 clamd 备份,请执行以下操作

#clamdctl start

第 4 章. Qmail-Scanner

4.1. 什么是 Qmail-Scanner?

来自 Qmail-Scanner 网站:“Qmail-Scanner 是一个附加组件,使 qmail 电子邮件服务器能够扫描所有网关电子邮件的某些特征(即内容扫描器)。它通常用于其反病毒保护功能,在这种情况下,它与商业病毒扫描器结合使用,但也使站点(在服务器/站点级别)能够对电子邮件做出反应,这些电子邮件在特定标头或特定附件文件名或类型(例如 *.VBS 附件)中包含特定字符串。它也可以用作审计或备份目的的存档工具。Qmail-Scanner 以比其他一些基于 Unix 的病毒扫描器更低的级别集成到邮件服务器中,从而获得更好的性能。它不仅能够扫描本地发送/接收的电子邮件,还能够扫描以中继身份跨越服务器的电子邮件。”


4.2. 安装 Qmail-Scanner 的先决条件

4.2.1. Maildrop

什么是 Maildrop

来自 maildrop 网站

maildrop Courier 邮件服务器 使用的邮件过滤器/邮件传递代理。”

您将不会在本安装中使用 Maildrop 或 Courier 邮件服务器。但是,Qmail-Scanner 需要 reformmime,它包含在 Maildrop 中。这是本 HOWTO 中提到 Maildrop 的唯一原因。

下载并解压缩最新版本的 Maildrop。请阅读 tar 包中包含的 INSTALL 文件。

#./configure
#make
#make install-strip
#make install-man

4.2.2. Perl 模块

Time::HiRes Perl 模块

来自 tar 包中的 README 文件

Time::HiRes 模块:高分辨率时间、睡眠和警报。“为 Perl 实现 usleep、ualarm 和 gettimeofday,以及实现 time、sleep 和 alarm 的包装器,这些包装器了解非整数秒。”

DB_File Perl 模块

来自 tar 包中的 README 文件

“DB_File 是一个模块,允许 Perl 程序利用 Berkeley DB 版本 1 提供的功能。(DB_File 可以构建 Berkeley DB 的版本 2、3 或 4,但它只支持 1.x 功能)”

下载 Time::HiRes 和 DB_File Perl 模块。这些模块可以从 www.cpan.org 获取(请参阅附录 C)。那里还有一个 HOWTO,它将解释 Perl 模块的安装过程。再次强调,请在安装之前阅读 tar 包中包含的说明并查看 README 信息。


4.2.3. Mark Simpson 的 TNEF 解包器

什么是 TNEF 解包器

此实用程序解压缩 ms-tnef 类型 MIME 附件。有关 MIME 类型附件的更好解释,请查看 http://www.ietf.org/rfc/rfc1521.txt?number=1521

下载软件包,并解压缩 tar 包。与 Maildrop 安装一样,您应该阅读 tar 包中包含的 INSTALL 文件。

#./configure
#./make check
#./make install

4.2.4. 补丁 qmail

如果您尚未这样做,请安装 Bruce Guenter 的 QMAILQUEUE 补丁。

要修补 qmail,请将补丁下载到您的 qmail 源代码目录。

#patch -p1<qmailqueue.patch
#./make setup check

4.3. 安装 Qmail-Scanner

我们现在准备安装 Qmail-Scanner。下载 Qmail-Scanner 的最新源代码。在编写本 HOWTO 时,它是 1.20。

创建一个用户,让 Qmail-Scanner 以该用户身份运行。

#groupadd qscand
#useradd qscand -g qscand -c "qmail scanner" -s /nonexistent

解压缩 tar 包并切换到 Qmail-Scanner 目录。

#tar -zxvf qmail-scanner-1.20.tar.gz
#cd qmail-scanner-1.20

运行 Configure 以自动检测系统上安装了哪些软件。查看输出以确保其正确。它应该看起来像这样

#./configure

This script will search your system for the virus scanners it knows
about, and will ensure that all external programs
qmail-scanner-queue.pl uses are explicitly pathed for performance
reasons.

It will then generate qmail-scanner-queue.pl - it is up to you to install it
correctly.

Continue? ([Y]/N) <PRESS ENTER>

Found tnef on your system! That means we'll be able to decode stupid
M$ attachments :-)


The following binaries and scanners were found on your system:

mimeunpacker=/usr/local/bin/reformime
unzip=/usr/bin/unzip
tnef=/usr/local/bin/tnef

Content/Virus Scanners installed on your System

clamuko=/usr/local/bin/clamdscan (which means clamscan won't be used as clamdscan is better)

Qmail-Scanner details.

log-details=0
fix-mime=1
debug=1
notify=sender,admin
redundant-scanning=no
virus-admin=root@mail  --substitute you domain here
local-domains='mail' --substitute your domain here
silent-viruses='klez','bugbear','hybris','yaha','braid','nimda','tanatos','sobig','winevar','palyh','fizzer','gibe','
cailont','lovelorn','swen','dumaru','sober','hawaii','holar-i'
scanners="clamuko_scanner"

If that looks correct, I will now generate qmail-scanner-queue.pl
for your system...
Continue? ([Y]/N)<PRESS ENTER>

			

现在输入

# ./configure ?install

这将安装 qmail-scanner-queue.pl 并创建必要的目录结构。您应该看到与之前类似的消息。再次强调,阅读脚本的输出以确保一切正确。如果正确,请按 ENTER 安装 Qmail-scanner。

如果 qmail 已成功安装,则 qmail-scanner-queue.pl 现在应该已安装。您应该在 /var/qmail/bin 中看到 qmail-scanner-queue.pl。

#ls /var/qmail/bin
/var/qmail/bin/qmail-scanner-queue.pl

如果您在 /var/qmail/bin 中没有看到 qmail-scanner-queue.pl,请再次执行 configure 脚本。请注意脚本的输出并验证所有设置是否正确。您也可以访问 Qmail-scanner 邮件存档,网址为 http://lists.sourceforge.net/mailman/listinfo/qmail-scanner-general


4.4. 所有权

为了使 Qmail-Scanner 能够使用 ClamAV,必须更改一些 ClamAV 所有权。如果您还记得,我们创建了一个 clamav 用户来运行 ClamAV,然后更改了权限,以便只有 clamav 用户可以运行它。现在我们需要为 qscand 用户提供使用 ClamAV 的权限。首先,更改 clamd supervise 目录的所有权。

#chown -R qscand /usr/local/clamav/supervise

现在更改 ClamAV 日志文件的所有权

#chown -R qscand /var/log/clamd

4.5. 测试

现在测试 Qmail-Scanner

#./contrib./test_instaltion.sh -doit
Sending standard test message - no viruses...done!
Sending eicar test virus - should be caught by perlscanner module...
				done!
Sending eicar test virus with altered filename - should only be caught
				by commercial anti-virus modules (if you have any)...
Sending bad spam message for anti-spam testing - In case you are using
				SpamAssassin... Done!

现在检查您的 postmaster 别名帐户的电子邮件。

您现在应该在 postmaster 的邮箱中有 4 封电子邮件

如果您在 postmaster 的邮箱中没有 4 封邮件,请执行以下操作:验证您是否正在检查正确的邮箱。

重新执行 qmail-scanner-queue.pl 的 configure 脚本。验证脚本输出中的“virus-admin”是否与您的 qmail postmaster 别名相同。

检查 qmail 以查看消息是否在队列中。如果它们在队列中,请尝试发出“qmailctl”flush 命令以强制传递。

如果一切都失败了,请查看 Qmail-Scanner 邮件列表存档,网址为 http://lists.sourceforge.net/mailman/listinfo/qmail-scanner-general


第 5 章. 配置 qmail 以使用 qmail-scanner-queue.pl

5.1. 更改您的 Tcp 规则

安装、配置和成功测试所有内容后,配置 qmail 以利用 Qmail-Scanner 和 ClamAV。如果您遵循了 Dave Sills 的 Life With qmail(请参阅附录 A:阅读资源)中的说明,您应该在 /etc 目录中有一个 tcp.smtp 文件。您必须编辑 tcp.smtp 文件以包含 QMAILQUEUE 变量。

	
#vi /etc/tcp.smtp

127.:allow,RELAYCLIENT="",QMAILQUEUE="/var/qmail/bin/qmail-queue"
10.:allow,RELAYCLIENT="",QMAILQUEUE="/var/qmail/bin/qmail-scanner-queue.pl"
:allow.QMAILQUEUE="/var/qmail/bin/qmail-scanner-queue.pl"
			

如您所见,我们通过将 QMAILQUEUE 变量设置为原始 qmail-queue,将 qmail-queue 用于所有本地传递。然后,我们将本地子网邮件传递更改为使用 qmail-scanner-queue.pl。这导致所有本地子网 SMTP 流量都由 Qmail-Scanner 和 ClamAV 扫描。此文件的最后一行扫描所有入站电子邮件。

添加 QMAILQUEUE 变量后,您必须重建 Qmail 的 cdb 文件。

#qmailctl cdb

5.2. 增加您的 Softlimit

如果您尝试发送电子邮件,您很可能会从客户端收到错误。错误消息会显示一些包含以下内容的内容

451 qq temporary problem (#4.3.0)

如果您遵循 Life with qmail,那么您在 /var/qmail/supervise/qmail-smtpd/run 文件中设置了内存限制。查找包含 softlimit 的行。它应该看起来像这样

exec /usr/local/bin/softlimit -m 2000000 \

此示例将 qmail-smtpd 的内存限制设置为 2M。在您进行所有更改后,qmail-smtpd 现在正在运行整个 Perl 解释器和 ClamAV。2M 永远不够。

每个系统都不同,并且有不同的要求。您需要进行一些实验才能找到适合您系统的 softlimit 的正确值。不要将 softlimit 设置为某个高值!如果您这样做,您将自找麻烦。为了找到您系统的最小值,我建议执行以下步骤

  • 将 softlimit 增加 1M

  • #qmailctl restart

  • 发送消息

  • 重复直到您可以成功发送电子邮件

找到最小值后,我建议将其增加 1.5M,以应对您的电子邮件服务器负载较重的情况。

之后,只需创建一个每日 cron 作业,运行 /var/qmail/bin/qmail-scan-queue.pl -z 以清理可能滞留在 /var/spool/qmailscan 中的任何丢弃的 SMTP 会话。


第 6 章. 结论

在遵循本 HOWTO 中的说明后,您现在可以对您的电子邮件消息更加安全感到自信。通过实施 Qmail-Scanner 和 clamav,您已成功为您的电子邮件系统和整体反病毒保护添加了另一层安全保障。当然,没有 100% 安全的电子邮件消息。此安装也不会取代健全的反病毒实践,但它应该使这些实践更容易实施和管理。


附录 A. 推荐阅读和其他资源

Dave Sills 编写的 Life with qmail http://www.lifewithqmail.org
D.J. Bernstein 编写的 qmail FAQ http://cr.yp.to/qmail/faq
Dan Bernstein 编写的 SMTP:简单邮件传输协议 http://cr.yp.to/smtp.html
D.J. Bernstein 编写的 Daemontools FAQ http://cr.yp.to/daemontools/faq
ClamAV FAQ http://www.clamav.net/faq.html#pagestart
Thomasz Kojm 编写的 ClamAV 用户手册 http://www.clamav.net/doc
Jason Haar 编写的 Qmail-Scanner:qmail 的内容扫描器 http://qmail-scanner.sourceforge.net
Qmail-Scanner FAQ http://qmail-scanner.sourceforge.net/FAQ.php
Jesse D. Guardiani 编写的 Clamd+daemontools howto http://clamav.elektrapro.com/doc/clamd_supervised/clamd-daemontools-guide.txt
qmail 邮件列表存档 http://www-archive.ornl.gov:8000/
Qmail-Scanner 列表存档 http://sourceforge.net/mailarchive/forum.php?forum=qmail-scanner-general
ClamAV 用户列表存档 http://news.gmane.org/gmane.comp.security.virus.clamav.user
ClamAV 病毒库列表存档 http://news.gmane.org/gmane.comp.security.virus.clamav.virusdb
Maildrop http://www.flounder.net/~mrsam/maildrop/
Perl 模块安装 HOWTO http://www.cpan.org/modules/INSTALL.html
Mime 类型 RFC http://www.ietf.org/rfc/rfc1521.txt?number=1521


附录 B. 脚本

这些是本 HOWTO 中包含的脚本。它们由 Jesse D. Guardiani 创建,可以在他的 clamd+daemontools HOWTO 中找到。

Clamdctl

#!/bin/sh

# For Red Hat chkconfig
# chkconfig: - 80 30
# description: the ClamAV clamd daemon

PATH=/usr/local/clamav/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin
export PATH

case "$1" in
  start)
    echo "Starting clamd"
    if svok /service/clamd ; then
      svc -u /service/clamd
    else
      echo clamd supervise not running
    fi  
    if [ -d /var/lock/subsys ]; then
      touch /var/lock/subsys/clamd
    fi
    ;;
  stop)
    echo "Stopping clamd..."
    echo "  clamd"
    svc -d /service/clamd
    if [ -f /var/lock/subsys/clamd ]; then
      rm /var/lock/subsys/clamd
    fi
    ;;
  stat)
    svstat /service/clamd
    svstat /service/clamd/log
    ;;
  restart)
    echo "Restarting clamd:"
    echo "* Stopping clamd."
    svc -d /service/clamd
    echo "* Sending clamd SIGTERM and restarting."
    svc -t /service/clamd
    echo "* Restarting clamd."
    svc -u /service/clamd
    ;;
  hup)
    echo "Sending HUP signal to clamd."
    svc -h /service/clamd
    ;;
  help)
    cat <<HELP
   stop -- stops clamd service (smtp connections refused, nothing goes out)
  start -- starts clamd service (smtp connection accepted, mail can go out)
   stat -- displays status of clamd service
restart -- stops and restarts the clamd service
    hup -- same as reload
HELP
    ;;
  *)
    echo "Usage: $0 {start|stop|stat|restart|hup|help}"
    exit 1
    ;;
esac

exit 0

/usr/local/clamav/supervise/clamd/run

vi /usr/local/clamav/supervise/clamd/run

#!/bin/sh
#
# --------------------------------------------------
# run
#
# Purpose     - Start the clamd daemon/service.
#                               
# Author      - Jesse D. Guardiani
# Created     - 09/10/03
# Modified    - 09/25/03
# --------------------------------------------------
# This script is designed to be run under DJB's
# daemontools package.
#         
#  ChangeLog
#  ---------
#
#  09/25/03 - JDG
#  --------------
#  - Changed clamd user to qscand in compliance with
#    the change to qmail-scanner-1.20rc3
#
#  09/10/03 - JDG
#  --------------
#  - Created
# --------------------------------------------------
# Copyright (C) 2003 WingNET Internet Services
# Contact: Jesse D. Guardiani (jesse at wingnet dot net)
# --------------------------------------------------

lockfile="/tmp/clamd"   # Location of clamd lock file
path_to_clamd="/usr/local/sbin/clamd"
                        # Location of the clamd binary
BAD_EXIT_CODE=1         # The exit code we use to announce that something bad has happened

# The following pipeline is designed to return the pid of each
# clamd process currently running.
get_clam_pids_pipeline=`ps -ax | grep -E "${path_to_clamd}\$" | grep -v grep | awk '{print $1}'`


# --------------------------------------------------
# Generic helper functions
# --------------------------------------------------

# Basic return code error message function
die_rcode() {
	EXIT_CODE=$1
	ERROR_MSG=$2

	if [ $EXIT_CODE -ne '0' ]; then
		echo "$ERROR_MSG" 1>&2
		echo "Exiting!" 1>&2
		exit "$BAD_EXIT_CODE"
	fi
}


# --------------------------------------------------
# Main
# --------------------------------------------------

ps_clamd=""
ps_clamd="$get_clam_pids_pipeline"

if [ -n "$ps_clamd" ]; then
	pid_count="0"
	for pid in $ps_clamd
	do
		pid_count=`expr $pid_count + 1`
	done
	
	die_rcode $BAD_EXIT_CODE "Error: $pid_count clamd process(es) already running!"

fi

if [ -e "$lockfile" ]; then
	rm "$lockfile"
	exit_code="$?"
	die_rcode $exit_code "Error: 'rm $lockfile' call failed."
fi

exec /usr/local/bin/setuidgid qscand $path_to_clamd

# --
# END /usr/local/clamav/supervise/clamd/run file.
# --

Create the /usr/local/clamav/supervise/clamd/log/run file:

#vi /usr/local/clamav/supervise/clamd/log/run

#!/bin/sh
exec /usr/local/bin/setuidgid qscand /usr/local/bin/multilog t /var/log/clamd
			

/usr/local/clamav/supervise/clamd/log/run

#!/bin/sh
exec /usr/local/bin/setuidgid qscand /usr/local/bin/multilog t /var/log/clamd
			

附录 C. 软件

qmail- http://www.qmail.org/netqmail-1.05.tar.gz
Daemontools- ftp://cr.yp.to/daemontools/daemontools-0.76.tar.gz
ClamAV- http://prodownloads.sourceforge.net/clamav/clamav-0.65.tar.gz
QMAILQUEUE 补丁- http://www.qmail.org/top.html#qmailqueue
MailDrop- http://download.sourceforge.net/courier
Time::HiRes - http://search.cpan.org/search?module=Time::HiRes
DB_File- http://search.cpan.org/search?module=DB_File
TNEF 解包器- http://sourcforge.net/projects/tnef
Qmail-Scanner- http://prodownloads.sourceforge.net/qmail-scanner/qmail-scanner-1.20.tgz?download
MIME 类型 RFC- http://www.ietf.org/rfc/rfc1521.txt?number=1521


附录 D. GNU 自由文档许可证

版本 1.2,2002 年 11 月

FSF 版权声明

版权所有 (C) 2000,2001,2002 自由软件基金会,公司,地址:59 Temple Place, Suite 330, Boston, MA 02111-1307 USA。 任何人均被允许复制和分发本许可证文档的逐字副本,但不允许更改它。


D.1. 序言

本许可证的目的是使手册、教科书或其他功能性和有用的文档在自由的意义上“自由”:确保每个人都拥有有效自由地复制和重新分发它,无论是否修改它,无论是商业用途还是非商业用途。其次,本许可证为作者和出版商保留了一种因其工作而获得荣誉的方式,同时不被视为对他人所做的修改负责。

本许可证是一种“反版权”,这意味着文档的衍生作品本身必须在相同的意义上是自由的。它补充了 GNU 通用公共许可证,后者是为自由软件设计的反版权许可证。

我们设计本许可证是为了将其用于自由软件的手册,因为自由软件需要自由文档:一个自由程序应该附带提供与软件相同自由的手册。但本许可证不限于软件手册;它可以用于任何文本作品,无论主题是什么,也无论它是否以印刷书籍的形式出版。我们主要为以指导或参考为目的的作品推荐本许可证。


D.2. 适用性和定义

本许可证适用于任何手册或其他作品,以任何媒介形式,其中包含版权持有者放置的声明,表明它可以根据本许可证的条款分发。此类声明授予在全球范围内、免版税、无限期地使用该作品的许可,但须遵守本文所述的条件。“文档”(Document),以下简称“文档”,是指任何此类手册或作品。公众的任何成员都是被许可人,并被称为“您”。如果您以需要版权法许可的方式复制、修改或分发作品,则表示您接受本许可证。

“修改版本”(Modified Version)的文档是指包含文档或其一部分的任何作品,无论是逐字复制,还是经过修改和/或翻译成另一种语言。

“二级节”(Secondary Section)是文档的命名附录或前言部分,专门处理文档的出版者或作者与文档的总体主题(或相关事项)的关系,并且不包含任何可以直接归入该总体主题的内容。(因此,如果文档部分是数学教科书,则二级节不得解释任何数学。)该关系可能是与主题或相关事项的历史联系,或关于它们的法律、商业、哲学、伦理或政治立场。

“不变节”(Invariant Sections)是某些二级节,其标题在声明文档根据本许可证发布的声明中被指定为不变节的标题。如果某个节不符合上述二级节的定义,则不允许将其指定为不变节。文档可能包含零个不变节。如果文档未识别任何不变节,则不存在不变节。

“封面文本”(Cover Texts)是在声明文档根据本许可证发布的声明中列出的某些简短的文本段落,作为封面文本或封底文本。封面文本最多可以有 5 个单词,封底文本最多可以有 25 个单词。

文档的“透明”(Transparent)副本是指机器可读的副本,以规范向公众开放的格式表示,适用于使用通用文本编辑器(对于像素组成的图像)或通用绘图程序(对于绘图)直接修订文档,并且适用于输入到文本格式化程序或自动翻译为各种适用于输入到文本格式化程序的格式。以其他透明文件格式制作的副本,其标记或缺少标记,已被安排为阻止或阻止读者后续修改的,则不是透明的。如果图像格式用于大量文本,则该图像格式不是透明的。不“透明”的副本称为“不透明”(Opaque)。

透明副本的合适格式示例包括没有标记的纯 ASCII、Texinfo 输入格式、LaTeX 输入格式、使用公开可用的 DTD 的 SGML 或 XML,以及符合标准的简单 HTML、PostScript 或 PDF,专为人工修改而设计。透明图像格式的示例包括 PNG、XCF 和 JPG。不透明格式包括专有格式,这些格式只能由专有文字处理器读取和编辑;DTD 和/或处理工具通常不可用的 SGML 或 XML;以及某些文字处理器为仅输出目的而生成的机器生成的 HTML、PostScript 或 PDF。

“标题页”(Title Page)对于印刷书籍,是指标题页本身,以及为合法地容纳本许可证要求在标题页中出现的材料所需的后续页面。对于没有标题页的格式的作品,“标题页”是指最突出的作品标题外观附近的文本,位于文本正文的开头之前。

“标题为 XYZ 的节”(Section "Entitled XYZ")是指文档的命名子单元,其标题要么精确地是 XYZ,要么在文本之后包含用括号括起来的 XYZ,该文本将 XYZ 翻译成另一种语言。(此处 XYZ 代表下面提到的特定节名称,例如“致谢”、“题献”、“赞誉”或“历史”。)当您修改文档时,“保留标题”(Preserve the Title)此类节意味着它仍然是根据此定义“标题为 XYZ 的节”。

文档可能包含与声明本许可证适用于文档的声明相邻的担保免责声明。这些担保免责声明应被视为通过引用包含在本许可证中,但仅限于声明免除担保:这些担保免责声明可能具有的任何其他含义均无效,并且对本许可证的含义没有影响。


D.3. 逐字复制

您可以以任何媒介复制和分发文档,无论是商业用途还是非商业用途,前提是在所有副本中复制本许可证、版权声明以及声明本许可证适用于文档的许可证声明,并且您不得在本许可证的条款之外添加任何其他条件。您不得使用技术措施来阻止或控制您制作或分发的副本的阅读或进一步复制。但是,您可以接受报酬以换取副本。如果您分发的副本数量足够大,您还必须遵守第 3 节中的条件。

在上述相同条件下,您也可以出借副本,并且您可以公开展示副本。


D.4. 大量复制

如果您出版印刷版副本(或通常带有印刷封面的媒体副本)的文档,数量超过 100 份,并且文档的许可证声明要求封面文本,您必须将副本装在封面上,封面上清晰且易读地带有所有这些封面文本:正面封面的正面封面文本和背面封面的背面封面文本。两个封面还必须清晰且易读地标明您是这些副本的出版商。正面封面必须以相同突出且可见的方式呈现标题的所有词语的完整标题。您可以在封面上添加其他材料。更改仅限于封面的复制,只要它们保留文档的标题并满足这些条件,在其他方面可以被视为逐字复制。

如果任何封面的所需文本过于冗长而无法清晰地容纳,您应将列出的前几个文本(尽可能多地合理容纳)放在实际封面上,并将其余部分延续到相邻页面上。

如果您出版或分发文档的不透明副本超过 100 份,您必须随每个不透明副本包含一份机器可读的透明副本,或者在每个不透明副本中或随附声明一个计算机网络位置,公众可以通过该位置使用公共标准网络协议访问下载文档的完整透明副本,且不包含添加的材料。如果您使用后一种选择,您必须采取合理谨慎的步骤,当您开始大量分发不透明副本时,以确保该透明副本在声明的位置保持可访问状态,至少在您向公众分发该版本的最后一个不透明副本(直接或通过您的代理商或零售商)后一年内。

建议但不要求您在重新分发大量副本之前与文档的作者联系,让他们有机会为您提供文档的更新版本。


D.5. 修改

您可以根据上述第 2 节和第 3 节的条件复制和分发文档的修改版本,前提是您根据本许可证精确地发布修改版本,使修改版本扮演文档的角色,从而将修改版本的发布和修改授权给拥有其副本的任何人。此外,您必须在修改版本中执行以下操作:

GNU FDL 修改条件

  1. 在标题页(以及任何封面,如果有的话)上使用与文档标题以及先前版本标题不同的标题(如果存在先前版本,则应在文档的“历史”部分中列出)。如果该版本的原始出版商给予许可,您可以使用与先前版本相同的标题。

  2. 在标题页上,将修改版本中修改的作者的一个或多个人或实体,以及至少五位文档的主要作者(如果少于五位,则为所有主要作者)列为作者,除非他们免除您的此项要求。

  3. 在标题页上,将修改版本的出版商的名称声明为出版商。

  4. 保留文档的所有版权声明。

  5. 在其他版权声明旁边为您所做的修改添加适当的版权声明。

  6. 在版权声明之后立即包含许可证声明,允许公众根据本许可证的条款使用修改版本,格式如下面的附录所示。

  7. 在该许可证声明中保留文档许可证声明中给出的不变部分和要求的封面文本的完整列表。

  8. 包含本许可证的未修改副本。

  9. 保留标题为“历史”的部分,保留其标题,并在其中添加一项,至少说明标题页上给出的修改版本的标题、年份、新作者和出版商。如果文档中没有标题为“历史”的部分,则创建一个,说明标题页上给出的文档的标题、年份、作者和出版商,然后添加一项,描述修改版本,如前一句所述。

  10. 保留文档中给出的任何用于公众访问文档透明副本的网络位置,以及文档中给出的其所基于的先前版本的网络位置。这些可以放在“历史”部分中。您可以省略在文档本身之前至少四年出版的作品的网络位置,或者如果其引用的版本的原始出版商给予许可。

  11. 对于任何标题为“致谢”或“献词”的部分,保留该部分的标题,并在该部分中保留每个贡献者致谢和/或献词的所有实质内容和语气。

  12. 保留文档的所有不变部分,其文本和标题均不得更改。节号或等效内容不被视为节标题的一部分。

  13. 删除任何标题为“背书”的部分。修改版本中不得包含此类部分。

  14. 不要将任何现有部分重新命名为标题为“背书”或在标题上与任何不变部分冲突。

  15. 保留任何担保免责声明

如果修改版本包含符合次要部分条件并且不包含从文档复制的材料的新前言部分或附录,您可以选择将其中一些或全部部分指定为不变部分。为此,请将它们的标题添加到修改版本的许可证声明中的不变部分列表中。这些标题必须与任何其他节标题不同。

您可以添加一个标题为“背书”的部分,前提是它仅包含各方对您的修改版本的背书——例如,同行评审声明或文本已被某个组织批准为标准的权威定义。

您可以添加最多五个词的段落作为正面封面文本,以及最多 25 个词的段落作为背面封面文本,添加到修改版本中封面文本列表的末尾。任何一个实体(或通过其安排)只能添加一段正面封面文本和一段背面封面文本。如果文档已经包含同一封面的封面文本,该文本先前由您或由您代表的同一实体安排添加,您不得添加另一个;但是,在获得添加旧文本的先前出版商的明确许可后,您可以替换旧文本。

文档的作者和出版商不通过本许可证授予许可使用他们的姓名进行宣传或声明或暗示对任何修改版本的认可。


D.6. 合并文档

您可以将文档与根据本许可证发布的其他文档合并,根据上述第 4 节中针对修改版本的条款定义,前提是您在合并中包含所有原始文档的所有不变部分,不得修改,并在其许可证声明中将它们全部列为合并作品的不变部分,并且您保留其所有担保免责声明

合并后的作品只需要包含本许可证的一个副本,并且多个相同的不变部分可以用单个副本替换。如果存在多个同名但内容不同的不变部分,请通过在其末尾添加括号,注明该部分的原始作者或出版商的姓名(如果已知),或者添加一个唯一的数字,使每个此类部分的标题唯一。在合并作品的许可证声明中的不变部分列表中对节标题进行相同的调整。

在合并中,您必须合并各个原始文档中标题为“历史”的任何部分,形成一个标题为“历史”的部分;同样合并任何标题为“致谢”的部分,以及任何标题为“献词”的部分。您必须删除所有标题为“背书”的部分。


D.7. 文档集合

您可以制作一个集合,其中包含文档和根据本许可证发布的其他文档,并将各个文档中本许可证的单独副本替换为集合中包含的单个副本,前提是您在所有其他方面都遵循本许可证关于每个文档逐字复制的规则。

您可以从这样的集合中提取单个文档,并根据本许可证单独分发,前提是您将本许可证的副本插入到提取的文档中,并在关于该文档逐字复制的所有其他方面都遵循本许可证。


D.8. 与独立作品的聚合

文档或其衍生作品与其他单独且独立的文档或作品的汇编,在存储或分发介质的卷中或卷上,如果汇编产生的版权不用于限制汇编用户的合法权利超出个别作品允许的范围,则称为“聚合”。当文档包含在聚合中时,本许可证不适用于聚合中本身不是文档衍生作品的其他作品。

如果第 3 节的封面文本要求适用于文档的这些副本,那么如果文档小于整个聚合的一半,文档的封面文本可以放在将文档括在聚合中的封面上,或者如果文档是电子形式,则放在封面的电子等效物上。否则,它们必须出现在括住整个聚合的印刷封面上。


D.9. 翻译

翻译被视为一种修改,因此您可以根据第 4 节的条款分发文档的翻译版本。用翻译替换不变部分需要其版权持有人的特殊许可,但您可以包含一些或所有不变部分的翻译,以及这些不变部分的原始版本。您可以包含本许可证的翻译版本,以及文档中的所有许可证声明和任何担保免责声明,前提是您还包含本许可证的原始英文版本以及这些声明和免责声明的原始版本。如果本许可证或声明或免责声明的翻译版本与原始版本之间存在分歧,则以原始版本为准。

如果文档中的某个部分的标题为“致谢”、“献词”或“历史”,则(第 4 节)保留其标题(第 1 节)的要求通常需要更改实际标题。


D.10. 终止

除非本许可证明确规定,否则您不得复制、修改、再许可或分发文档。任何其他复制、修改、再许可或分发文档的尝试均属无效,并将自动终止您在本许可证下的权利。但是,根据本许可证从您处收到副本或权利的各方,只要这些各方保持完全合规,其许可证将不会终止。


D.11. 本许可证的未来修订

自由软件基金会可能会不时发布 GNU 自由文档许可证的新修订版本。此类新版本在精神上将与当前版本相似,但在细节上可能有所不同,以解决新的问题或疑虑。请参阅 https://gnu.ac.cn/copyleft/。

许可证的每个版本都给出了一个区分版本号。如果文档指定本许可证的特定编号版本“或任何更高版本”适用于它,您可以选择遵循该指定版本或自由软件基金会已发布的任何更高版本(非草案)的条款和条件。如果文档未指定本许可证的版本号,您可以选择自由软件基金会曾经发布的任何版本(非草案)。


D.12. 附录:如何在您的文档中使用本许可证

要在您编写的文档中使用本许可证,请在文档中包含本许可证的副本,并将以下版权和许可证声明放在标题页之后:

不变部分列表示例

版权所有 (c) 年份 您的姓名。 特此授权根据自由软件基金会发布的 GNU 自由文档许可证 1.2 版或任何更高版本的条款复制、分发和/或修改本文档;不包含不变部分,不包含正面封面文本,不包含背面封面文本。 许可证的副本包含在标题为“GNU 自由文档许可证”的部分中。

如果您有不变部分、正面封面文本和背面封面文本,请将“不包含...文本”行替换为以下内容:

不变部分列表示例

不变部分为 列出其标题,正面封面文本为 列出,背面封面文本为 列出。

如果您有不变部分而没有封面文本,或者三者的其他某种组合,请合并这两种备选项以适应具体情况。

如果您的文档包含重要的程序代码示例,我们建议并行地根据您选择的自由软件许可证(例如 GNU 通用公共许可证)发布这些示例,以允许在自由软件中使用它们。