深入解析Sendmail:配置、安全与性能优化
1. Sendmail与Amavisd的集成配置
在邮件系统中,有时会将Amavisd置于中间位置,使其作为传入邮件的
MAIL_HUB
和传出邮件的
SMART_HOST
。不过,这种方案是在Sendmail接受邮件进行投递后进行离线扫描的。若要进行在线扫描,可查看Amavisd - new文档中的
README.milter
文件。
在面向互联网的服务器上,将所有邮件传递给监听端口10024的Amavisd进程的关键配置行如下:
FEATURE(`stickyhost')
define(`MAIL_HUB', `esmtp:[127.0.0.1]')
define(`SMART_HOST', `esmtp:[127.0.0.1]')
define(`confDELIVERY_MODE', `q')
define(`ESMTP_MAILER_ARGS', `TCP $h 10024')
DAEMON_OPTIONS(`Name=receivingMTA')
最后一行配置有助于调试,因为能明确是接收的Sendmail、发送的Sendmail还是Amavisd记录了哪些消息。
扫描完成后,Amavisd将邮件传递给监听端口10025(而非通常的25端口)的仅用于排队的Sendmail进程,之后队列运行器会完成本地投递或将邮件发送到互联网。
在发送服务器上,设置如下配置可让Sendmail监听端口10025以接收来自Amavisd的邮件:
DAEMON_OPTIONS(`Addr=127.0.0.1, Port=10025, Name=transmittingMTA')
它会以
transmittingMTA
的名称记录信息或错误消息,以便与
receivingMTA
区分。
此外,还可调整一些设置(如性能限制),确保两个Sendmail实例协同工作。同时,要仔细考虑具体的检查内容、执行检查的进程以及检查顺序。
amavisd - new
发行版中的
README_FILES/README.sendmail - dual
文件是很好的参考资料。
2. Sendmail的安全配置
随着互联网的迅猛发展,像Sendmail这类接受任意用户输入并将其传递给本地用户、文件或shell的程序,常成为黑客攻击的目标。Sendmail与DNS甚至IP一样,正在尝试通过内置的认证和加密功能来解决一些基本的安全问题。
Sendmail支持SMTP认证和TLS(传输层安全,前身为SSL,安全套接层)加密。TLS引入了六个新的证书文件和密钥文件配置选项,访问数据库匹配的新操作可能要求认证必须成功。
2.1 所有权与权限
在Sendmail的世界里,有三个重要的用户账户:
DefaultUser
、
RunAsUser
和
TrustedUser
。
-
DefaultUser
:默认情况下,所有Sendmail的邮件程序都以
DefaultUser
身份运行,除非邮件程序的标志另有指定。若
/etc/passwd
文件中存在
mailnull
、
sendmail
或
daemon
用户,
DefaultUser
将使用该用户;否则,默认为UID 1和GID 1。建议使用
mailnull
账户和
mailnull
组,将其添加到
/etc/passwd
文件中,设置密码为星号,无有效shell,无主目录,默认组为
mailnull
,同时也要将其添加到组文件中。
mailnull
账户不应拥有任何文件。若Sendmail不以root身份运行,则邮件程序必须设置setuid位。
-
RunAsUser
:若设置了
RunAsUser
,Sendmail将忽略
DefaultUser
的值,以
RunAsUser
身份执行所有操作。若以setgid(到
smmsp
)方式运行Sendmail,提交的Sendmail会通过SMTP将邮件传递给真正的Sendmail,真正的Sendmail虽未设置setuid位,但会从启动文件以root身份运行。
RunAsUser
是Sendmail在打开与端口25的套接字连接后运行的UID。由于端口号小于1024的端口只能由超级用户打开,所以Sendmail最初必须以root身份运行,但之后可切换到不同的UID,这样能降低Sendmail被欺骗执行恶意操作时的损害风险。不过,不要在支持用户账户或其他服务的机器上使用此功能,它仅适用于防火墙或堡垒主机。
-
TrustedUser
:
TrustedUser
可拥有映射和别名文件,允许启动守护进程或重建别名文件,主要用于为需要对某些用户提供有限管理控制的Sendmail GUI界面提供支持。设置
TrustedUser
时,要确保保护其指向的账户,因为该账户易被利用获取root权限。
TrustedUser
与
TRUSTED_USERS
类不同,后者决定谁可以重写邮件的
From
行。
文件和目录权限对Sendmail的安全至关重要。以下是安全的设置建议:
| Path | Owner | Mode | What it contains |
| — | — | — | — |
| /var/spool/clientmqueue | smmsp:smmsp | 770 | Queue for initial submissions |
| /var/spool/mqueue | RunAsUser | 700 | Mail queue directory |
| /, /var, /var/spool | root | 755 | Path to mqueue |
| /etc/mail/* | TrustedUser | 644 | Maps, the config file, aliases |
| /etc/mail | TrustedUser | 755 | Parent directory for maps |
| /etc | root | 755 | Path to mail directory |
Sendmail会拒绝读取权限宽松的文件,如组或世界可写的文件,或位于组或世界可写目录中的文件。特别是对于别名文件或转发文件的完整路径,Sendmail要求非常严格。若要查看自己的权限设置是否符合Sendmail的要求,可运行
sendmail -v -bi
命令,
-bi
标志会初始化别名数据库并警告不适当的权限设置。
Solaris有一个实用程序
check - permissions
,它能理解Sendmail的安全标准并报告不安全的路径或文件,可根据命令行标志检查调用用户或所有用户的权限。此外,若指向
.forward
文件的目录路径权限宽松且该文件的链接计数大于1,Sendmail将不再读取该文件。
可以使用
DontBlameSendmail
选项关闭上述许多限制性文件访问策略,但不建议这样做。
2.2 更安全的邮件投递
建议使用
smrsh
代替
/bin/sh
作为程序邮件程序,使用
mail.local
代替
/bin/mail
作为本地邮件程序。这两个程序都包含在Sendmail发行版中。要将它们集成到配置中,可在
.mc
文件中添加以下行:
FEATURE(`smrsh', `path - to - smrsh')
FEATURE(`local_lmtp', `path - to - mail.local')
若省略显式路径,命令将默认位于
/usr/libexec
。可使用Sendmail的
confEBINDIR
选项更改二进制文件的默认位置。不同操作系统中Sendmail受限投递代理的位置如下:
| OS | smrsh | mail.local | sm.bin |
| — | — | — | — |
| sendmail | /usr/libexec | /usr/libexec | /usr/adm |
| Ubuntu | /usr/lib/sm.bin | /usr/lib/sm.bin | /usr/adm |
| SUSE | /usr/lib/sendmail.d/bin | /usr/lib/sendmail.d/bin | – |
| Red Hat | /usr/sbin | – | /etc/smrsh |
| Solaris | /usr/lib | /usr/lib | /var/adm |
| HP - UX | /usr/sbin | – | /usr/adma |
| AIX | /usr/sbin | – | /usr/adma |
smrsh
是一个受限的shell,它仅执行一个目录(默认是
/usr/adm/sm.bin
)中的程序,会忽略用户指定的路径,尝试在其已知安全的目录中查找所需命令,还会阻止使用某些shell元字符,如输入重定向符号
<
。
sm.bin
中允许使用符号链接,因此无需复制允许的程序。
vacation
程序是
sm.bin
的合适候选,但不要将
procmail
放在这里,因为它不安全。以下是一些示例shell命令及其可能的
smrsh
解释:
vacation eric # Executes /usr/adm/sm.bin/vacation eric
cat /etc/passwd # Rejected, cat not in sm.bin
vacation eric < /etc/passwd # Rejected, no < allowed
Sendmail的
SafeFileEnvironment
选项可控制当邮件通过别名或
.forward
文件重定向到文件时的写入位置。它会执行
chroot
系统调用,使文件系统的根不再是
/
,而是
/safe
或在
SafeFileEnvironment
选项中指定的路径。例如,将邮件定向到
/etc/passwd
文件的别名,实际上会将邮件写入
/safe/etc/passwd
。该选项还通过仅允许写入常规文件来保护设备文件、目录和其他特殊文件,除了提高安全性外,还能减轻用户错误的影响。一些站点将该选项设置为
/home
,以便在限制系统文件访问的同时允许访问主目录。邮件程序也可在chroot目录中运行。
2.3 隐私选项
Sendmail还有隐私选项,用于控制以下方面:
- 外部人员通过SMTP能了解到的站点信息。
- 对SMTP连接另一端主机的要求。
- 用户是否可以查看或运行邮件队列。
以下是隐私选项的可能取值及其含义:
| Value | Meaning |
| — | — |
| public | Does no privacy/security checking |
| needmailhelo | Requires SMTP HELO (identifies remote host) |
| noexpn | Disallows the SMTP EXPN command |
| novrfy | Disallows the SMTP VRFY command |
| needexpnhelo | Does not expand addresses (EXPN) without a HELO |
| needvrfyhelo | Does not verify addresses (VRFY) without a HELO |
| noverba | Disallows verbose mode for EXPN |
| restrictmailq | Allows only mqueue directory’s group to see the queue |
| restrictqrun | Allows only mqueue directory’s owner to run the queue |
| restrictexpand | Restricts info displayed by the -bv and -v flags |
| noetrnc | Disallows asynchronous queue runs |
| authwarnings | Adds warning header if outgoing message seems forged |
| noreceipts | Turns off delivery status notification for success return receipts |
| nobodyreturn | Does not return message body in a DSN |
| goaway | Disables all SMTP status queries (EXPN, VRFY, etc.) |
建议采取保守策略,在
.mc
文件中使用以下配置:
define(`confPRIVACY_OPTIONS', ``goaway, authwarnings, restrictmailq, restrictqrun'')
Sendmail的隐私选项默认值为
authwarnings
,上述配置会重置该值。注意使用双引号,某些版本的m4需要这样做以保护隐私选项值列表中的逗号。不同操作系统的默认隐私选项设置不同,如Red Hat、Solaris和AIX默认设置为
authwarnings
;SUSE和Ubuntu默认设置为
authwarnings, needmailhelo, novrfy, noexpn, and noverb
;HP - UX默认设置为
restrictqrun, goaway, and authwarnings
,是最安全的设置。
2.4 运行chrooted Sendmail
若担心Sendmail对文件系统的访问权限,可在chroot监狱中启动它。需在监狱中创建一个最小的文件系统,包括
/dev/null
、
/etc
的基本文件(
passwd
、
group
、
resolv.conf
、
sendmail.cf
、任何映射文件、
mail/*
)、Sendmail所需的共享库、Sendmail二进制文件、邮件队列目录和任何日志文件。可能需要调整列表以确保设置正确。使用
chroot
命令启动受限制的Sendmail,例如:
$ sudo chroot /jail /usr/sbin/sendmail -bd -q30m
2.5 拒绝服务攻击防范
拒绝服务攻击难以预防,因为无法事先确定一条消息是攻击还是有效的电子邮件。攻击者可能采取多种恶意手段,如用虚假连接淹没SMTP端口、用大邮件填满磁盘分区、阻塞传出连接和邮件轰炸等。Sendmail有一些配置参数可帮助减缓或限制拒绝服务攻击的影响,但这些参数也可能影响正常邮件。Milters可帮助系统管理员抵御长时间的拒绝服务攻击。
- MaxDaemonChildren选项 :限制Sendmail进程的数量,可防止系统被Sendmail工作淹没,但攻击者也可借此轻松关闭SMTP服务。
- MaxMessageSize选项 :有助于防止邮件队列目录被填满,但设置过低会导致正常邮件被退回。建议设置一个较高的限制,并告知用户该限制,以免他们的邮件被退回时感到惊讶。
- ConnectionRateThrottle选项 :限制每秒允许的连接数,可稍微减缓攻击速度。
- MaxRcptsPerMessage选项 :控制单个邮件允许的最大收件人数,可能会有帮助。
Sendmail一直能够根据系统负载平均拒绝连接(选项
REFUSE_LA
)或对邮件进行排队(
QUEUE_LA
)。
DELAY_LA
选项可让邮件继续流动,但会降低速率。尽管有这些保护措施,邮件轰炸仍会干扰正常邮件,且邮件轰炸可能非常恶劣。
2.6 SASL和TLS
-
SASL(简单认证和安全层)
:Sendmail支持RFC4954中定义的SMTP认证系统,该系统基于SASL(RFCs 4422和4752)。SASL是一种共享密钥系统,通常用于主机到主机的认证,需要为每对相互认证的服务器进行明确的安排。它常用于用户代理与MSA之间或站点内MSA与MTA之间。SASL是一种通用的认证机制,可集成到多种协议中。其框架有两个基本概念:授权标识符(如登录名)和认证标识符(如密码),可将它们映射到文件权限、账户密码、Kerberos票据等。SASL包含认证和加密组件。要在Sendmail中使用SASL,可从
ftp.andrew.dmu.edu/pub/cyrus - mail获取Cyrus SASL的副本。 -
TLS(传输层安全)
:TLS在RFC3207中定义,是另一种加密/认证系统,在Sendmail中作为SMTP的扩展
STARTTLS实现,甚至可以同时使用SASL和TLS。TLS设置稍复杂,需要一个证书颁发机构。可以付费让VeriSign颁发证书,也可以设置自己的证书颁发机构,或者使用OpenCA等。在转发邮件或接受主机连接时,使用强认证代替主机名或IP地址作为授权令牌。例如,access_db中的以下条目表示正在使用STARTTLS,发往secure.example.com域的邮件必须使用至少112位加密密钥进行加密,只有客户端进行身份验证后,才接受来自laptop.example.com域主机的邮件:
TLS_Srv:secure.example.com
ENCR:112
TLS_Clt:laptop.example.com
PERM+VERIFY:112
Sendmail公司的Greg Shapiro和Claus Assmann在网上提供了一些(略有过时)关于Sendmail安全的额外文档,可从
sendmail.org/~gshapiro
和
sendmail.org/~ca
获取,
~ca
中的索引链接特别有用。
3. Sendmail性能优化
Sendmail有多个配置选项可用于提升性能,以下将详细介绍这些对高流量邮件系统至关重要的选项和特性。若每小时需要发送100万封邮件且并非垃圾邮件发送者,使用Sendmail的商业版本可能是更好的选择。
3.1 投递模式
Sendmail有四种基本投递模式:后台模式、交互模式、队列模式和延迟模式。每种模式都代表了延迟和吞吐量之间的权衡:
-
后台模式
:立即投递邮件,但需要Sendmail派生一个新进程来完成。
-
交互模式
:同样立即投递,但由同一进程完成,并使远程端等待结果,此模式很少使用。
-
队列模式
:将传入邮件排队,由队列运行器在稍后时间进行投递。
-
延迟模式
:类似于队列模式,但还会延迟所有映射、DNS、别名和转发查找。
后台模式更注重低延迟,而延迟或队列模式则更倾向于高吞吐量。投递模式可通过
confDELIVERY_MODE
选项设置,默认值为后台模式。
3.2 队列组和信封拆分
队列组允许为外发邮件创建多个队列,并分别控制每个队列组的属性。它与信封拆分功能结合使用,可将具有多个收件人的邮件(如发送到邮件列表的邮件)分配到多个队列组。以下是使用队列组的几个关键配置原语示例:
# 示例配置
define('QUEUE_GROUP', 'group1')
define('QUEUE_GROUP', 'group2')
# 更多配置...
具体的配置和使用细节可参考相关文档,如O’Reilly的Sendmail书籍或
cf/README
文件。
3.3 队列运行器
Sendmail会派生自身的副本以执行邮件的实际传输。可以控制任意时刻运行的副本数量,甚至控制每个队列组所关联的副本数量。通过此功能,可在繁忙的邮件中心机器上平衡Sendmail和操作系统的活动。
有三个Sendmail选项可控制处理每个队列的队列运行器守护进程数量:
-
MAX_DAEMON_CHILDREN选项
:指定在任何时刻允许运行的Sendmail守护进程副本总数,包括运行队列和接受传入邮件的进程。
-
MAX_QUEUE_CHILDREN选项
:设置一次允许的最大队列运行器数量。
-
MAX_RUNNERS_PER_QUEUE选项
:如果在队列组定义中未使用
Runners=
(或
R=
)参数显式设置,则设置每个队列的默认运行器限制。
3.4 负载平均控制
Sendmail一直具备在系统负载平均过高时拒绝连接或对邮件进行排队而非投递的能力。然而,负载平均的粒度仅为一分钟,因此它并非用于平滑Sendmail资源消耗的精细工具。
DELAY_LA
原语允许设置一个负载平均值,当达到该值时,Sendmail应减慢速度。此时,它会在当前连接的SMTP命令之间以及接受新连接之前暂停一秒。默认值为0,表示关闭此机制。
3.5 处理队列中的不可投递邮件
邮件队列中的不可投递邮件会严重影响繁忙邮件服务器的性能。Sendmail有几个功能可帮助解决此问题:
-
FALLBACK_MX选项
:若邮件在首次尝试投递时失败,该选项会将邮件转交给另一台机器。主机器可快速处理有效地址的邮件,将有问题的邮件分流到备用机器。例如:
define('confFALLBACK_MX', 'mailbackup.atrust.com')
此配置将首次投递失败的邮件转发到
mailbackup.atrust.com
进行进一步处理。如果指定的主机在DNS中有多个MX记录,则可以有多个备用机器。
-
TO_ICONNECT选项
:设置初始连接和发送邮件尝试的超时时间。如果设置较短,更多工作将分流到备用MTA,但这能让主服务器在处理大型邮件列表时快速完成第一轮处理。
-
HOST_STATUS_DIRECTORY选项
:在备用机器上,该选项可帮助处理多次失败的情况。它指示Sendmail为每个发送邮件的主机维护一个状态文件,并在每次运行队列时使用该状态信息对主机进行优先级排序。此状态信息实际上实现了负缓存,允许在队列运行之间共享信息。对于处理包含大量无效地址的邮件列表的服务器来说,这是一个性能提升,但在文件I/O方面可能成本较高。例如:
define('confHOST_STATUS_DIRECTORY', '/var/spool/mqueue/.hoststat')
需要先创建该目录。如果以相对路径指定
.hoststat
目录,它将存储在队列目录下方。Sendmail会根据目标主机名创建自己的内部子目录层次结构。
另外,还可以设置最小队列年龄,使任何在初始尝试中无法投递的邮件在队列中停留的时间不少于该最小值。通常将此技术与更频繁运行队列的命令行标志(如
-q5m
)结合使用。如果队列运行器因一封坏邮件而挂起,另一个运行器将在5分钟后启动,从而提高可投递邮件的性能。整个队列将按满足最小停留时间的邮件批次进行处理。例如,在配置文件中包含以下内容并以
-bd -q5m
标志运行Sendmail:
define('confMIN-QUEUE_AGE', '27m')
这可能会使系统响应更迅速。
3.6 内核调优
如果计划使用UNIX或Linux机器作为高流量邮件服务器,需要修改内核的几个网络配置参数。以下是在Linux高流量邮件服务器上需要更改的参数及其建议值和默认值:
| Variable (relative to /proc/sys) | Default | Suggested |
| — | — | — |
| net/ipv4/tcp_fin_timeout | 180 | 30 |
| net/ipv4/tcp_keepalive_time | 7200 | 1800 |
| net/core/netdev_max_backlog | 300 | 1024 |
| fs/file_max | 4096 | 16384 |
| fs/inode_max | 16384 | 65536 |
要重置Linux机器上网络栈的参数,可使用shell的
echo
命令将值重定向到
/proc
文件系统中的相应变量。
总结
Sendmail作为一个强大的邮件传输代理,在配置、安全和性能优化方面有诸多要点需要关注。通过合理集成Amavisd、严格设置安全选项、优化性能配置以及进行必要的内核调优等操作,可以构建一个安全、高效的邮件系统。在实际应用中,需根据具体的业务需求和系统环境,灵活运用这些配置和优化策略,以确保邮件系统的稳定运行和良好性能。
以下是一个简单的mermaid流程图,展示了Sendmail处理邮件的大致流程:
graph LR
A[邮件接收] --> B{是否通过Amavisd扫描}
B -- 是 --> C[传递到队列]
B -- 否 --> D[处理异常]
C --> E{本地投递还是外发}
E -- 本地投递 --> F[本地邮件处理]
E -- 外发 --> G[外发邮件处理]
F --> H[完成投递]
G --> H
这个流程图概括了Sendmail从接收邮件到最终投递的主要步骤,有助于更好地理解整个邮件处理过程。
超级会员免费看
25

被折叠的 条评论
为什么被折叠?



