美文网首页
详解电子邮件系统系列之三:postfix及dovecot安装

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

作者: 暴走的初号机 | 来源:发表于2023-04-15 14:27 被阅读0次

    有了前两章的概念基础,这章终于步入正题,开始搭建自有的电子邮件系统。系统搭建需要用到两个开源软件: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

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/qlmaddtx.html