之前一直用博客,然鹅现在用RSS的伙伴越来越少了,公众号这种主动推送机制对读者和作者都很好用,所以欢迎大家关注我的微信公众号:IT漫步。主要分享自己折腾的各类技术和一些观点。扫码关注:
暑假的时候见识了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发行版基本都带。但是配置麻烦。
- postfix:Wietse 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。那么我们需要
- 设置rDNS,将1.1.1.2映射到mail1.wangchenyu.net.cn。DNS是域名->IP的解析。rDNS即IP->域名的解析。有了这个rDNS记录,收到邮件的服务器就能确认mail1.wangchenyu.net.cn可以被用在1.1.1.2这个IP上。一般在主机商后台可以添加rdns记录,找不到的话提交一个工单即可。
- 设置best.pm和best.nl的MX记录,记录名为@,值为mail1.wangchenyu.net.cn,优先级为10。MX记录用于别人向best.pm这个域发送邮件时查找收信服务器。不设置的话无法收到别人发的邮件,并且自己发出的邮件的“可信度”也会大大降低。优先级
- 设置DKIM签名。DKIM先由发件服务器生成,之后每封邮件都会带上这个签名。接着,还要在best.pm和best.nl上各添加一条TXT记录,记录名和值在发件服务器生成DKIM时都会提供。收到邮件后会对比邮件中的DKIM签名和DNS中的TXT记录是否一致。
- 设置SPF记录。这个记录规定了可以用这个域发邮件的主机。在best.pm和best.nl上各添加一条TXT记录,记录名为
@
,值为v=spf1 mx ~all
即可允许所有IP使用此域。 - 设置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
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!
Comments | 19 条评论
怎么我搭建了邮件服务器接收邮件正常(ssl方式),发送邮件25端口发送邮件提示发送成功,但是对方就是收不到,但也不是到对方的垃圾箱中,换了不同邮箱帐号还是一样,我使用ssl 587端口发送直接报无法连接。请问你知道这是什么情况吗?
@音符
要是你也是用docker搭建的话,docker logs mail这样看一下dovecot日志,看看有没有发出去。
至于端口无法连接,检查一下建立容器的时候绑定587端口了不?无法连接是报什么错误?证书有问题还是什么?
你好,docker-compose.yml 这个文件放在那个目录下啊。还是在任意目录都可以,只要执行到时候指定文件路径比如,docker-compose ./docker-compose.yml up -d mail
@coompoy
已经搞定了,谢谢
@coompoy
没记错的话,如果执行的是
docker-compose up -d
会在当前目录寻找docker-compose.yml
如果手动指定配置文件的话,那就无所谓 放在哪里/文件名是什么 啦
搞定了就好~
@cheney
你这个域名是不是被墙了,还是你腾讯云这个香港ip被墙了,现在要翻墙才能访问哈哈😄
@coompoy
Orz 不是被墙啦,是备案期间不想被谷歌惩罚,就屏蔽了所有国内ip不解析😏
至于为啥又备案了呢,为了“覆盖”历史记录:)
非常抱歉打扰你,需要自己搭建邮件服务器,没有配置反向解析,配置了域名–>IP的记录,其他的都是按照你的文章里写的步骤操作的,最后用outlook连接,总是连不上,我用其他的邮件发送了邮件,通过docker logs mail,是能看到成功收到邮件了,好纠结,希望你能帮我分析下问题
@xiaoxiao
如果docker logs mail能看见的话,说明dovecot收到收件了,也就说明收信端口25正常打开。客户端能不能连上的话,可以看看
1. docker容器是否把端口993成功映射到了主机
– 执行docker port mail查看
2. 主机是否有防火墙未开放993
– 确认容器映射正确的话,在主机上执行telnet 127.0.0.1 993能否连通
– 上面能连通的话,在本地执行telnet your.mail.server 993能否连通
3. 收信软件的协议是否选择正确
– 上面都能连通的话,检查outlook客户端配置的是不是imap协议
谢谢,已经可以正常收发邮件了
@xiaoxiao
好极啦 🙂
为什么我按着博主的步骤做最后还是发不了邮件?更不用说收邮件了。。。
有谁可以帮助下我?qq或微信: 2 8 9 9 3 1 6 5 0
@KennyZhang
看上面的评论哦,按照这个流程检查一下:
如果docker logs mail能看见的话,说明dovecot收到收件了,也就说明收信端口25正常打开。客户端能不能连上的话,可以看看
1. docker容器是否把端口993成功映射到了主机
– 执行docker port mail查看
2. 主机是否有防火墙未开放993
– 确认容器映射正确的话,在主机上执行telnet 127.0.0.1 993能否连通
– 上面能连通的话,在本地执行telnet your.mail.server 993能否连通
3. 收信软件的协议是否选择正确
– 上面都能连通的话,检查outlook客户端配置的是不是imap协议
该评论为私密评论
@始皇哥
1. 搭建邮件服务器最好要一个域名,MX记录是必须填写域名的。不过,你可以在freenom.com免费申请一个.tk/.cf/.ga/.ml的域名。
2. DNS、MX这些都是最基础的东西啦,如果你想自建邮件服务器,最好先把他们搞明白,这些概念并不难理解。
如果你实在无法理解,推荐你使用商用的邮件服务如mailgun、sendgrid。
如果不在乎邮箱的后缀,直接使用QQ邮箱、163邮箱等带的SMTP功能来发送邮件也行。
你好!获取证书失败,请问是什么原因。
相关流程:
1.使用命令“ sudo yum install -y certbotBash”,安装certbot工具已经成功。
2。使用电脑PING命令可以拼通”xxx.xxx.top”。
3。但是使用命令“ certbot certonly –standalone -d mail1.wangchenyu.net.cn”,申请证书失败。
以下是报错内容(邮箱 地址做了 隐藏):
—————————————————————————————————————–
Please see the logfiles in /var/log/letsencrypt for more details.
[root@localhost ~]# certbot certonly –standalone -d xxx.xxx.top
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for xxx.xxx.top
Waiting for verification…
Cleaning up challenges
Failed authorization procedure. icemail.fictime.top (http-01): urn:ietf:params:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://xxx.xxx.top/.well-known/acme-challenge/i2TR9ASXtANyiJgtFotOyYmiEoJiAjaVB3bU1iyeCIw: Timeout during connect (likely firewall problem)
IMPORTANT NOTES:
– The following errors were reported by the server:
Domain: xxx.xxx.top
Type: connection
Detail: Fetching
http://xxx.xxx.top/.well-known/acme-challenge/i2TR9ASXtANyiJgtFotOyYmiEoJiAjaVB3bU1iyeCIw:
Timeout during connect (likely firewall problem)
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address. Additionally, please check that
your computer has a publicly routable IP address and that no
firewalls are preventing the server from communicating with the
client. If you’re using the webroot plugin, you should also ver
—————————————————————————————————————–
使用的命令是这个“ certbot certonly –standalone -d xxx.xxx.top”,申请证书失败。
@leron_lee
看起来错误信息是超时
1. 试试看自己手动访问xxx.xxx.top/.well-known可否访问?
2. 自己在.well-known目录下建个文件,然后访问xxx.xxx.top/.well-known/文件名 能否访问?
如果自己访问是正常的,而letsencrypt的验证服务器无法访问,可以试试用acme.sh脚本,用dns的方式申请证书,见这里:https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E
该评论为私密评论