Contents
前言
闲来无事,觉得家庭数据中心怎么着也应该有个自己域名后缀的邮箱,就准备自己搭建个邮件服务器。关于软件的选择,考察了很多,先考察EwoMail,结果官方推荐centos7/8,于是就装了centos 8,然后发现在2021-12-31结束了生命周期之后,linux社区不再维护该版本,所以yum命令都没法用了,就算更改了源之后,在使用安装脚本安装的时候,又报了一堆错,生气了,直接换。
又考察了一些开源的邮件服务器软件,Postal、mailcow等,要么就是功能单一(只有出站,没有邮箱管理等),要么就是功能太全并且又太耗资源。细化下我的需求:支持webmail,支持邮件的收和发,支持docker部署,不那么耗资源。。。找了一圈,发现paste能满足我所有要求。
poste简介
poste是一款开源邮件服务软件,可以很方便的搭建:SMTP+ IMAP + POP3 + 反垃圾邮件 + 防病毒 + Web 管理 + Web 电子邮件,支持以下特性:
- SPF、DKIM、DMARC、SRS 的原生实现,带有简单的向导
- 用于检测木马、病毒、恶意软件的防病毒引擎 ( ClamAV )
- 内置垃圾邮件过滤器( RSPAMD )
- HTTPS 上的Webmail 客户端(Roundcube)
- 通过Sieve 脚本进行电子邮件重定向、自动回复和其他过滤(电子邮件所有者管理,每个操作都可以编写脚本)
- 用于限制邮箱空间或电子邮件数量的配额
- 系统管理员、域管理员、电子邮件所有者具有不同权限的Web 管理。
- 内置Microsoft 产品的自动发现功能,Thunderbird
- 帮助正确设置域和邮件服务器的诊断
- 默认情况下,所有密码都存储为加盐SHA512哈希(5000 轮)。攻击者将很难破解您的密码。
看起来很强大,关键原生支持docker部署,自家的邮件服务器就靠它来实现了。
网络环境要求
首先确认下使用paste.io搭建邮件服务器时候对网络环境的要求,先看看paste官方的说明:
这些端口在创建docker的时候会用-p参数进行映射,不过在这其中哪些端口是必须的呢?
先看看我搭建的paste邮件服务器自身的检查结果,红框是检查结果异常的:
异常原因分析:
LE(Let’s Encrypt)
这个应该是我的家庭宽带没有443端口,所以无法使用,这个影响不大,就是不能靠Let’s Encrypt自动申请和更新证书,腾讯云上每个账号有20个免费一年期证书的额度,就靠蹭了。
outbound port 25
出向25端口显示有问题,但是其实是没问题的,主要它是测试的gmail的25端口的可连接性,这有问题很正常。
inbound 80,443,4190
80,443端口,家庭宽带肯定没,有问题正常,搭建docker的时候可以改成其他端口。4190是可选项,异常也没什么影响,就不管了。
以上结果显示,我的家庭宽带在没有80,443,4190端口的情况下,是可以正常收发邮件的,所以这几个端口不是必须的。剩余的110,143,587,993,995端口,其实都是邮件客户端可以使用的各种协议(pop3,imap)以及其对应的TLS版来连接邮件服务器时候使用的,即便有些没有,也只是说邮件客户端不能直接用对应的方式来连接邮件服务器而已,但是至少可以用webmail的方式,也就是说,其实也不是必须的。
剩下还有个25端口,这个是不是必须的呢?对搭建邮件服务器而言,25端口就是必须的了,其实细化来说,SMTP的25端口分为”inbound”和”outbound”两个方向(如上图中的测试项),对于发邮件,outbound是必须的;对于收邮件,inbound是必须的。
这个要从SMTP工作的流程上开始讲了。
先看下发送端通过SMTP协议发送的邮件达到接收端的全过程:
再简化一点:
上图中可知,第一步从邮件客户端到发信服务器(Sender Mail Server)并不一定需要25端口,也可以使用其他端口(如果要用25端口,这个对于发信服务器就是inbound方向);而第二步其实只是指定了收信服务器必须使用25端口来接受信件(发信服务器给收信服务器发送请求的目标端口是25,这对发信服务器而言就是outbound方向),而对发信服务器发送请求的源端口并没有要求。
一句话总结:SMTP 25端口的outbound,就是邮件服务器使用SMTP协议去访问别人的25端口;SMTP 25端口的inbound,就是别人使用SMTP协议来访问邮件服务器的25端口。
关于发信服务器向收信服务器发邮件的具体过程可以下面这个图,这是我用自己的邮件服务器给139邮箱发送邮件时候的抓包流程,可以看到我的邮件服务器(发信服务器)先和139邮箱服务器(收信服务器)的25端口建立了tcp的3次握手,然后139邮箱服务器主动以25端口为源端口向我的邮件服务器发起了SMTP请求:
一般而言,云服务器供应商都会封锁云主机的25端口,这个封锁25端口其实是指outbound的封锁,就是为了防止你随便架设个邮件服务器就开始发垃圾邮件,毕竟SMTP协议本身因为出现得较早,导致对发件方缺乏验证机制,认证机制的缺乏导致了SMTP协议是包容的,当然也就包括了垃圾邮件。
其实就算云供应商封锁了25端口(outbound),也只是让你的邮件服务器不能直接使用SMTP协议发邮件,SMTP 25端口inbound没封锁,收别的邮件服务器使用SMTP发的邮件还是没问题的。
如果要向云供应商申请解除这个25端口封锁,首先需要你买的云主机是比较昂贵的包年预付费的云主机类型,其次申请了解封还需要看运气能不能过审。我因为买的腾讯云主机是最便宜的轻量级服务器,所以都没资格申请解封,最后只能用家庭宽带了。
配置域名解析记录
架设邮件服务器必须先在你的域名供应商上设置好相关的DNS记录。以域名是example.com为例,需要在域名供应商上的example.com域里添加的dns记录如下图所示:
以上的MX和TXT类型对应的主机记录@表示邮箱后缀是example.com,如果邮箱后缀是其他的二级域名,比如”@mail.example.com”,则这里的@就应该改成“mail.example.com”。3个CNAME的作用是为了给邮件客户端提供不同协议访问的服务器地址,方便记忆而已,其实不是必须的,直接使用mail.example.com也是一样的。
前面3条记录是必须配置的:A记录和MX记录这2条记录加在一起,能让你的邮箱正常收到邮件。A记录和TXT(这个TXT本来应该是SPF记录,由于有些域名供应商不支持SPF记录,所以用TXT代替,内容是一样的)加在一起,能让你的邮箱发送的邮件可以通过收件人邮箱基本的SPF安全检测。
你的邮箱在SMTP 25端口 outbound能用的情况下,本来就能正常发出邮件到达各个邮件提供商的邮件服务器上,但是能不能最终进入收件人的收件箱甚至垃圾箱,就是另外一个方面的问题了,我们在下一节”邮件评分”中单独来讲。
另,因为我的家庭宽带的出口地址是动态公网IPv4,所以需要用工具将出口的公网地址实时同步到腾讯云的dnspod域名管理上,这点我是通过爱快路由器自带的动态域名工具来完成的,这点很重要,因为涉及到SPF记录,具体的在下一节中详细讲。
邮件评分
上一节我们提到,只要SMTP 25端口的outbound可用,则你邮箱作为发信邮箱给其他邮箱地址发送的邮件都能到达目的邮箱服务器(感谢SMTP协议的包容性)。但是因为这个包容性,垃圾邮件也一样可以到达。。所以各个邮箱服务的供应商都会有一套自己的评分体系来鉴别一封邮件是否是垃圾邮件。虽然评分体系各不相同,但是却有一些最基本的判断步骤是一致的:
rDNS
reverse DNS(反向DNS),根据IP反向解析成域名,主要是收信服务器根据收到的邮件的来源IP地址反向查询域名(叫反向是因为正向是域名查IP),然后和发件人邮箱域名对比,这里无外乎有2种结果:
1、查到了但是不一致,说明是假冒。
2、查不到,说明发件人域名的DNS上没有配置PTR记录,虽然不一定是坏人,但是肯定不是正规军。这种情况不同运营商的处置方式就不一样了,可能直接拒收或丢弃,也可能只是减印象分。
我是家庭宽带,没法做PTR记录,所以属于第2种情况。从我的测试结果来看,gmail,qq邮箱都收不到(连进垃圾邮箱的资格都没有。。),但是163邮箱,139邮箱都是可以的。
SPF记录
Sender Policy Framework(发件人策略框架),其目的是为了防止发件方随意伪造发件人。实现的原理很简单:收信人邮箱服务器会查询发信人邮箱后缀对应的IP地址,然后和已收到邮件的发送方IP地址对比是否一致。这个需要在发信人后缀域名对应的DNS域中设置SPF记录或者TXT记录(见上节内容)。SPF记录值有多种语法指定不同的IP,详细的语法大家可以自行搜索。
注意,不同的域名供应商的语法符号上可能有一定差别,例如对于上节内容中的”mx all”,意思是拒绝除了mx记录解析的IP以外的其他所有IP地址,这个”all”是在腾讯云dnspod上的写法,如果是阿里云邮箱,则是”-all”,所以大家在添加SPF记录的时候,看看各种域名提供商的相关说明。
DKIM
DomainKeys Identified Mail(域名密钥识别邮件),用于在邮件内容的邮件头中,添加发送方的数字签名,接收方收到邮件后,需要对邮件头中的数字签名进行验证,验证成功后邮件就是发送者亲自发送,否则就是伪造。
DKIM 的基本工作原理同样是基于传统的密钥认证方式,他会产生两组钥匙,公钥(public key)和私钥(private key),公钥将会存放在 DNS 中,而私钥会存放在寄信服务器中。私钥会自动产生,并依附在邮件头中,发送到寄信者的服务器里。公钥则放在DNS服务器上,供自动获得。收信的服务器,将会收到夹带在邮件头中的私钥和在DNS上自己获取公钥,然后进行比对,比较寄信者的域名是否合法,如果不合法,则判定为垃圾邮件。
poste的DKMI需要在web控制台中生成(后面我们会讲到),然后以TXT类型进行添加(其实就是上面提到的公钥)。
DMARC
DMARC(Domain-based Messaging, Authentication, Reporting and Conformance standard,基于网域的信息传递、身份验证、报告和一致性标准)是基于SPF和DKMI的解决方案,本质上是一组约定:邮件发送方通过其DNS公开标明自己会用到的发件服务器(通过SPF),并对发送的邮件使用私钥进行电子签名(通过DKMI);邮件接收方会检查收到的邮件是否来自发送方授权的邮件服务器(查询邮件域名对应的SPF记录)以及电子签名是否真实(根据DKMI记录提供的公钥),对于未能通过检查的邮件如何处理(拒收还是进入垃圾邮件箱)以及是否发送告知邮件给发件人邮箱。
如何配置
以上提到的4点落到实处其实就是对应于发件邮箱DNS中的4条记录:一条PTR记录用于(rDNS),一条SPF记录(或者TXT记录)用于SPF,一条TXT记录用于DKIM,一条TXT记录用于DMARC。
PTR记录有些VPS提供商可以直接提供,但是国内就难了,反正腾讯云上PTR记录对云主机类型有要求,而且5条PTR一年1500。
SPF记录的添加方式我在上节已经讲过,可以直接添加SPF记录类型,也可以用TXT记录的方式添加,内容都是一样的。
DKIM以TXT记录的方式添加,具体添加内容我们后面会讲到。
DMARC以TXT记录的方式添加,以腾讯云dnspod为例:
记录类型:TXT
主机记录:_dmarc
记录值:v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]
参数解释:
v=DMARC1
dmarc的版本号
p=none
用于告知收件方,当检测到某封邮件存在伪造发件人的情况,收件方要做出什么处理。有以下3种选择:p=none; 为收件方不作任何处理 p=quarantine; 为收件方将邮件标记为垃圾邮件 p=reject; 为收件方拒绝该邮件
rua=mailto:[email protected]
可选项,用于告诉收件方,汇总报告应该用哪个邮箱地址通知发件人。这个属于“建议零售价”,收件方接不接受建议就不好说了。
ruf=mailto:[email protected]
可选项,用于告诉收件方,如果收到通不过SPF、DKMI检查的邮件应用用哪个邮箱地址通知发件人。同rua,也是属于“建议”。
其实除了前面几个方面,发件方的IP地址本身也非常之重要:是否在黑名单中、是否是固定IP等都是收件方评分的重要标准。
可以通过一些工具网站在线查看ip地址或者域名是否在黑名单中,如下:
https://mxtoolbox.com/blacklists.aspx
docker安装poste
poste的docker命令如下:
docker run --name mailserver -d --restart=always --network=public-net \
--hostname "mail.example.com" \
-p 25:25 \
-p 110:110 \
-p 143:143 \
-p 465:465 \
-p 587:587 \
-p 993:993 \
-p 995:995 \
-p 4190:4190 \
-p 8080:80 \
-p 8443:443 \
-e "TZ=Asia/Shanghai" \
-e "DISABLE_CLAMAV=TRUE" \
-e "DISABLE_RSPAMD=FALSE" \
-e "DISABLE_ROUNDCUBE=FALSE" \
-e "HTTPS=OFF" \
-v /docker/poste.io/data:/data \
-v /etc/localtime:/etc/localtime:ro \
-t analogic/poste.io
端口说明:
如果架设邮件的服务器是有公网IP的云主机的话,除了webmail的8080和8443根据自己的的实际环境进行调整以外,其他端口宿主机的映射端口就不要变了,保持上图中的值不变。但是如果是内网部署的方式,像我这种家庭宽带,那宿主机上的映射端口是多少就无所谓了,主要在出口路由器上做好上图中端口的映射到宿主机上配置的端口就成。
参数说明:
–hostname “mail.example.com” 指定搭建邮箱的服务器公网IP对应的域名,就是在上一节域名配置中MX记录后面的记录值
-e “DISABLE_CLAMAV=TRUE”
禁用反病毒功能 减少系统资源消耗
-e “DISABLE_RSPAMD=FALSE”
禁用反垃圾邮件功能 减少系统资源消耗
-e “DISABLE_ROUNDCUBE=FALSE”
禁用web收发功能 如果只用客户端收发邮件,这个可以禁用,但是一般来说还是留着吧。
-e “HTTPS=OFF”
如果要配合反向代理使用,就需要这个选项,关闭http端口重定向到https端口的功能,一般用了这个,就不需要-p 8443:443
这个映射了
-v /docker/poste.io/data:/data
将宿主机的/docker/poste.io/data
目录挂载到容器的/data目录
-v /etc/localtime:/etc/localtime:ro
同步宿主机时钟
-t analogic/poste.io
指定镜像名字,这个主要是为了区分免费版和专业版
docker成功运行后,直接用http://宿主机IP:8080/admin/
即可访问poste的控制台。我因为是配合反向代理使用,所以用了-e "HTTPS=OFF"
参数,因此可以直接用http的方式访问。
配置poste
初始化
使用http://宿主机IP:8080/admin/登录设备:
首次登录需要配置邮件服务器的公网域名(域名部分A记录指定的),本例中就是mail.example.com,同时指定管理员邮箱地址以及密码,设置完以后点Submit进入。
创建DKIM
在Virtual domains右边选择example.com:
点击右边中部红框中的create a new key:
以下是生成的DKIM:
在上图中,红框中的
s20231026459._domainkey
部分就是DKIM对应TXT记录的主机记录,红框中的k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+dbUYLiyTlvAhyUINYw7FdHFNO8DSCMkQHbOAwQe0kWyGyDaXRRjp5LYPYawHIg+JyX+drnGepkg2w2rsN9UgNxkgKTnEmWLPGDdAwf2phjIKUT4Xw8y1TzL2nGaQK80lQWr1fNMxR8urcmiUZBCbQdPGRlqAVX1moymHd66Mk3MssvMW2WV9EjMJ5dqTplbP2NABuA+ygTtoP7zt1zo6QLTUvjsoD2hg26xtQy4DcXEtVzdlCjW22GUOwip7FyqiIgKfY2EGEzlsl7J5V+nisQzYqS6m7UUFSxqHr0EwKB8xMTvKCFofrwuWogTqsp9Gim01HDqLuTfLsHrynOhwIDAQAB
就是TXT记录的记录值。
设置TLS证书
如果要使用邮件客户端收发邮件并且使用SMTPs,IMAPs,POP3s这些加密的连接方式,则需要设置邮箱的TLS证书:
poste支持Let’s Encrypt自动申请证书和手动上传证书2种方式,见右边的红框部分:
Let’s Encrypt 方式比较简单,如下:
配置完成之后点击下方的save changes就会自动申请证书,不过这种方式应该是需要443端口才可以,我家宽没有,所以申请失败了,所以我用的腾讯云申请的免费证书并手动上传:
第一行是域名mail.example.com证书的私钥文件,第二行和第三行都选择域名的公钥证书文件就行了,最后点击下方的Save changes保存。
注:保存以后不会出现成功之类的字样,回闪一下然后又回到原样:
这是正常的,在映射目录的ssl文件夹下可以看到已经有了证书:
这个时候,poste已经可以正常收发邮件了,不过收邮件没问题,发邮件能不能到别人的收件箱里就要看前面邮件评分部分的配置如何了,邮箱评分情况可以参见下面的评分网站:
邮箱评分工具:https://www.mail-tester.com/
这个网站一个邮箱一天能测试3次,比如我的邮箱测试结果:
可以看到扣分项,橙色和红色应该是问题的严重程度,比如我第2项扣了3.1,点开以后可以看到详情:
可以看到最大的扣分项是PYZOR_CHECK和RDNS。RDNS这个是我的死血,没有办法,就这一项就让我邮箱发出的邮件被大型邮件服务供应商拒之门外了,那么PYZOR_CHECK是个啥呢?看了一下解释,原来是要求发送的邮件内容要真实,我就发了个测试2个字,估计被鄙视了。
这个测试分数作为参考就行,比如我上次测试的时候分数还高达8.9:
然并卵,收不到的还是收不到。
最后,要登录webmail,使用http://宿主机IP:8080/webmail/
即可登录邮箱:
配置公网访问
如果要发布到公网上的,大家需要根据实际环境和自己使用的反向代理选择最适合自己的发布方式,可以参考我以前的几篇文章:
1、docker系列 使用docker基于NPM搭建自己的反向代理
2、linux面板系列 配置反向代理并使用非443端口进行发布
3、家庭数据中心系列 通过国内备案云主机白嫖cloudflare实现国外快速访问国内站点
4、家庭数据中心系列 通过无公网IP的家庭宽带白嫖cloudflare实现快速建站(通用)
其中第1,2种方式适合有公网ip却没有合法443端口的环境(家庭宽带、未备案的云主机),需要在url后面加非标端口(如果使用cloudflare建站的不需要加端口,但是需要自定义源站端口,这个可以参考:家庭数据中心系列 通过cloudflare的Origin Rules解决建站有公网IP却没有合法的80、443端口的问题)。第3种方式适合有备案的云主机,第4种方式适合所有环境(包括没有公网IP的环境),也是我建议的方式(不管你的环境有没有公网IP,因为这种方式不需要直接在公网上跑https流量)。
另:使用nginx反向代理的替换功能可以隐藏web页面上的pro字样,看起来清爽了一点点,也没啥用。。
后话
终于写完了,写这篇文章好累,要查好多资料,花费的精力相当于写好多篇一般的文章了。后续我看看还有什么能补充的,家宽邮箱拿来收邮件装装逼还是没啥问题的,发的话,就要看运气了(正规大型邮件提供商的邮箱估计都悬),现在我测的163邮箱和139邮箱是能收到邮件的,gmail和qq邮箱收不到。如果真的要正儿八经的架邮件服务器,还是尽量用国外的支持rDNS的VPS把。
另:如果只有收邮件的需求,可以使用cloudflare的电子邮件路由功能,简单几步就实现了和自建邮件服务器一样的收邮件功能,具体配置步骤可以参见文章:家庭数据中心系列 使用cloudflare打造使用你自己域名后缀的邮箱小号 。