当前位置: 代码迷 >> 综合 >> 2020-11-29 漫谈email之smtp、pop3、spf dkim
  详细解决方案

2020-11-29 漫谈email之smtp、pop3、spf dkim

热度:29   发布时间:2023-12-15 15:13:03.0

一. 基础篇

SMTP表示发件服务器,POP3(或IMAP)表示收件服务器,这些名词就不赘述了,相信大家早已耳熟能详。下面是一个电子邮件在网上简单的交互的流程:

  • 发件人:me@qq.com 收件人:you@gmail.com
  • me@qq.com 用邮件客户端(比如outlook)写了一封邮件给you@gmail.com,点下发送按钮后,邮件首先会发送到smtp.qq.com
  • smtp.qq.com 检索到这封邮件的收件人域名是gmail.com,于是通过互联网(WAN)将邮件发送到smtp.gmail.com
  • smtp.gmail.com确认收下邮件后,将它转存到邮件服务器的硬盘中待收。

观察以上流程,你会发现smtp服务器其实身兼了 “收、发” 两个功能,在整个流程中, 对于smtp.qq.com而言,是发送。 而从smtp.gmail.com的角度来看,则是接收。那么,咱们平时经常说起的 “收件服务器pop3” 又是怎么回事呢,整个流程似乎看不到它的身影?

pop3(或imap服务器,与之性质相同)更多的是起一个中转作用,它将存储在邮件服务器硬盘中的邮件搬运回邮件客户端(user agent),换句话说它只负责从邮件服务器到邮件客户端这段路径,而邮件在广域网上的传递与它没有关系。
如图:


  • SPF和DKIM又是干什么用的呢?

为了防伪,用来检查一封电邮是否来自其所声称的发送者。

回想一下在纸质邮件时代,我们是怎么写信的,
首先,信纸信封是不同的两个东西,里面都包含有发件人和收件人信息,请注意,实际上出现了两个发件人,一是信封上的那个发件人,另一个是信纸里落款时那个发件人,两者一般来说是一致的。但也有可能不一样,过去并没有太好的防伪措施,但通过签名来判断发件人身份也不失为一个方法。

电子邮件也有类似的 “信封” 和 “信纸” 的概念,但电子邮件的 “信封” 对于普通用户通常是不可见的。那么问题来了,比如我收到一封email,其信封上的发件人是某诈骗网站badguy.com,但是这封邮件自己声称(信纸上写的)来自qq.com,因为我看不到信封,我就会误认为这封邮件真的是腾讯(qq.com)发给我的。

那么,怎么知道对方的身份是否真的就是他“声称”的那个呢?对不起,还真没办法!过去在纸质邮件时代最低限度大家还可以瞧瞧签名是不是假的,电子邮件并没有签名这一说,因此,防伪手段非但没有进步,反而是更不堪了。

为了遏制电子邮件欺诈,于是人们就想出了SPF和DKIM。
其根本目的是为了解决 “我真的是我” 这个问题。


基本原理:
SPF:通过存放在DNS服务器内的IP来验证电子邮件的真实来源。
例如example.com对应ip: 111.222.233.244,则一切发件人冠以example.com的邮件,必须是以111.222.233.244这台服务器发出的才是真实的,如果不是这个ip,则是假冒的。

DKIM:同样通过DNS服务器来实现,通过一对公私钥来验证电子邮件的真实来源。
例如example.com有一对非对称加密的公私钥证书,公钥已经公布在DNS里了,任何人都能获取,同时example.com还根据自身持有的私钥加密了一小段信息藏在邮件头里,
当该邮件发送到目标SMTP服务器的时候,首先对方会在DNS服务器里找到example.com的公钥,然后再用这把公钥试图去解密邮件头里夹带的那一小段内容,如果解密成功,说明这封邮件确实是从example.com发过来的,如果解密失败,则说明是伪造的,如此一来,想要冒充example.com作为发件人则只剩下两个途径:

  1. 篡改放在DNS服务器里的公钥
  2. 想办法搞到example.com的私钥

很显然,挑战以上任何一项都绝非易事,邮件欺诈者很难再像过去一样,通过盗用发件人姓名、改变附件属性等小伎俩达到目的了。

如果你对所谓的非对称加密、公钥、私钥这些知识还不太理解,建议先读一下这篇文章:https://zhuanlan.zhihu.com/p/42516761 [ 对称加密和非对称的加密 的优缺点和理解 ]


二.实战篇 (默认你已经装好了postfix)

1.设置spf

登录example.com的DNS管理界面,添加一条TXT记录,
host填:@
value填:v=spf1 mx ~all

@表示针对所有外域访问者
v=spf1表示这是一个SPF记录,并且SPF记录的版本是SPF1
mx ~all 表示只有从本IP发出去的邮件才是这个域名下发出的真实邮件,~all表示没有例外

  • 设置完毕后,回到本地系统。
  • 输入:
dig example.com txt

[ 验证spf信息是否正确写入了DNS ]
spf设置完毕,即当外域smtp服务器收到example.com这个域名的邮件时,会先到公众dns服务器去查验example.com所对应的IP地址,如果发现跟DNS里存储的IP不一致,则说明是冒牌货。

此外,example.com本身作为一台smtp服务器时,当收到外域邮件的时候,也需要具备这个功能,比如说当我们收到来自gmail.com的邮件时,我们也要先去DNS上查一下gmial.com所对应的ip,看看是不是冒充的。

  • 首先安装所需的软件包:
dnf install pypolicyd-spf -y
dnf install epel-release -y
  • 添加用户:policyd-spf :
adduser policyd-spf --user-group --no-create-home -s /bin/false
  • 编辑postfix的master设置文件,在文件末尾添加以下几行,告诉Postfix在启动SPF策略守护程序时自行启动。 Policyd-spf将以policyd-spf用户身份运行:
nano /etc/postfix/master.cf
#修改为:
policyd-spf  unix  -       n       n       -       0       spawnuser=policyd-spf argv=/usr/libexec/postfix/policyd-spf
  • 修改postfix的main设置文件,在文件末尾添加以下几行。 第一行指定Postfix策略代理超时设置(用于查询DNS)。 以下几行将通过检查SPF记录来限制传入电子邮件。
nano /etc/postfix/main.cf
#修改为:
policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination,check_policy_service unix:private/policyd-spf
  • 重启postfix:
systemctl restart postfix

2.设置DKIM
  1. 安装OpenDKIM
yum install opendkim -y
systemctl start opendkim
systemctl enable opendkim

  1. 修改配置文件:
nano /etc/opendkim.conf
#修改为:
Mode     sv
SendReports yes
KeyFile   /etc/opendkim/keys/example.com/12345678.private
KeyTable            /etc/opendkim/KeyTable
SigningTable        refile:/etc/opendkim/SigningTable
ExternalIgnoreList  refile:/etc/opendkim/TrustedHosts
InternalHosts       refile:/etc/opendkim/TrustedHost

  1. 创建签名表
nano /etc/opendkim/SigningTable
#在此文件的末尾添加以下行:
*@example.com    12345678._domainkey.example.com

这相当于告诉OpenDKIM,如果您服务器上的发件人正在使用@example.com地址,则应使用12345678._domainkey.example.com标识的私钥对其进行加密。

因为一个域名可以具有多个DKIM密钥,所以需要添加前缀以区分,在这里12345678没有什么特殊含义,是随便想出来的一个标识,这个标识你可以随意设定,但一定要注意前后一致,后面有多个地方会遇到它。


  1. 创建密钥表
nano /etc/opendkim/KeyTable 
#添加以下内容:
12345678._domainkey.littledot.net
example.com:12345678:/etc/opendkim/keys/example.com/12345678.private

  1. 创建可信任主机列表
nano /etc/opendkim/TrustedHosts
#默认情况下,此文件中包含127.0.0.0.1和:: 1。 现在添加以下行:
*.example.com

告诉OpenDKIM,如果电子邮件来自example.com本域,则不执行DKIM验证。


  1. 创建密钥对(公钥和私钥)
#创建一个存放钥匙的单独目录:
mkdir /etc/opendkim/keys/example.com
#创建两把密钥:
opendkim-genkey -b 2048 -d  example.com -D /etc/opendkim/keys/example.com -s 12345678 -v

上面的命令将创建两把2048位密钥。 -d(域)指定域。 -D(目录)指定将存储密钥的目录。 并使用12345678作为前缀, 执行命令后,私钥将被写入12345678.private文件,公钥将被写入12345678.txt文件。公钥创建完毕之后,需要手工在DNS中发布,私钥则用于加密邮件头,请务必保管好。


  1. 修改权限,让用户opendkim能够访问此文件:
chown opendkim:opendkim /etc/opendkim/keys/ -R
chmod 0600 /etc/opendkim/keys

  • 发布公钥
  1. 在example.com的DNS管理界面中,创建一条TXT记录,
    host填:12345678._domainkey
    那么value填什么呢?这比较麻烦,请按照以下操作一步一步来:
    第1步:返回到本地ssh窗口,
    第2步:执行cat命令查看公钥:
cat /etc/opendkim/keys/example.com/12345678.txt

第3步:复制括号中的所有内容(注意:需要删除值字段中的所有双引号和换行符)然后回到dns管理界面,将内容粘贴到value中。以下是一个参考文本:

v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu+7VSgwCUwpAIV+L5Nq3pwRqFV80ylncWpW7pgVUtCylj8lPUsdSV1RLfWn5Zd6afYHqHDFwyVvA66hijqyTQYjbmnZQOXPqkBdxhOt9KEfDh610rtMbwSltH4pl5brlsD9DuBBbvWzklFR676e5lhZFsG+oSnHxUzhflVrF3TUXRM3jrNT/V/EyF6DCxJAJX0Ear9snjC0AXftSNPofbl1IvHBUeU8bSZuYpDdZqHT9Wnxo0Cm3YXoNVEcvFrLS7D0PbYwjJ5xYeuqyZSRpQh1P9tQK4BKPatCimFbmULVIlG9+neH76dqbJmx/0Qa0Q5eMSPvdie2OhLT/+NBEowIDAQAB


  • 验证私钥和公钥是否对得上
    重启opendkim让设置生效:
systemctl restart opendkim

执行:

opendkim-testkey -d example.com -s 12345678 -vvv
  • 如果返回:opendkim-testkey: key OK 表示成功!

  • 现在,针对目标SMTP服务器的DKIM设置工作已经完成了,接下来,让咱们自己的SMTP也具备这个功能:
nano /etc/postfix/main.cf
#在此文件的末尾添加以下行,
#以便Postfix能够通过milter协议调用OpenDKIM。 
#请注意,您应该使用127.0.0.1作为地址, 不要使用localhost。# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters

保存并关闭文件。 然后将postfix用户添加到opendkim组。

gpasswd -a postfix opendkimsystemctl restart postfix [ 重启postfix ]

三. DMARC

  • 关于 DMARC, 它相当于spf和dkim的整合,以报告的形式向管理员汇报邮件服务器的防伪情况,汇报周期是可以更改的。 DMARC并不是必备的,但是添加了它之后您的邮件服务器 “尊重度” 将会提高。

具体的操作如下:

  1. 添加DNS TXT记录
    host填:_dmarc
    value填:v=DMARC1; p=none; pct=100; fo=1; rua=mailto:dmarck-reports@example.com

dmarck-reports@example.com 这个就是邮件管理者的邮件地址,即邮件报告的接收者,此账号必须是一个可用的电子邮件账号。

  1. 检查DMARC是否生效

方法1:
dig txt +short _dmarc.littledot.net
如果回显:"v=DMARC1; p=none; pct=100; fo=1; rua=mailto:dmarck-reports@littledot.net" 表示成功!

方法2:
yum install opendmarc -y
opendmarc-check littledot.net


四. 邮件服务器的 “受尊重度”

  • 由于前些年垃圾邮件泛滥成灾,大的邮件服务商都有对应的反垃圾邮件机制,一些上了黑名单的服务器直接会被他们将邮件放到用户的垃圾箱中。你肯定不希望自己的邮件进入这个黑名单吧,当然如果我们的邮件服务器是正常使用的话,倒也不至于此,一般来说一个全新的邮件服务器是不会进入黑名单的。但这并不能保证你就是一个值得信任的邮件服务器,因此邮件服务器的 “受尊重度” 这个概念就产生了。

  • 由于各大邮件服务商(gmail、yahoo、 网易、腾讯等等)的具体策略外人并不得而知,到底他们会将你的邮件怎么处理,所以也没有一个准数。但从总体来说,国内的几家邮件商还是比较宽松的,基本上设好了spf和dkim,都能做到通行无阻。最困难的应该算是gmail了,即使 spf+dkim+dmarc 这些都设好了,也不一定型。它还有一些比较奇特的参考策略,比如说这个域名绑定ip的时长,或者这个域名有没有对应www网站等等,烦不胜烦。

  • 最后,这个网站 https://www.mail-tester.com/ 可以测试你的邮件服务器尊重度得分,并且会对不足之处做出专业性建议,根据其生成的报告逐步完善吧。

  相关解决方案