1. 什么是DKIM
DomainKeys Identified Mail (DKIM) 是一种电子邮件验证系统,旨在帮助接收邮件服务器确定某个电子邮件是否真的由声称拥有其发件人地址的域所授权并发送。DKIM通过使用公钥密码学和数字签名技术来增强电子邮件的安全性和可靠性。
2. DKIM工作原理
2.1 密钥生成与存储:
- 发送域首先生成一对公钥和私钥。私钥保留在邮件服务器上,并用于签署即将发出的邮件。
- 公钥则作为DKIM记录存储在发送域的DNS记录中,通常是以TXT类型的DNS记录形式存在。
2.2 邮件签署:
- 当邮件从授权的服务器发出时,邮件服务器会使用私钥对邮件的部分或全部内容(通常是邮件头和主体的一部分)进行加密签名。
- 这个签名被添加到邮件头部的DKIM-Signature字段中,包含了一系列标识符(比如d=域名、s=选择器、bh=散列摘要、b=签名数据等)。
2.3 邮件验证:
- 当邮件到达接收方邮件服务器时,服务器会提取DKIM-Signature头信息,并查找与邮件中标识的域名和选择器相对应的DKIM记录。
- 接收方邮件服务器从DNS中获取到相应的公钥后,使用该公钥对邮件签名进行解密验证。
如果数字签名验证通过,则表明邮件内容在传输过程中未被篡改,并且邮件的确是从声称的域名授权的服务器发送的。
3. DKIM记录
DKIM记录的格式是在DNS(Domain Name System)中以TXT类型的资源记录形式存在的,它包含了公开可用的DKIM公钥和其他相关参数,以便邮件接收服务器能够验证发送自特定域名的电子邮件的真实性。DKIM记录的核心组成部分包括以下几个部分:
selector._domainkey.domain.tld. TTL IN TXT "v=DKIM1; k=rsa; p=base64_public_key"
selector:
这是一个可自定义的选择器,用于区分同一域名下可能有的多个DKIM密钥对。选择器通常代表一个特定的邮件服务器或服务,使得同一个域名下的不同邮件流可以用不同的DKIM密钥进行签名。selector需要配置到邮件系统上,不同品牌的邮件系统配置方法不同。
_domainkey:
这是一个固定的子域名前缀,用来标识这是一个DKIM相关的DNS记录。
domain.tld:
指的是要验证的域名,即邮件声称的发件人地址所属的域名。例如,如果发件人为user@example.com,那么这里将是example.com。
TTL:
Time To Live,生存时间,指定DNS记录在缓存中的有效时间(以秒为单位),在此期间其他DNS服务器无需重新查询记录。
IN:
Internet 类型,表明这是一个互联网资源记录。
TXT:
表明这是一个文本记录类型。
“v=DKIM1; k=rsa; p=base64_public_key”:
这是一个字符串值,其中包含了DKIM记录的具体参数:
- v: 版本号,这里是DKIM1,指DKIM协议版本1。
- k: 密钥类型,此处的rsa表示使用RSA算法的公钥。
- p: 公钥本身,它是私钥对应的公钥,经过Base64编码后的字符串形式,邮件服务器可以通过这个公钥验证邮件头部携带的DKIM签名。
此外,DKIM TXT记录还可能包含其他参数,如:
- t=:签名时间戳选项。
- s=:服务类型选项,用于限定签名的应用范围。
- h=:签名头列表,列出哪些邮件头会被纳入签名计算中。
- g=:公钥管理规范(GUA)选项,指向另一个URI,可用于更新公钥信息。
DKIM签名实际应用时,邮件头部会有DKIM-Signature字段(下文会做介绍),其中的d=(domain)、s=(selector)等标签与DNS中的DKIM TXT记录对应,共同完成邮件的身份验证过程。
4. DKIM配置示例
4.1 生成密钥
在Linux系统,可以通过openssl命令分别生成公钥和私钥。生成私钥命令示例如下,生成的私钥需要配置到邮件系统上(具体配置方法需要咨询邮件系统厂商):
[root@localhost tmp]# openssl genrsa -out rsa.private 1024 Generating RSA private key, 1024 bit long modulus
.................++++++
........................++++++
e is 65537 (0x10001)
生成公钥命令示如下,生成的公钥需要配置到域名的DNS记录中:
[root@localhost tmp]# openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
# 下面命令是列出公钥信息
[root@localhost tmp]# cat rsa.public
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDATePPt6HZkegPZq3Rt5EJzl3
tVV8VEC3TroXsw11mf/JKXGETYtnjm08unmnjkemIGPKOwnuWCQNR3nEWwYzQAa1
2YXTHVuntqfdohDGlGQB7DHkvTp3R5bw4u16yrkZ816C6pLAXgHtd/YEffoZMehe
gX/upuGfo6yhScgEkQIDAQAB
-----END PUBLIC KEY-----
4.2 配置私钥
私钥需要配置到邮件系统中,具体配置方法需要咨询您的邮件系统提供商。同时,如何启用DKIM功能也需要咨询您的邮件系统提供商。
4.3 配置公钥
公钥需要配置到DNS解析记录中,以mailabc.cn域名为例,在阿里云的域名控制台添加TXT类型的记录,记录值配置如下:
阿里云域名解析界面
其中记录类型为TXT;主机记录为dkim._domainkey,这里的dkim属于自定义的selector;记录值如下,其中p=表示上面生成的公钥。
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDATePPt6HZkegPZq3Rt5EJzl3tVV8VEC3TroXsw11mf/JKXGETYtnjm08unmnjkemIGPKOwnuWCQNR3nEWwYzQAa12YXTHVuntqfdohDGlGQB7DHkvTp3R5bw4u16yrkZ816C6pLAXgHtd/YEffoZMehegX/upuGfo6yhScgEkQIDAQAB
DNS记录配置完成后,可以通过dig或nslookup查询。以mailabc.cn域名为例,查询结果如下:
[root@localhost tmp]# dig dkim._domainkey.mailabc.cn txt
;; ANSWER SECTION:
dkim._domainkey.mailabc.cn. 600 IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDATePPt6HZkegPZq3Rt5EJzl3tVV8VEC3TroXsw11mf/JKXGETYtnjm08unmnjkemIGPKOwnuWCQNR3nEWwYzQAa12YXTHVuntqfdohDGlGQB7DHkvTp3R5bw4u16yrkZ816C6pLAXgHtd/YEffoZMehegX/upuGfo6yhScgEkQIDAQAB"
至此,所有配置工作完成。
5. 如何验证邮件启用了DKIM签名?
上文提到当启用DKIM签名时,在信头中会存在DKIM-Signature字段,以t1@mailabc.cn给163.com的邮箱发送邮件为例,在信头中存在如下信息:
启用DKIM签名后的信头
当信头中存在上述签名信息,则表明发信方启用了DKIM签名。
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=mailabc.cn; s=dkim; h=Received:Date:From:To:Subject:
Content-Type:MIME-Version:Message-ID; bh=u1bnFmVtzdAeVZ2afeXyEnM
Ns4aUQjMDjQnsu5zkeds=; b=Jk7hVIFXExhLitRylf/MmzlWqB4Lf+zq+Y7/+Pa
ZGnCkKMNcTjs3DAwcr99vgTlMaVXhKMusDGuC7OVUFAPMyFlnlXbWyXgR/SNdP2Y
DmpA2TWnJ260aNsgx4a56sR4RSrMBCZG0hZQZ3jeoGdIgI1C7sXlLvgAvouWqSvp
F3kw=
以上述信头为例,DKIM-Signature内容解释如下:
🔹 v=1: 表示DKIM签名的版本为1。
🔹 a=rsa-sha256: 指定使用的签名算法是RSA加密算法配合SHA-256哈希算法。
🔹 c=relaxed/relaxed: 指定头部canonicalization(规范化)方式。在这个例子中,”relaxed”表示对邮件头部字段的处理方式较为宽松,允许一些非关键字符(如多余的空格、换行符等)被忽略,同时在处理顺序上也可以不严格遵循RFC规定的顺序。
🔹 d=mailabc.cn: 表示该签名关联的域名是mailabc.cn,即邮件声称来自这个域名。
🔹 s=dkim: 表示签名的选择器(selector),用于在DNS中查找对应的DKIM公钥记录。
🔹 h=Received: Date: From: To: Subject: Content-Type: MIME-Version: Message-ID:: 列出了参与签名计算的邮件头部字段,这些字段的内容将被哈希化然后用私钥签名。
🔹 bh=u1bnFmVtzdAeVZ2afeXyEnMNs4aUQjMDjQnsu5zkeds=: 这是一个基于选定头部字段计算得出的哈希摘要,采用的是base64编码。
🔹 b=Jk7hVIFXExhLitRylf/MmzlWqB4Lf+zq+Y7/+PaZGnCkKMNcTjs3DAwcr99vgTlMaVXhKMusDGuC7OVUFAPMyFlnlXbWyXgR/SNdP2YDmpA2TWnJ260aNsgx4a56sR4RSrMBCZG0hZQZ3jeoGdIgI1C7sXlLvgAvouWqSvpF3kw=: 这是签名数据,也是base64编码后的结果,包含了经过私钥签名的哈希值。当接收邮件服务器收到这封邮件时,会根据d=和s=的值去DNS中查找对应的DKIM TXT记录,获取公钥。然后,服务器会对邮件头部中列出的字段按照同样的方式进行规范化处理,计算出新的哈希值,并利用获取到的公钥验证签名的有效性。如果验证成功,则说明邮件的来源得到了DKIM签名保护,提高了邮件的可信度。