电子邮件服务器DKIM配置
时间:2022-05-03
本文章向大家介绍电子邮件服务器DKIM配置,主要内容包括4.3. dkim、4.3.2. 测试、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
本文节选自《Netkiller Mail 手札》
4.3. dkim
DKIM(DomainKeys Identified Mail) 是一种电子邮件的验证技术,使用密码学的基础提供了签名与验证的功能。DKIM 能增加你邮件的信任度。
安装 OpenDKIM 环境是CentOS 7
yum install -y opendkim
查看配置文件
[root@mail.netkiller.cn ~]# egrep -v "^#|^$" /etc/opendkim.conf
PidFile /var/run/opendkim/opendkim.pid
Mode sv
Syslog yes
SyslogSuccess yes
LogWhy yes
UserID opendkim:opendkim
Socket inet:8891@localhost
Umask 002
SendReports yes
SoftwareHeader yes
Canonicalization relaxed/relaxed
Selector default
MinimumKeyBits 1024
KeyFile /etc/opendkim/keys/default.private
KeyTable /etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
InternalHosts refile:/etc/opendkim/TrustedHosts
OversignHeaders From
生成公钥和私钥example.com 替换成你的域名
mkdir /etc/opendkim/keys/example.com
opendkim-genkey -D /etc/opendkim/keys/example.com/ -d example.com -s default
chown -R opendkim: /etc/opendkim/keys/example.com
ln -s /etc/opendkim/keys/example.com/default.private /etc/opendkim/keys/default.private
将你域名example.com添加到/etc/opendkim/KeyTable格式如下:
default._domainkey.example.com example.com:default:/etc/opendkim/keys/example.com/default.private
接下来修改 /etc/opendkim/SigningTable 并添加如下记录
*@example.com default._domainkey.example.com
添加信任主机到/etc/opendkim/TrustedHosts,通常是 example.com / mail.example.com
example.com
mail.example.com
注意:TrustedHosts 是发送邮件机器的IP,不是邮件服务器的IP,例如你的WEB服务器连接到邮件服务器发送电子邮件,那么TrustedHosts 就是你的WEB服务器IP地址。
至此 opendkim 已经配置完毕。
现在需要配置域名TXT记录解析,开打文件 /etc/opendkim/keys/example.com/default.txt 参照下面配置
cat /etc/opendkim/keys/example.com/default.txt
default._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5anjIUkTgJT8DSBL2tiydi6DZLIMnPnveFBcyKshwIuGeRzIN2PwQW5F/bvQWdatPLGuw0w5mKXtATJtarbWXy89BgjcJgAGrPSr8GdzsNH0RXRqTy1A21BQyGER3Mx2Fbr6J62reTG2i7jY0w3/cxzuFIGlSn/RP/KrlMze4zQIDAQAB" ) ; ----- DKIM key default for example.com
接下来配置postfix把OpenDKIM整合到Postfix修改/etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
milter_protocol = 2
启动 opendkim,重启 postfix
systemctl enable opendkim.service
systemctl start opendkim.service
systemctl restart postfix.service
检查opendkim状态与端口
# systemctl status opendkim.service
● opendkim.service - DomainKeys Identified Mail (DKIM) Milter
Loaded: loaded (/usr/lib/systemd/system/opendkim.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2016-08-25 02:07:42 EDT; 6s ago
Docs: man:opendkim(8)
man:opendkim.conf(5)
man:opendkim-genkey(8)
man:opendkim-genzone(8)
man:opendkim-testadsp(8)
man:opendkim-testkey
http://www.opendkim.org/docs.html
Process: 12577 ExecStart=/usr/sbin/opendkim $OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 12578 (opendkim)
CGroup: /system.slice/opendkim.service
└─12578 /usr/sbin/opendkim -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid
Aug 25 02:07:42 localhost.localdomain systemd[1]: Starting DomainKeys Identified Mail (DKIM) Milter...
Aug 25 02:07:42 localhost.localdomain systemd[1]: Started DomainKeys Identified Mail (DKIM) Milter.
Aug 25 02:07:42 localhost.localdomain opendkim[12578]: OpenDKIM Filter v2.10.3 starting (args: -x /etc/opendkim.conf -P /var/run/opendkim/opendkim.pid)
# ss -lnt | grep 8891
LISTEN 0 128 127.0.0.1:8891 *:*
4.3.1. 增加域名
创建证书
mkdir /etc/opendkim/keys/mydomain.com
opendkim-genkey -D /etc/opendkim/keys/mydomain.com/ -r -d mydomain.com
chown -R opendkim: /etc/opendkim/keys/mydomain.com
配置 KeyTable
default._domainkey.mydomain.com mydomain.com:default:/etc/opendkim/keys/mydomain.com/default.private
配置 SigningTable
*@mydomain.com default._domainkey.mydomain.com
4.3.2. 测试
/var/log/maillog
Aug 26 03:02:03 localhost postfix/smtpd[5837]: connect from unknown[155.133.82.144]
Aug 26 03:02:03 localhost opendkim[5762]: configuration reloaded from /etc/opendkim.conf
Aug 26 03:02:04 localhost postfix/smtpd[5837]: lost connection after AUTH from unknown[155.133.82.144]
Aug 26 03:02:04 localhost postfix/smtpd[5837]: disconnect from unknown[155.133.82.144]
Aug 26 03:02:09 localhost postfix/smtpd[5837]: connect from unknown[202.130.101.34]
Aug 26 03:02:10 localhost postfix/smtpd[5837]: 27EEC802C1C5: client=unknown[202.130.101.34]
Aug 26 03:02:10 localhost postfix/cleanup[5843]: 27EEC802C1C5: message-id=<1770496307.0.1472194929612@Server>
Aug 26 03:02:10 localhost opendkim[5762]: 27EEC802C1C5: DKIM-Signature field added (s=default, d=cf139.com)
Aug 26 03:02:10 localhost postfix/qmgr[4605]: 27EEC802C1C5: from=<neo@netkiller.cn>, size=531, nrcpt=1 (queue active)
Aug 26 03:02:10 localhost postfix/smtpd[5837]: disconnect from unknown[202.130.101.34]
Aug 26 03:02:10 localhost postfix/smtp[5844]: connect to gmail-smtp-in.l.google.com[2607:f8b0:400e:c03::1b]:25: Network is unreachable
Aug 26 03:02:11 localhost postfix/smtp[5844]: 27EEC802C1C5: to=<netkiller@msn.com>, relay=gmail-smtp-in.l.google.com[74.125.25.26]:25, delay=1.6, delays=0.58/0.01/0.48/0.49, dsn=2.0.0, status=sent (250 2.0.0 OK 1472194931 om6si19759602pac.41 - gsmtp)
Aug 26 03:02:11 localhost postfix/qmgr[4605]: 27EEC802C1C5: removed
查看原件原文,如果正常会显示DKIM-Filter和DKIM-Signature两项
Delivered-To: netkiller@msn.com
Received: by 10.28.169.3 with SMTP id s3csp180808wme;
Fri, 26 Aug 2016 00:02:11 -0700 (PDT)
X-Received: by 10.66.10.234 with SMTP id l10mr3141577pab.69.1472194931522;
Fri, 26 Aug 2016 00:02:11 -0700 (PDT)
Return-Path: <neo@netkiller.cn>
Received: from mail.cf139.com ([104.243.134.186])
by mx.google.com with ESMTP id om6si19759602pac.41.2016.08.26.00.02.11
for <netkiller@msn.com>;
Fri, 26 Aug 2016 00:02:11 -0700 (PDT)
Received-SPF: pass (google.com: domain of neo@netkiller.cn designates 104.243.134.186 as permitted sender) client-ip=104.243.134.186;
Authentication-Results: mx.google.com;
dkim=temperror (no key for signature) header.i=@cf139.com;
spf=pass (google.com: domain of neo@netkiller.cn designates 104.243.134.186 as permitted sender) smtp.mailfrom=neo@netkiller.cn
Received: from Server (unknown [202.130.101.34])
by mail.cf139.com (Postfix) with ESMTP id 27EEC802C1C5
for <netkiller@msn.com>; Fri, 26 Aug 2016 03:02:09 -0400 (EDT)
DKIM-Filter: OpenDKIM Filter v2.10.3 mail.cf139.com 27EEC802C1C5
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cf139.com;
s=default; t=1472194930;
bh=aTYsMuMwFaanDPkTLEncpu/hxKsNsCaozbJRmQJ6aho=;
h=Date:From:To:Subject:From;
b=qPYy2TPDv+zxHQ2gqGOwVsgRm42E3p6WvSxdXgUaLtkY6LH6657cdEa96HYJLVqHC
EygkTz+3n7WePhGH9jAJrb/PBrGIK1XVCREz4ayfUxc3QUwFSQ9o+5ULkExxdhyRUu
4TiCbkcUMbYI3YXJqGiU0OBCyTq655trOaWBby+k=
Date: Fri, 26 Aug 2016 15:02:09 +0800 (CST)
From: neo@netkiller.cn
To: netkiller@msn.com
Message-ID: <1770496307.0.1472194929612@Server>
Subject: =?UTF-8?B?5Li76aKY77ya566A5Y2V6YKu5Lu2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
5rWL6K+V6YKu5Lu25YaF5a65
- Python编程中的反模式
- Python机器学习库:Scikit-Learn简介
- 很简单的企业管理器---我写程序的方式,几个自定义控件。
- 使命必达: 深入剖析WCF的可靠会话[原理揭秘篇](上)
- 其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
- 为Symfony2和Redis正名,基于PHP的10亿请求/周网站打造
- 如何使用Python基线预测进行时间序列预测
- 如何使用统计显着性检验来解释机器学习结果
- 其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
- WCF服务端运行时架构体系详解[上篇]
- 使命必达: 深入剖析WCF的可靠会话[编程篇](下)
- 在网页里让文本框只能输入数字的一种方法。外加回车换Tab
- 如何用Python从零开始实现简单的线性回归
- 使命必达: 深入剖析WCF的可靠会话[编程篇](上)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python全栈(七)Flask框架之5.视图高级--类视图和蓝图
- Python全栈(六)项目前导之5.使用GitHub进行多人协同开发
- 附002.Nginx代理相关模块解析
- ApiBoot v2.3.x分支第一个版本发布,重构源码架构设计
- Python全栈(七)Flask框架之1.Flask简介与URL和视图介绍
- 两个CSS知识点:BFC和选择器权重
- C语言入门系列之9.预处理
- Python爬虫常见异常及解决办法
- 理解nodejs中js和c++的通信原理
- 如何使用FFmpeg将互联网直播点播平台内直播视频流转化为HLS流?
- 记一次nodejs问题排查
- 使用Go语言编译互联网视频直播点播平台EasyDSS出现ld returned 1 exit status错误
- c/c++补完计划(四): 字节对齐和虚继承
- Python 不用selenium 带你高效爬取京东商品评论
- 《闲扯Redis六》Redis五种数据类型之Hash型