详解电子邮件系统系列之三:postfix及dovecot安装

有了前两章的概念基础,这章终于步入正题,开始搭建自有的电子邮件系统。系统搭建需要用到两个开源软件:postfix和dovecot。其中postfix 主要实现smtp收件服务器和smtp发件服务器的功能,dovecot主要实现pop3/imap收件的功能。

postfix 安装配置

postfix 是Wietse Venema在IBM的 GPL 协议之下开发的一款 MTA 软件。postfix是Wietse Venema想要为使用最广泛的 sendmail 提供替代品的一个尝试。在 postfix 之前,sendmail 是广泛用于使用的用于邮件传输的 MTA 软件。Postfix试图更快、更容易管理、更安全,同时还与sendmail保持足够的兼容性。

postfix整体架构

postfix现在是预置在各大主流linux发行版中,且默认服务状态是开启的(所以你的服务器25端口默认是开启的,呵呵)。互联网的设计者当初是想把每一台主机都当成 open relay 来看待,当然互联网发展到现在和他们当初设想的已经大相径庭。如果系统里面没有postfix,可以通过下面的命令进行安装:
centos/redhat:

yum install postfix

debian/ubuntu

apt install postfix

可以通过以下命令查看系统中当前默认的MTA:

[root]# alternatives --display mta
mta - status is manual.
 link currently points to /usr/sbin/sendmail.postfix
/usr/sbin/sendmail.postfix - priority 30
 slave mta-pam: /etc/pam.d/smtp.postfix
 slave mta-mailq: /usr/bin/mailq.postfix
 slave mta-newaliases: /usr/bin/newaliases.postfix
 slave mta-rmail: /usr/bin/rmail.postfix
 slave mta-sendmail: /usr/lib/sendmail.postfix
 slave mta-mailqman: /usr/share/man/man1/mailq.postfix.1.gz
 slave mta-newaliasesman: /usr/share/man/man1/newaliases.postfix.1.gz
 slave mta-aliasesman: /usr/share/man/man5/aliases.postfix.5.gz
 slave mta-sendmailman: /usr/share/man/man1/sendmail.postfix.1.gz
Current `best' version is /usr/sbin/sendmail.postfix.

postfix的配置非常复杂,默认的配置文件就有600多行(这还不是全部的配置,很多配置只列在了官方文档中,没写在配置文件里),学习曲线很陡峭,本系列文章仅对于主要配置进行一下说明,其余的配置使用方法可参考官方文档:https://www.postfix.org/postconf.5.html

基础配置

主要是一些邮件服务器的域名、后缀等等一些的配置:

myhostname = mail.abc.mail //邮件服务器主机名,一般为smtp.domain或者mail.domain这样的形式
mydomain = abc.mail //域名,也需要设置
myorigin = $mydomain //设置本地邮件的接收规则,即定义哪些属于本地邮件,一般和mydomain一致

传输安全配置

从之前的系列文章中我们可以了解到,安全性可以主要分为传输安全和身份认证安全。根据电子邮件系统架构图,邮件在传输过程中,跨可信网络区域的传输主要有发送用户MUA-->发送方MTA、发送方MTA-->接收方MTA、接收用户MUA-->接收方MTA这几个环节,其余的MTA至MDA,或者MRA至mailbox等等,一般我们认为都在邮件服务商内部网络区域,安全传输的需求不突出。那么要解决上述的几个may环节的传输安全,技术上来说就是通过SSL/TLS、STARTTLS等方式来解决。传输加密非常重要,否则你的邮件在互联网上就相当于裸奔,任何传输中间环节的网络设备、服务器节点都可以轻易获取你的发送内容。根据谷歌的统计数据,目前gmail上面超过90%的进出站邮件都是通过TLS加密传输的。

那么回到具体的软件,发送用户MUA-->发送方MTA、发送方MTA-->接收方MTA这两个环节是由postfix来解决的,接收用户MUA-->接收方MTA是由dovecot来解决的。postfix 的核心配置是 /etc/postfix/main.cf/etc/postfix/master.cf 这两个文件。注意postfix有smtp和smtpd两个模块,其中smtpd是服务端模块,用于接收客户端或其他MTA发送过来的请求,smtp是客户端模块,用于向其他MTA发送请求,许多配置的前缀也是基于上述描述,要注意区分。

客户端tls安全传输配置:

# stmp config here(smtp client)
# Mandatory (high-grade) TLS encryption.
smtp_tls_security_level = encrypt //与其他smtp服务器建立连接使用encrypt强制加密方式,其他可选项还有none、may等
smtp_tls_mandatory_ciphers = high //要求对方开启高级别的加密传输等级

这样设置只要对方smtp服务器支持tls加密传输,那么postfix在传输邮件时就会开启tls加密会话。
未启用传输加密,以gmail为例,会在收件人下方显示一个红色小锁的图标,提示这封邮件未通过加密传输:


非加密传输

而如果发送方启用了加密传输,则邮件信息中会显示已加密:


加密传输

服务端安全传输配置:

# stmpd config here(smtp server)
smtpd_tls_security_level = may //安全级别,may意思是如果客户端支持tls则使用加密传输,但不强制
smtpd_tls_received_header = yes //把tls认证相关信息加入 Received 标头中
smtpd_tls_cert_file=/etc/ssl/myfullchain.pem //服务端tls证书
smtpd_tls_key_file=/etc/ssl/mykey.pem //服务端tls私钥

这段配置,会使用配置里面的ssl证书,建立tls的安全传输通道。注意这里服务端的参数要选择may,不能开启encrypt进行强制加密,依据是rfc 2487规范,不设置为may可能会导致某些不支持加密的邮件服务商发过来的邮件被拒收。具体可查看官方文档:https://www.postfix.org/postconf.5.html#smtpd_tls_security_level

这里碰到个问题,smtpd_tls_security_level 设置为may后,理论上发送方的MTA如果支持tls,应该就会通过starttls 开启加密传输通道,但是实测国内的邮箱服务商如163、189等都还是使用明文传输(qq邮箱是加密的),而gmail、outlook等国际邮件服务商都使用了tls加密,不知道是国内的支持有问题还是配置问题,但163直接发gmail又是加密的,只能说国内邮箱尽量少用吧。

这时候还需要配置 master.cf 这个配置文件,打开465和587监听端口,以允许邮件客户端建立加密连接通道。

smtps     inet  n       -       n       -       -       smtpd
submission inet n       -       n       -       -       smtpd

把上述配置前面的#去除即可。

邮件转发配置

为了防止我们搭建的邮件服务器成为 open relay 被人利用滥发垃圾邮件,邮件转发的配置非常重要。它定义了postfix的smtpd模块对于哪些邮件发送请求是可以处理的,哪些邮件请求是需要拒绝的。核心配置参数为smtpd_relay_restrictions,它的默认值为permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination,下面分别介绍一下:

  • permit_mynetworks:允许从本地网络发起的请求,一般需要和邮件服务器在一个子网下,也可以设置特定的ip规则(cidr格式)
  • permit_sasl_authenticated:允许通过sasl 用户身份认证的请求
  • defer_unauth_destination:拒绝未认证的收件地址

这是一个邮件转发的最佳实践,正常情况下已经足够我们使用。第一个同一子网比较好理解,第二个配置,要求postfix配置一个sasl认证。关于sasl认证,这里不展开讲,否则又是一大篇。这里我们只要知道,postfix默认配置的sasl认证是 cyrus,为了要完成认证,还需要安装 saslauthd 工具,而 cyrus 本身又是一个门面,需要借助其他的工具 pam、/etc/shadow等完成认证,而pam也不做实际的认证,只做集成,还需要配合实际的认证方式。。。总之,为了方便,我们这里不使用默认的cyrus,而使用 dovecot 作为认证方式(postfix只支持这两种方式),可使用 postconf -a命令查看支持的认证方式。相关配置如下:

smtpd_sasl_auth_enable = yes //开启认证,默认是no,不开启的话 smtpd 将拒绝所有目标地址非本地的发送请求
smtpd_sasl_type = dovecot //sasl的认证方式设置为 dovecot
smtpd_sasl_path = private/auth //认证接口路径,需要和dovecot中的保持一致
smtpd_sasl_authenticated_header = yes //配置完后,postfix 将在日志中记录认证信息

光通过sasl认证身份还不够,我们还必须要保证发件人邮箱和通过认证的用户相匹配,这里需要启用reject_sender_login_mismatch 这个参数(其实就是reject_authenticated_sender_login_mismatch, reject_unauthenticated_sender_login_mismatch 这两个参数的别名),要实现这两个参数,必须要配置smtpd_sender_login_maps,定义认证用户名与发件人邮箱的对应关系。注意,这里使用到了db,也就是需要把配置转换成db文件,postfix才能识别出来。我一开始就是卡在这里,以为做好maps的配置文件就可以,实际是需要转换一下,postfix才能识别的。关于postfix支持的db格式,可以参考这里:https://www.postfix.org/DATABASE_README.html。smtpd_sender_login_maps默认使用的是 Berkeley DB(也支持mysql、Postgres等其他数据库),转换使用的工具为:postmap,具体用法参考:https://www.postfix.org/postmap.1.html
这里我们先准备一个文本文件 sender_login_maps:

bob@abc.mail   bob
postmaster@abc.mail  bob

上面的配置,给bob这个用户绑定了两个邮箱,分别是bob@abc.mail 和postmaster@abc.mail,bob用户可以分别以这两个发件人身份往外发件。我们使用postmap把这个配置文件转换成 db 文件:

[root@ethical-ponies-1 ~]# postmap sender_login_maps //将文本文件转换成berleley db
[root@ethical-ponies-1 ~]# postmap -q bob@abc.mail sender_login_maps //根据key查询db文件
bob

把我们做好的db文件进行配置,就可以正常进行发件人校验了:

smtpd_sender_restrictions = reject_sender_login_mismatch
smtpd_sender_login_maps = hash:/etc/postfix/sender_login_maps

到这里我们postfix的基本配置就都完成了,可以看出来这并不是一个开箱即用的配置,还是稍许有点复杂,通过上述配置的postfix的转发规则概括为:

  • 发件人为本地邮箱,收件人为非本地邮箱:会进行sasl用户认证及发件人匹配认证,通过后才会转发邮件,相当于smtp服务器的角色
  • 发件人为非本地邮箱,收件人为本地邮箱:这类情况相当于mx服务器的角色,会强制要求对方通过tls方式传输邮件,邮件会投递到本机的mailbox中
  • 发件人为非本地邮箱,收件人为非本地邮箱:这类其实就是 open relay 了,全部拒绝

基本满足一个邮箱的安全配置,当然为了防止垃圾邮件滥发,一般还需要做spf、dkim、dmarc、rDNS等认证,这个放到后面再讲。

dovecot安装配置

dovecot 是一个实现了 pop3/imap协议的开源软件,通过读取主机的mailbox来将邮件传输到客户端。


dovecot

dovecot 在系统中没有自带,需要自己安装:
centos/redhat:

yum install dovecot

debian/ubuntu

apt install dovecot

如果你准备使用roundcube这样的webmail,那么dovecot也可以不安装,仅在使用邮件客户端的时候需要安装 dovecot

安全传输设置

dovecot默认启用了tls安全传输,需要进行证书配置
/etc/dovecot/conf.d/10-ssl.conf:

# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# dropping root privileges, so keep the key file unreadable by anyone but
# root. Included doc/mkcert.sh can be used to easily generate self-signed
# certificate, just make sure to update the domains in dovecot-openssl.cnf
ssl_cert = </etc/ssl/myfullchain.pem
ssl_key = </etc/ssl/mykey.pem

身份认证配置

/etc/dovecot/conf.d/10-auth.conf:

# Username formatting before it's looked up from databases. You can use
# the standard variables here, eg. %Lu would lowercase the username, %n would
# drop away the domain if it was given, or "%n-AT-%d" would change the '@' into
# "-AT-". This translation is done after auth_username_translation changes.
auth_username_format = %n

dovocot默认使用pam进行用户认证,正常dovecot认证只能输入用户名,这个配置可以让用户名加上@后面的域名,也可以通过认证,dovecot会忽略@后面的内容,只看前面的用户名(很多邮箱客户端会默认加上@后面的部分作为用户名)

postfix 认证对接

/etc/dovecot/conf.d/10-master.conf:

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  #
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  #
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions)

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
  }

}

配置认证监听的unix套接字地址为/var/spool/postfix/private/auth ,注意这里要和postfix中配置的要一致,这样postfix就可以把sasl认证请求转发给dovecot处理。这样配置的好处是两边的认证方式是一样的,不会出现smtp认证和imap认证不一致的情况。

日志配置

/etc/dovecot/conf.d/10-logging.conf:

# Log file to use for error messages. "syslog" logs to syslog,
# /dev/stderr logs to stderr.
log_path = /var/log/dovecot

防火墙配置

为了有效进行访问安全控制,需要开启防火墙,并打开特定端口,这里以centos自带的firewalld举例,其他防火墙也差不多:
firewalld的命令行工具为firewall-cmd,它有一个zone的概念,通过不同的zone可以配置不同的访问控制规则。我们通过 --add service命令添加相关的服务端口:

[root@ethical-ponies-1 ~]# firewall-cmd --get-zones
block dmz drop external home internal public trusted work
[root@ethical-ponies-1 ~]# firewall-cmd --get-active-zones
dmz
  sources: 
public
  interfaces: eth0 eth1
[root@ethical-ponies-1 ~]# firewall-cmd --get-default-zone
public
[root@ethical-ponies-1 ~]# firewall-cmd --add-service=imaps smtp smtp-submission smtps --permanent
success
[root@ethical-ponies-1 ~]# firewall-cmd --reload
success
[root@ethical-ponies-1 ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources: 
  services: dhcpv6-client imaps smtp smtp-submission smtps ssh
  ports: 28068/tcp
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

上面的命令添加了邮箱相关的服务端口,--permanent 参数告诉防火墙是永久生效的,reload之后参数生效。

这里需要注意的是,对于默认的zone,interfacessources这两个参数是不生效的,也就是不匹配其他zone的interfaces和sources规则的流量,都会进默认的zone,里面配置的访问控制规则都会生效。而如果其他zone里面配置了interfaces和sources这两个参数,符合匹配规则的流量会优先进入其他zone,流量适用该zone的访问控制规则。

域名配置

以上各类配置工作就差不多了,要能够正常收邮件,我们还需要进行域名配置。我们需要设置一条mx记录和一条a记录(mx记录可以告诉客户端@abc.mail这个邮箱后缀所指向的mx服务器地址,它只能设置为域名,所以要设置两条,以下为示例,非真实dns服务商):

HOSTNAME TYPE ADDRESS / VALUE TTL
MX mail.abc.mail 3600
mail A 123.123.123.123 3600

调试服务

现在我们的基础搭建工作就完成了,我们可以使用telnet/openssl工具进行smtp/imap服务的调试,调试方式已经在系列二的文章中详细的介绍过了,大家使用命令行方式可以方便的进行发送邮件、收取邮件的调试。注意要善于查看应用日志来解决问题,postfix的日志位置在/var/log/maillog,dovecot日志位置在/var/log/dovecot

参考资料

1、Debian 8 Server搭建Postfix+Dovecot邮件服务器
https://www.linuxdashen.com/debian-8-server%E6%90%AD%E5%BB%BApostfixdovecot%E9%82%AE%E4%BB%B6%E6%9C%8D%E5%8A%A1%E5%99%A8
2、在 CentOS 7 上搭建属于自己的 “完美” 邮件系统
https://zhuanlan.zhihu.com/p/28816035
3、安装和配置 Postfix
https://chloerei.com/2015/04/22/install-and-configure-postfix/
4、The Postfix Mail Server
https://paulgorman.org/technical/postfix.txt.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容