搭建邮箱服务器遇到的发送邮件的问题

我在机房搭建了几台 Postfix,代理机房机器给公司邮箱发邮件( 公司使用 Gmail ),默认邮件会被谷歌拒收,这里需要注意一下。

 

1. SPF。

Sender Policy Framework (SPF) records allow domain owners to publish a list of IP addresses or subnets that are authorized to send email on their behalf.  The goal is to reduce the amount of spam and fraud by making it much harder for malicious senders to disguise their identity.  To learn more, visit the SPF Website.

SPF 的规则是:

接收方会验证发送方的公网 IP,如果接收方域名的 SPF 记录中包含这个 IP,认为是正确的邮件,否则认为是伪造的。

举个例子: 13_F7_9T$T}WM61VQTE`O[GD

2JN23o423osrwerwe

23G234o23u4nsdf

v=spf1 表示是第一版的 SPF;

include 表示包含这个域名的 SPF;

~all 表示如果都不匹配,SoftFail,如果 -all,表示都不匹配直接 Fail,如果 +all,表示通过,SPF 规则就无用了,如果 ?all 表示 Neutral,中立,你自己看着办。

此外,还有几个机制:

mx,表示如果发送方 IP 在此域名的 mx 记录解析结果里,通过;

a,比如 a:mx1.nosa.me a:mx2.nosa.me,如果发送方 IP 在 a 指定的域名解析结果中,那么通过;

ptr,比如 ptr:otherdomain1.com ptr:otherdomain2.com,官方解释:The hostname or hostnames for the client IP are looked up using PTR queries. The hostnames are then validated: at least one of the A records for a PTR hostname must match the original client IP. Invalid hostnames are discarded. If a valid hostname ends in domain, this mechanism matches。官方建议关闭,因为会带来大量的解析查询。

 

更多的机制看这里:

http://www.openspf.org/SPF_Record_Syntax

http://www.spfwizard.net/  这个网站可以生成 SPF ( TXT ) 记录。

 

2. DKIM。

DomainKeys Identified Mail (DKIM)  对邮件进行签名,防止内容被篡改。

在 Centos 下可以使用 dkim-milter 这个包(或者 opendkim ),比如:

EBDB8091-78E0-4522-B54F-97883FBDDDC4

通过在 dkim-filter.conf 配置使用 mx 这两个文件,mx.private 是私钥,mx.txt 则是包含公钥,看下 mx.txt 的内容:

mx._domainkey IN TXT “v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2dzV0IjYa76/Wc0WLMFhv4eCeZZX1mudLzQ003siBr1XG1oCnrPRClPchpPYigdODj/hyAP5tqHpaV8yskjgHByAL4WzsqxV6N8JPyrxejLfR+TN/Q3FTDvyLJZgsr6JuaHPO2hCT6ymNk/TbAX3VbDjJltLkc3GI/gcKWtm1TQIDAQAB” ; —– DKIM mx for nosa.me

此时解析一下 mx._domainkey.nosa.me TXT,可以看到:

99D80393B

 

DDNS 报错:RRset exists (value dependent)’ prerequisite not satisfied

问题场景:

我们的装机系统使用 DHCP + DNS 环境来保存 SN 和 控制卡 IP 的映射关系,很久之前开始发现控制卡因为损坏更换之后,使用 idrac-SN 解析出来的 IP 是老的,连不上,而 控制卡已经通过 DHCP 获得了新的 IP ( 通过 /var/lib/dhcpd/dhcpd.leases 查看 )。

 

看 DNS 的日志 /var/named/data/named.run 有类似如下报错:

21-Jul-2015 16:13:37.002 client 10.2.1.1#19205: updating zone ‘ilo.xxx.com/IN’: update unsuccessful: idrac-1K39D02.ilo.xxx.com: ‘name not in use’ prerequisite not satisfied (YXDOMAIN)
21-Jul-2015 16:13:37.003 client 10.2.1.1#44065: updating zone ‘ilo.xxx.com/IN’: update unsuccessful: idrac-1K39D02.ilo.xxx.com/TXT: ‘RRset exists (value dependent)’ prerequisite not satisfied (NXRRSET)

看起来是 DHCPD 更新 DNS 失败,显示 TXT 已经存在,条件不满足。

TXT 在这里是 mac 和 控制卡 hostname 等的哈希,更换控制卡之后 TXT 发生变化,和 DNS 中的 TXT 不一致,所以更新不了。

然后我做了两个尝试:
1. 把 DNS 中的 TXT/A/PTR 记录删掉,重启控制卡重新获取 IP,发现 DNS 此时可以正确加上;
2. 只把 TXT 记录删掉,同样重启控制卡重新获取 IP,不会添加 DNS。

 

手动删除 TXT/A/PTR 记录太麻烦了,最好的方法是在 DHCP 中加一个选项:

update-conflict-detection false

如果 TXT 不存在或者不匹配,都会重写 TXT/A/PTR 到 DNS,是完全 OK 的,已验证。

 

http://comments.gmane.org/gmane.network.dhcp.isc.dhcp-client/6202

https://lists.isc.org/pipermail/dhcp-users/2013-January/016367.html

https://lists.isc.org/pipermail/dhcp-users/2013-January/016378.html

 

把 DNS 域的 @ 配置成 CNAME 的一个坑

如果你在一个域里面( 比如 test.com. )同时配置下面两条记录:

@ CNAME 默认(或其他线路) www.test.com.
@ MX         默认(或其他线路) 「记录值」.

那么 向 test.com. 域发邮件可能失败,原因是:

CNAME 其实只是一个别名,DNS 服务器在收到常规 DNS 记录 (非 CNAME )请求的时候会检查是否已经有对应的 CNAME 记录,如果有就重新启动对 CNAME 值的查询并返回,如果显示指定查询的就是 CNAME 记录,则直接返回。

所以,即使在配了 CNAME 之后又配置了 A、MX 等记录,也没用,因为 CNAME 优先级高。

 

记住,「请不要对 @ 设置 CNAME 记录」。

 

RFC 的说明如下:

When a DNS resolver encounters a CNAME record while looking for a regular resource record, it will restart the query using the canonical name instead of the original name. (If the resolver is specifically told to look for CNAME records, the canonical name (right-hand side) is returned, rather than restarting the query.)

An alias defined in a CNAME record must have no other resource records of other types (MX, A, etc.). (RFC 1034 section 3.6.2, RFC 1912 section 2.4) The exception is when DNSSEC is being used, in which case there can be DNSSEC related records such as RRSIG, NSEC, etc. (RFC 2181 section 10.1)

 

参考

http://blog.clanzx.net/2013/09/02/dns-cname.html

 

update at Sat Jul 18 10:13:15 CST 2015

增加一点,AWS 的 route53 可以通过 alias 实现对 @ 增加 CNAME 记录,但只限于 LB 和 S3 等服务,具体请看  http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html

http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html

0FA5B5CB-62E7-4441-AE4C-95D729B51EAC

 

 

构建机房运维基础架构(四): 机器装机初始配置(DELL)

我们的服务器基本是DELL的,所以下面的配置是针对DELL 最新的R420 R720等服务器的,机器在经过下面的配置之后运到机房,插线之后即可通过SN解析到控制卡IP。

其他机器型号(HP,HUAWEI等)的配置找其他资料哈。

 

1.  把第一块网卡设置成 none,第二块网卡设置成 PXE 启动模式(出厂默认第一块网卡是PXE模式,我们自己用第二块网卡装机,所以给第一块关掉。)

如下:

CTRL + S 进入配置

cc9fb7c0985a670ee56e917d11b8cad4

 

2. 关于远程控制卡,需要设置为 Dedicated 模式,开启 DHCP,并使用DHCP获取到的DNS (因为我们的远程控制卡IP是自动获取的,用来装机,这点很重要)

222

8388bd6b0ea330eaa5349e772bb54080

76c9349f8bd80b57dc6521d6066192bd

 

3. Boot Mode 和 Boot Seq 设置  (720 720xd等 默认是UEFI,把它改成 BIOS;启动顺序 为 Hard drive C:,第二块网卡,第一块网卡。 )

3dacb5207bfe3be34b84b8dda1b02dbc

4fff19561d207d2b03ab04bf8071847f

 

 

 

这里只列出了自动装机需要的配置,其他的配置比如电源设置、风扇设置等没写,可以参考:

https://www.evernote.com/shard/s240/sh/292d15ba-404d-4d54-912e-ff5fa325713d/c67904c014276b864364104b48017612

 

 

 

构建机房运维基础架构(三): 自动装机流程

流程

1. 根据 SN 去 DDNS 请求 ILO IP

2. 设置第二块网卡支持PXE启动 (通过 ssh root@$iloip 设置)。

3. 设置启动顺序,硬盘启动第一优先级,第二块网卡第二优先级。

4. 设置机器从PXE启动一次。

5. 重启

6. 拷贝对应的tftp 配置文件(根据mac地址命名文件名)

7. 机器从第二块网卡启动PXE,通过DHCP获取到IP,DHCP告诉机器 tftp服务器的IP

8. 机器连接tftp服务器,获取内核文件,加载内核,并获取到 tftp配置文件,并根据配置文件去请求 ks 文件。

9. 拿到ks文件,执行装机流程,包括 语言、时区、硬盘格式化、防火墙 等等。

10. 执行到post阶段,开始执行自己的自定义脚本。

11. 我们的装机类型有三种:
1) raw_clean (纯净物理机)
2) kvm_host  (宿主机)
3) kvm_guest (虚拟机)

我们的自定义脚本是post_install.sh ,会自动装好三种 类型的机器;脚本做的最重要的事情有:
1) 通用初始化
2) 获取主机名和IP,并配置到系统
3) 准备好增加本机主机名到DNS的脚本到机器上。
4) 准备puppet执行环境

这个脚本也是最可能需要动的了。

12. post 阶段 之后 是 重启,重启之后DNS脚本自动执行,把自己的主机名增加DNS,然后Puppet 开始执行初始化环境 ( Puppet会自动把资产和监控的客户端安装好,资产的客户端会把机器信息上传到资产系统 )。

 

注意的问题

1. 物理装机我们用DHCP指定的 DNS —

    option domain-name-servers 10.0.12.234;
    option domain-name “nosa.me;

虚拟机装机的时候在virt-install 命令里 要手动指定一个 dns server —

   -x “ip=xxx netmask=xxx gateway=xxx dns=xxx “ 

这样会解析所有的全域名,但是遇到 前缀域名就完蛋了,因为 kickstart 不支持search nosa.me 之类的语法;这个问题导致了我的Puppet 不能工作,初始化失败。

所以可以在post阶段 执行下面这个命令:
  echo “search nosa.me” >>/etc/resolv.conf

此乃大坑。