SMTP 服务器搭建完全指南 / 第 3 章:main.cf 配置详解
第 3 章:main.cf 配置详解
掌握
main.cf的每一个关键参数,才能真正驾驭 Postfix。
3.1 配置文件概览
3.1.1 Postfix 配置文件体系
Postfix 有多个配置文件,各有分工:
| 文件 | 路径 | 作用 |
|---|---|---|
main.cf | /etc/postfix/main.cf | 主配置文件(本章重点) |
master.cf | /etc/postfix/master.cf | 服务进程配置 |
aliases | /etc/aliases | 系统别名 |
access | /etc/postfix/access | 访问控制 |
transport | /etc/postfix/transport | 邮件路由 |
virtual | /etc/postfix/virtual | 虚拟用户映射 |
sasl_passwd | /etc/postfix/sasl_passwd | 中继认证凭据 |
header_checks | /etc/postfix/header_checks | 邮件头过滤 |
3.1.2 配置语法
# main.cf 语法规则:
# 1. 每行一个参数,格式:参数名 = 值
# 2. # 开头为注释
# 3. 空行被忽略
# 4. 值可引用其他参数($参数名)
# 5. 多值用逗号或空格分隔
# 6. 续行使用缩进或行尾 \
# 示例:
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain # 引用其他参数
3.1.3 配置管理命令
# 查看当前生效的配置(去除注释和默认值)
postconf -n
# 查看所有配置及默认值
postconf
# 查看单个参数
postconf myhostname
# 设置参数(写入 main.cf)
sudo postconf -e "myhostname = mail.example.com"
# 查看默认值
postconf -d myhostname
# 检查配置语法
sudo postfix check
# 重新加载配置
sudo systemctl reload postfix
3.2 网络与监听配置
3.2.1 inet_interfaces — 监听地址
# 监听所有网络接口(推荐生产环境使用)
inet_interfaces = all
# 仅监听本地回环
inet_interfaces = loopback-only
# 监听特定地址
inet_interfaces = 127.0.0.1, 203.0.113.10
# 使用主机名
inet_interfaces = mail.example.com
选择建议:
| 场景 | 推荐值 | 说明 |
|---|---|---|
| 单机服务器 | all | 监听所有接口 |
| 仅本地收发 | loopback-only | 不对外暴露 |
| 多网卡服务器 | 指定 IP | 精确控制 |
3.2.2 inet_protocols — 协议版本
# 仅 IPv4
inet_protocols = ipv4
# 仅 IPv6
inet_protocols = ipv6
# IPv4 和 IPv6(默认)
inet_protocols = all
3.2.3 master.cf 中的端口配置
# /etc/postfix/master.cf — 端口相关配置
# SMTP 端口 25(服务器间传输)
smtp inet n - y - - smtpd
# 提交端口 587(客户端提交)
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
# SMTPS 端口 465(隐式 TLS)
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_reject_unlisted_recipient=no
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
3.3 域名与身份配置
3.3.1 核心域名参数
# 服务器主机名(FQDN)
myhostname = mail.example.com
# 域名
mydomain = example.com
# 发件域名(默认追加到没有 @domain 的发件地址)
myorigin = $mydomain
# 本服务器负责投递的域名
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost
3.3.2 mydestination 详解
mydestination 决定了哪些域名的邮件会被投递到本地邮箱:
# 接收发往这些域名的邮件并投递到本地
mydestination = $myhostname, $mydomain, localhost.$mydomain, localhost
# 如果要为多个域名提供服务
mydestination = $myhostname, example.com, mail.example.com, \
example.org, localhost.$mydomain, localhost
注意:mydestination 中的域名和虚拟域名(virtual domains)不能重叠。
3.3.3 发件地址伪装
# 将本地用户名伪装为完整域名地址
# 效果:本地用户 user 发出的邮件,发件地址显示为 [email protected]
myorigin = $mydomain
# 使用主机名作为发件域名
myorigin = $myhostname
3.4 中继控制(Relay Control)
3.4.1 什么是中继
中继(Relay)是指邮件服务器接收来自外部客户端的邮件,
然后转发到另一个域名的邮件服务器。
合法中继:用户通过认证后发送邮件到外部
开放中继(Open Relay):任何人都可以利用服务器发送邮件 ← 危险!
3.4.2 mynetworks — 可信网络
# 定义可信网络(这些来源的邮件允许中继)
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
# 添加内部网络
mynetworks = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
# 添加特定 IP
mynetworks = 127.0.0.0/8 203.0.113.50/32
# 使用 CIDR 格式
mynetworks = 127.0.0.0/8, 10.0.0.0/24, 192.168.1.0/24
⚠️ 安全警告:
mynetworks必须精确配置,范围过大会导致服务器成为开放中继。
3.4.3 relay_domains — 允许中继的目标域名
# 允许为这些域名中继邮件
relay_domains = example.org, example.net
# 使用 hash 表文件
relay_domains = hash:/etc/postfix/relay_domains
# 禁止所有中继(仅本地投递)
relay_domains =
3.4.4 smtpd_relay_restrictions — 中继限制
# 端口 25 的中继限制(默认配置)
smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination
# 端口 587 的中继限制(提交端口,更严格)
# 在 master.cf 中设置
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
限制规则详解:
| 规则 | 作用 |
|---|---|
permit_mynetworks | 允许可信网络 |
permit_sasl_authenticated | 允许已认证用户 |
reject_unauth_destination | 拒绝未授权的目标域名 |
reject_unknown_sender_domain | 拒绝未知发件域名 |
reject_unknown_reverse_client | 拒绝无 PTR 记录的客户端 |
reject_rhsbl_reverse_client | 拒绝 PTR 在黑名单中的客户端 |
3.5 发件人与收件人限制
3.5.1 连接限制
# 每个客户端最大并发连接数
smtpd_client_connection_count_limit = 50
# 同一客户端的连接速率(次/秒)
smtpd_client_connection_rate_limit = 100
# 每个会话的最大错误次数
smtpd_soft_error_limit = 5
smtpd_hard_error_limit = 10
3.5.2 发件人限制
# 每个会话最大收件人数
smtpd_recipient_limit = 1000
# 每封邮件最大大小(字节)
message_size_limit = 10485760 # 10MB
# 邮箱最大大小(字节)
mailbox_size_limit = 5368709120 # 5GB
# 每个会话最大命令数
smtpd_error_sleep_time = 5s
3.5.3 速率限制配置
# 使用 anvil 进行速率限制
# 每个客户端每分钟最大连接数
smtpd_client_message_rate_limit = 100
# 邮件发送速率(使用 postfwd)
# 安装 postfwd
sudo apt install postfwd
# 在 main.cf 中配置
smtpd_recipient_restrictions =
check_policy_service inet:127.0.0.1:10040,
...
3.6 邮件路由与传输
3.6.1 transport_maps — 传输映射
# transport 文件格式:域名 transport:nexthop
# /etc/postfix/transport
# 将 example.org 的邮件通过特定服务器中继
example.org smtp:[mail.example.org]:25
# 将所有其他邮件通过默认路由发送
* :
# 在 main.cf 中引用
transport_maps = hash:/etc/postfix/transport
# 生成数据库
sudo postmap /etc/postfix/transport
3.6.2 sender_dependent_relayhost — 基于发件人中继
# 不同发件人使用不同的中继服务器
# /etc/postfix/sender_relay
[email protected] [smtp.provider1.com]:587
[email protected] [smtp.provider2.com]:587
@example.com [smtp.default.com]:587
# 在 main.cf 中配置
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
3.6.3 relayhost — 统一中继
# 所有外发邮件通过特定服务器中继
relayhost = [smtp.example.com]:587
# 使用方括号避免 MX 查询
# [smtp.example.com] 表示直接连接到 smtp.example.com 的 A 记录
# 不会查询 smtp.example.com 的 MX 记录
3.7 别名与虚拟域
3.7.1 系统别名(aliases)
# /etc/aliases
# 基础别名
postmaster: root
abuse: root
root: [email protected]
# 邮件列表(一个地址转发给多人)
team: [email protected], [email protected], [email protected]
# 包含文件
dev-team: :include:/etc/postfix/lists/dev-team.txt
# 管道到程序
bug-reports: "|/usr/local/bin/bug-handler"
# 丢弃邮件
spam-trap: /dev/null
# 修改别名后必须更新数据库
sudo newaliases
# 或者
sudo postalias /etc/aliases
3.7.2 虚拟别名(virtual alias)
# /etc/postfix/virtual
# 虚拟域名别名
[email protected] [email protected]
[email protected] [email protected]
@example.com [email protected]
# 跨域名转发
[email protected] [email protected]
# 在 main.cf 中配置
virtual_alias_maps = hash:/etc/postfix/virtual
# 生成数据库
sudo postmap /etc/postfix/virtual
3.7.3 虚拟域名托管
# 为多个域名提供邮件服务
# /etc/postfix/virtual_domains
example.com
example.org
example.net
# /etc/postfix/virtual
# example.com
[email protected] user1
[email protected] user2
# example.org
[email protected] user3
# 在 main.cf 中配置
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual
virtual_mailbox_base = /var/mail/vhosts
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
3.8 邮件大小与队列配置
3.8.1 邮件大小限制
# 单封邮件最大大小(字节)
message_size_limit = 10485760 # 10MB
# 邮箱总大小限制(0 = 不限制)
mailbox_size_limit = 0
# 队列文件大小限制
virtual_mailbox_limit = 0
3.8.2 队列管理配置
# 队列扫描间隔(秒)
queue_run_delay = 300
# 最小退信间隔(秒)
minimal_backoff_time = 300
# 最大退信间隔(秒)
maximal_backoff_time = 4000
# 队列生命周期(天)
maximal_queue_lifetime = 5
# 退信生命周期(天)
bounce_queue_lifetime = 5
# 队列目录
queue_directory = /var/spool/postfix
3.9 日志配置
# 日志文件路径(Debian/Ubuntu)
maillog_file = /var/log/mail.log
# RHEL/CentOS 使用 syslog
# 在 /etc/rsyslog.d/postfix.conf 中配置
# mail.* /var/log/maillog
# 日志级别(0-5)
# 0: 仅错误和警告
# 1: 加上连接和协议信息
# 2: 加上排队信息
# 3: 加上延迟和转发信息
# 4: 加上详细调试
# 5: 极其详细(仅调试用)
3.10 业务场景:多域名邮件托管
场景描述
一家小型 ISP 需要为三个域名提供邮件托管服务:
company-a.comcompany-b.comcompany-c.com
完整配置
# /etc/postfix/main.cf — 多域名托管配置
# ==================== 基础设置 ====================
myhostname = mail.hosting-isp.com
mydomain = hosting-isp.com
myorigin = $mydomain
mydestination = localhost.$mydomain, localhost
# ==================== 虚拟域名 ====================
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual_mailbox
virtual_alias_maps = hash:/etc/postfix/virtual_alias
virtual_mailbox_base = /var/mail/vhosts
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_minimum_uid = 5000
# ==================== 安全限制 ====================
smtpd_relay_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination
message_size_limit = 20971520
mailbox_size_limit = 0
# ==================== TLS ====================
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.hosting-isp.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.hosting-isp.com/privkey.pem
smtpd_tls_security_level = may
# /etc/postfix/virtual_domains
company-a.com
company-b.com
company-c.com
# /etc/postfix/virtual_mailbox
[email protected] company-a.com/admin/
[email protected] company-a.com/user1/
[email protected] company-b.com/admin/
[email protected] company-c.com/admin/
# /etc/postfix/virtual_alias
# 别名映射
[email protected] [email protected]
[email protected] [email protected]
# 生成数据库
sudo postmap /etc/postfix/virtual_domains
sudo postmap /etc/postfix/virtual_mailbox
sudo postmap /etc/postfix/virtual_alias
# 创建目录
sudo mkdir -p /var/mail/vhosts/{company-a.com,company-b.com,company-c.com}
sudo useradd -r -u 5000 -d /var/mail vmail
sudo chown -R vmail:vmail /var/mail/vhosts
# 重新加载
sudo systemctl reload postfix
3.11 注意事项
⚠️ mydestination 与 virtual_mailbox_domains 不能重叠,否则会导致投递冲突。
mydestination中的域名:邮件投递到系统用户邮箱virtual_mailbox_domains中的域名:邮件投递到虚拟用户邮箱
⚠️ 修改 main.cf 后必须重新加载:
sudo systemctl reload postfix # 或 sudo postfix reload
💡 使用 postconf 而非手动编辑:
# 推荐方式(自动写入 main.cf) sudo postconf -e "myhostname = mail.example.com" # 不推荐方式(容易出错) sudo vi /etc/postfix/main.cf