暑假的时候见识了Vestacp,用它可以方便快捷的搭建一个邮局。但是邮局经常崩,常收不到邮件。寒假了就折腾了一下Docker。

PS(2017.2.13更新):将近一个月了,期间收了已经有上百封邮件。我用uptime robot检测的还没有一例宕机事故,监控页面在这里。docker容器的稳定性是有目共睹的。

一、基础知识

1.常见邮局端口&&协议:

发邮件的协议有SMTP,收邮件的协议有POP3和IMAP。

  • SMTP:明文使用25端口。加密后使用25/587/465端口。
  • IMAP:明文使用143端口。加密后使用143/993端口。
  • POP3:明文使用110端口。加密后使用110/995端口。

2.常见邮局软件和安全软件:

  • sendmail:用于发邮件。资格最老的邮局,所有Linux发行版基本都带。但是配置麻烦。
  • postfixWietse Venema觉得sendmail配置太麻烦了,就开发了一个“简化配置版sendmail”,即postfix。支持smtp协议。
  • dovecot:用于收邮件,支持imap/pop3。
  • spamassasin:垃圾邮件过滤器。可以自订规则。
  • clamav:邮件杀毒工具。
  • opendkim:生成dkim签名。有什么用?详见下面的“反垃圾邮件技术”。
  • fail2ban:防止别人暴力破解用户名密码的工具。

3.反垃圾邮件技术:

假设我要在1.1.1.2这台机器上配置best.pm、best.nl这两个域名用于发邮件。1.1.1.2的主机名是mail1.wangchenyu.net.cn。那么我们需要

  1. 设置rDNS,将1.1.1.2映射到mail1.wangchenyu.net.cn。DNS是域名->IP的解析。rDNS即IP->域名的解析。有了这个rDNS记录,收到邮件的服务器就能确认mail1.wangchenyu.net.cn可以被用在1.1.1.2这个IP上。一般在主机商后台可以添加rdns记录,找不到的话提交一个工单即可。
  2. 设置best.pm和best.nl的MX记录,记录名为@,值为mail1.wangchenyu.net.cn,优先级为10。MX记录用于别人向best.pm这个域发送邮件时查找收信服务器。不设置的话无法收到别人发的邮件,并且自己发出的邮件的“可信度”也会大大降低。优先级
  3. 设置DKIM签名。DKIM先由发件服务器生成,之后每封邮件都会带上这个签名。接着,还要在best.pm和best.nl上各添加一条TXT记录,记录名和值在发件服务器生成DKIM时都会提供。收到邮件后会对比邮件中的DKIM签名和DNS中的TXT记录是否一致。
  4. 设置SPF记录这个记录规定了可以用这个域发邮件的主机。在best.pm和best.nl上各添加一条TXT记录记录名为@,值为v=spf1 mx ~all即可允许所有IP使用此域。
  5. 设置DMARC记录这个记录指出他们的地址被 SPF 和/或 DKIM/或别的方法保护。在best.pm和best.nl上各添加一条TXT记录记录名为_dmarc,值为v=DMARC1; p=none

二、操作步骤

这里我选择了一个Github上的docker-mailserver。正如介绍中所言,它的功能齐全,配置简单,并且不需要*sql数据库。部署和升级都相对简单得多。在服务器上安装docker和docker-compose。

1.参照着上面给的说明,首先拉取镜像:

docker pull tvial/docker-mailserver:latest

2.创建docker-compose.yml

内容参考docker-compose.yml.dist,我略做改动如下,注意hostnamedomainname,他俩最终要能拼成主机名:
version: '2'

services:
 mail:
 image: tvial/docker-mailserver:2.1
 hostname: mail1
 domainname: wangchenyu.net.cn
 container_name: mail
 ports:
 - "25:25"
 - "143:143"
 - "587:587"
 - "993:993"
 volumes:
 - /home/mail:/var/mail
 - /home/mail-state:/var/mail-state
 - /root/config/:/tmp/docker-mailserver/
 - /etc/letsencrypt:/etc/letsencrypt
 environment:
 - ENABLE_SPAMASSASSIN=0
 - ENABLE_CLAMAV=0
 - ENABLE_FAIL2BAN=1
 - ONE_DIR=1
 - DMS_DEBUG=0
 - SSL_TYPE=letsencrypt
 cap_add:
 - NET_ADMIN

3.添加邮件账户:

mkdir -p /root/config
touch /root/config/postfix-accounts.cf
docker run --rm \
 -e MAIL_USER=user1@best.pm \
 -e MAIL_PASS=mypassword \
 -ti tvial/docker-mailserver:latest \
 /bin/sh -c 'echo "$MAIL_USER|$(doveadm pw -s SHA512-CRYPT -u $MAIL_USER -p $MAIL_PASS)"' >> /root/config/postfix-accounts.cf

如果有多个邮箱账户,则多次执行上面的docker run语句就行。

4.创建DKIM key:

docker run --rm \
 -v "/root/config":/tmp/docker-mailserver \
 -ti tvial/docker-mailserver:latest generate-dkim-config

执行完之后查看/root/config/opendkim/keys/best.pm/mail.txt的内容就是我们要设置的dns解析。我的内容是:

cat /root/config/opendkim/keys/best.pm/mail.txt
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DPENNNNNNNNNNCBiQKBgQCy9JV3FnXjLjsRJs/N0fy1C233333IV7t3f7fWpv/lo4NsoPEtG693hTgApkhuLl9KeV233333DMTagtXN898lXenKFEIS4COi7X/RjbGuOoApg4qS23333333TfXsrjN3xVC78E9T/HrS6pJN5fX+1s+1s+1s+1s+1s+1sIDAQAB" ) ; ----- DKIM key mail for best.pm

如果是自己搭建的bind,直接把这段塞进域名的hosts文件就行。如果使用的是第三方解析,就去后台添加一条TXT记录记录名mail._domainkey记录值两段引号内的字符串拼接起来即可,如我的就是:

v=DKIM1; k=rsa;p=MIGfMA0GCSqGSIb3DPENNNNNNNNNNCBiQKBgQCy9JV3FnXjLjsRJs/N0fy1C233333IV7t3f7fWpv/lo4NsoPEtG693hTgApkhuLl9KeV233333DMTagtXN898lXenKFEIS4COi7X/RjbGuOoApg4qS23333333TfXsrjN3xVC78E9T/HrS6pJN5fX+1s+1s+1s+1s+1s+1sIDAQAB

5.申请letsencrypt证书并自动续费:

非CentOS请参考certbot.eff.org

安装certbot工具:

sudo yum install -y certbot

确保将mail1.wangchenyu.net.cn解析到了1.1.1.2,然后执行:

certbot certonly --standalone -d mail1.wangchenyu.net.cn

即可申请到mail1.wangchenyu.net.cn的证书,申请后证书就放在

/etc/letsencrypt/live/mail1.wangchenyu.net.cn

下,其中

  • fullchain.pem是机构证书+域名证书
  • chain.pem是机构证书
  • cert.pem是域名证书
  • privkey.pem是域名私钥

因为上面的docker-compose.yml中已经把/etc/letsencrypt映射到了容器中所以到这里就完成了证书的工作。

输入crontab -e打开定时任务设置面板,然后按i进入编辑模式,粘贴进这段代码即可每周一凌晨5点0分给证书续期:

0 5 * * 1 /usr/bin/certbot renew --quiet

到这里已经万事大吉了。

如何检测SSL配置是否成功?

参照https://github.com/tomav/docker-mailserver/wiki/Configure-SSL,
启动容器后运行:

docker exec mail openssl s_client -connect 0.0.0.0:587 -starttls smtp -CApath /etc/letsencrypt/

docker exec mail openssl s_client -connect 0.0.0.0:993 -starttls imap -CApath /etc/letsencrypt/

看到这个说明成功了:

Verify return code: 0 (ok)

6.启动容器:

执行下列命令即可:

docker-compose up -d mail

三、客户端配置

服务器配置好了,如何连接?

在任一个邮件客户端中这么配置:

收信:

  • 服务器地址:mail1.wangchenyu.net.cn
  • 协议:IMAP
  • 端口:993
  • 用户名:user1@best.pm
  • 密码:mypassword
  • 使用SSL:是

发信:

  • 服务器地址:mail1.wangchenyu.net.cn
  • 协议:SMTP
  • 端口:587
  • 用户名密码同上
  • 使用SSL:是

Enjoy it!