我正在使用 Postfix TLS 策略来强制外发电子邮件使用 TLS。不幸的是,在某些情况下证书验证会失败,但我不知道原因。
例如,这是我的 TLS 政策的摘录
#/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
facebook.com secure ciphers=high
hearst.com secure match=gslb.pphosted.com ciphers=high
fastmail.fm secure ciphers=high
这 3 家提供商都使用相同的根 CA。我可以毫无问题地向 facebook.com 发送电子邮件。对于 hearst.com,我必须指定 CN 匹配,因为证书没有正确的 SAN 字段。我不明白为什么我还必须为 fastmail.fm 添加匹配 CN。否则证书验证会失败。证书是可信的,目标服务器名称为 smtp.messagingengine.com,证书具有与其匹配的 SAN 字段 (*.messagingengine.com)
Feb 25 21:57:22 mail postfix/smtp[25291]: Trusted TLS connection established to in1-smtp.messagingengine.com[66.111.4.74]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Feb 25 21:57:22 mail postfix/smtp[25291]: D33A02504112: to=<[email protected]>, relay=in1-smtp.messagingengine.com[66.111.4.74]:25, delay=8.4, delays=0.02/0/8.4/0, dsn=4.7.5, status=deferred (Server certificate not verified)
有人知道为什么证书不被接受吗?有没有建议强制执行“安全”的 TLS 策略,而无需指定匹配规则?
版本详细信息
root@mail:/etc/postfix# uname -a
Linux mail.EXAMPLE.com 3.13.0-65-generic #106-Ubuntu SMP Fri Oct 2 22:08:27 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
root@mail:/etc/postfix# postconf -d | grep mail_version
mail_version = 2.11.0
milter_macro_v = $mail_name $mail_version
扩展日志
Feb 25 21:57:22 mail postfix/smtp[25291]: setting up TLS connection to in1-smtp.messagingengine.com[66.111.4.74]:25
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: TLS cipher list "aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH:!MD5:!DES:!ADH:!RC4:!PSD:!SRP:!3DES:!eNULL:!aNULL"
Feb 25 21:57:22 mail postfix/smtp[25291]: looking for session smtp&fastmail.fm&in1-smtp.messagingengine.com&66.111.4.74&&FC83E1ADCEDFC581CE5F87CAF6E49FEFFF83CD0F9EBC0B57C4A19ED3DC3416EC in smtp cache
Feb 25 21:57:22 mail postfix/tlsmgr[25292]: lookup smtp session id=smtp&fastmail.fm&in1-smtp.messagingengine.com&66.111.4.74&&FC83E1ADCEDFC581CE5F87CAF6E49FEFFF83CD0F9EBC0B57C4A19ED3DC3416EC
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:before/connect initialization
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:unknown state
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read server hello A
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: depth=2 verify=1 subject=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: depth=1 verify=1 subject=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: depth=0 verify=1 subject=/C=AU/ST=Victoria/L=Melbourne/O=FastMail Pty Ltd/CN=*.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read server certificate A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read server key exchange A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read server done A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 write client key exchange A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 write change cipher spec A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 write finished A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 flush data
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read server session ticket A
Feb 25 21:57:22 mail postfix/smtp[25291]: SSL_connect:SSLv3 read finished A
Feb 25 21:57:22 mail postfix/smtp[25291]: save session smtp&fastmail.fm&in1-smtp.messagingengine.com&66.111.4.74&&FC83E1ADCEDFC581CE5F87CAF6E49FEFFF83CD0F9EBC0B57C4A19ED3DC3416EC to smtp cache
Feb 25 21:57:22 mail postfix/tlsmgr[25292]: put smtp session id=smtp&fastmail.fm&in1-smtp.messagingengine.com&66.111.4.74&&FC83E1ADCEDFC581CE5F87CAF6E49FEFFF83CD0F9EBC0B57C4A19ED3DC3416EC [data 1788 bytes]
Feb 25 21:57:22 mail postfix/tlsmgr[25292]: write smtp TLS cache entry smtp&fastmail.fm&in1-smtp.messagingengine.com&66.111.4.74&&FC83E1ADCEDFC581CE5F87CAF6E49FEFFF83CD0F9EBC0B57C4A19ED3DC3416EC: time=1456433842 [data 1788 bytes]
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: *.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: mail.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: dav.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: caldav.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subjectAltName: carddav.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25 CommonName *.messagingengine.com
Feb 25 21:57:22 mail postfix/smtp[25291]: in1-smtp.messagingengine.com[66.111.4.74]:25: subject_CN=*.messagingengine.com, issuer_CN=DigiCert SHA2 High Assurance Server CA, fingerprint=D8:F5:7E:43:A8:DA:29:22:6B:7E:90:A6:31:86:C8:CD, pkey_fingerprint=49:07:46:E5:F1:35:C2:96:75:09:67:BE:D9:FE:DB:46
Feb 25 21:57:22 mail postfix/smtp[25291]: Trusted TLS connection established to in1-smtp.messagingengine.com[66.111.4.74]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Feb 25 21:57:22 mail postfix/smtp[25291]: D33A02504112: to=<[email protected]>, relay=in1-smtp.messagingengine.com[66.111.4.74]:25, delay=8.4, delays=0.02/0/8.4/0, dsn=4.7.5, status=deferred (Server certificate not verified)
主配置文件
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
smtpd_banner = mail.EXAMPLE.com ESMTP $mail_name (nou)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# TLS parameters
smtpd_tls_cert_file = /etc/ssl/certs/EXAMPLE.com.crt
smtpd_tls_key_file = /etc/ssl/private/EXAMPLE.com.key
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_security_level = may
smtpd_tls_mandatory_ciphers = high
smtp_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL
smtpd_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL
smtpd_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_starttls_timeout = 300s
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
smtpd_tls_eecdh_grade = strong
tls_preempt_cipherlist = yes
#smtp_tls_note_starttls_offer = yes
#smtp_tls_per_site = may
# Logging
smtp_tls_loglevel = 2
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = mail.EXAMPLE.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = mail.EXAMPLE.com, localhost.contabo.host, localhost
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
# Handing off local delivery to Dovecot's LMTP
virtual_transport = lmtp:unix:private/dovecot-lmtp
#Enabling SMTP for authenticated users, and handing off authentication to Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtp_tls_security_level = may
# Force TLS for outgoing server connection
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
smtp_tls_CApath = /etc/postfix/rootcas/
#Virtual domains, users, and aliases
virtual_mailbox_domains = /etc/postfix/virtual_mailbox_domains
virtual_mailbox_base = /var/mail/vhosts
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
virtual_alias_maps = hash:/etc/postfix/valias
# DKIM
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
content_filter = smtp-amavis:[127.0.0.1]:10024
message_size_limit = 0
主配置文件
smtp inet n - - - - smtpd
submission inet n - - - - smtpd
-o smtpd_tls_security_level=may
pickup unix n - - 60 1 pickup
-o content_filter=
-o receive_override_options=no_header_body_checks
cleanup unix n - - - 0 cleanup
qmgr unix n - n 300 1 qmgr
#qmgr unix n - n 300 1 oqmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
relay unix - - - - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
maildrop unix - n n - - pipe
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}
smtp-amavis unix - - - - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
-o max_use=20
127.0.0.1:10025 inet n - - - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_delay_reject=no
-o smtpd_client_restrictions=permit_mynetworks,reject
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=reject_unauth_pipelining
-o smtpd_end_of_data_restrictions=
-o mynetworks=127.0.0.0/8
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000
-o smtpd_client_connection_count_limit=0
-o smtpd_client_connection_rate_limit=0
-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
答案1
使用secure
级别,您要求后缀验证收件人和服务器的关系,但在安全的方式(不依赖 DNS 数据)
它正确地启动值得信赖TLS 连接(证书由您了解/信任的 CA 签名)
然后它尝试安全验证服务器/收件人,如果有任何 CN/SAN 与 fastmail.fm 匹配 - 并且它们不匹配。因此该消息在本地队列中被延迟。
证书messagesingengine.com/gslb.phosted.com不保证他们接受的其他域名。facebook.com验证了自身。
您secure
通过添加match
MX 进行了修改 - 这verify
实际上是这样做的。因此,您可以下拉进行验证,或者继续添加匹配项。
smtp_tls_security_level
may
TLS?很好。没有 TLS?很好。encrypt
接受任何无效的服务器证书,要求加密。verify
接受受信任的服务器证书(我信任 CA 吗?CN 是否与 MX 匹配?),要求加密。secure
如果 CN/SAN 与收件人域匹配,则仅接受受信任的证书 - 并忽略不安全的 (MX) 信息进行验证。
这postfix 文档在解释差异时有些不清楚。
答案2
在 /etc/postfix/main.cf 文件中你可以放置此指令:
smtp_tls_secure_cert_match = hostname, nexthop, dot-nexthop
将其放入 main.cf 将允许 DNS MX 记录中的主机名匹配被允许用于安全策略级别。这实际上只是将安全策略级别转换为验证策略级别,因此您不妨将 tls 策略级别更改为验证或更低级别。要回答您关于导致其失败的原因的问题,您的原始收件人是
当你设置 TLS 策略来保护控制变量时
smtp_tls_secure_cert_match(默认值:nexthop,dot-nexthop)
并且 nexthop 除非在传输表中有一个覆盖,否则将按照下面发布的 man 5 postconf 页面中讨论的那样确定。
下一跳域,可以是收件人域,也可以是为域配置的传输下一跳
该电子邮件地址的安全策略中的下一跳是fastmail.fmMX 记录中唯一的域名是消息引擎网站,在安全策略下它永远不会匹配。但是查看 fastmail.fm 的 MX 记录。
[[email protected] openssl]# host -t MX fastmail.fm
fastmail.fm mail is handled by 10 in1-smtp.messagingengine.com.
fastmail.fm mail is handled by 20 in2-smtp.messagingengine.com.
如果您放宽安全证书匹配指令以包含主机名(同样与 smtp_tls_security_level = verify 完全相同)证书将根据指向的 MX 记录进行验证in1-smtp.messagingengine.com匹配通用名称 *.messagingengine.com. 这也发生在[电子邮件保护],我相信还有很多其他人,就像他们在 postconf 的 man 5 页中说的那样
smtp_tls_security_level (default: empty)
verify Mandatory TLS verification. At this security level, DNS MX lookups are trusted to be secure enough, and the name verified in the server certificate is usually
obtained indirectly via unauthenticated DNS MX lookups. The smtp_tls_verify_cert_match parameter controls how the server name is verified. In practice
explicit control over matching is more common at the "secure" level, described below. This security level is not an appropriate default for systems delivering
mail to the Internet.
secure Secure-channel TLS. At this security level, DNS MX lookups, though potentially used to determine the candidate next-hop gateway IP addresses, are not trusted
to be secure enough for TLS peername verification. Instead, the default name verified in the server certificate is obtained from the next-hop domain as speci‐
fied in the smtp_tls_secure_cert_match configuration parameter. The default matching rule is that a server certificate matches when its name is equal to or is
a sub-domain of the nexthop domain. This security level is not an appropriate default for systems delivering mail to the Internet.
对于向互联网传递邮件的系统来说,此安全级别不是合适的默认级别。
然后它再次表明 tls 策略验证也是如此,但这就是它总是会失败的原因。
请参阅 postconf man5 页中上面引用的两个指令:
smtp_tls_secure_cert_match (default: nexthop, dot-nexthop)
How the Postfix SMTP client verifies the server certificate peername for the "secure" TLS security level. In a "secure" TLS policy table ($smtp_tls_policy_maps)
entry the optional "match" attribute overrides this main.cf setting.
This parameter specifies one or more patterns or strategies separated by commas, whitespace or colons. In the policy table the only valid separator is the colon
character.
For a description of the pattern and strategy syntax see the smtp_tls_verify_cert_match parameter. The "hostname" strategy should be avoided in this context, as in
the absence of a secure global DNS, using the results of MX lookups in certificate verification is not immune to active (man-in-the-middle) attacks on DNS.
Sample main.cf setting:
smtp_tls_secure_cert_match = nexthop
Sample policy table override:
example.net secure match=example.com:.example.com
.example.net secure match=example.com:.example.com
This feature is available in Postfix 2.3 and later.
它还引用了 smtp_tls_verify_cert_match 以便更好地理解
smtp_tls_verify_cert_match (default: hostname)
How the Postfix SMTP client verifies the server certificate peername for the "verify" TLS security level. In a "verify" TLS policy table ($smtp_tls_policy_maps)
entry the optional "match" attribute overrides this main.cf setting.
This parameter specifies one or more patterns or strategies separated by commas, whitespace or colons. In the policy table the only valid separator is the colon
character.
Patterns specify domain names, or domain name suffixes:
example.com
Match the example.com domain, i.e. one of the names the server certificate must be example.com, upper and lower case distinctions are ignored.
.example.com
Match subdomains of the example.com domain, i.e. match a name in the server certificate that consists of a non-zero number of labels followed by a .exam‐
ple.com suffix. Case distinctions are ignored.
Strategies specify a transformation from the next-hop domain to the expected name in the server certificate:
nexthop
Match against the next-hop domain, which is either the recipient domain, or the transport next-hop configured for the domain stripped of any optional socket
type prefix, enclosing square brackets and trailing port. When MX lookups are not suppressed, this is the original nexthop domain prior to the MX lookup, not
the result of the MX lookup. For LMTP delivery via UNIX-domain sockets, the verified next-hop name is $myhostname. This strategy is suitable for use with the
"secure" policy. Case is ignored.
dot-nexthop
As above, but match server certificate names that are subdomains of the next-hop domain. Case is ignored.
hostname
Match against the hostname of the server, often obtained via an unauthenticated DNS MX lookup. For LMTP delivery via UNIX-domain sockets, the verified name is
$myhostname. This matches the verification strategy of the "MUST" keyword in the obsolete smtp_tls_per_site table, and is suitable for use with the "verify"
security level. When the next-hop name is enclosed in square brackets to suppress MX lookups, the "hostname" strategy is the same as the "nexthop" strategy.
Case is ignored.
Sample main.cf setting:
smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop
Sample policy table override:
example.com verify match=hostname:nexthop
.example.com verify match=example.com:.example.com:hostname