Weblog entry #49 for lee

Whitelisting hosts in Exim4 causing TLS errors
Posted by lee on Sun 15 Dec 2013 at 17:27
Tags:

By the end of 2013 the minimum key-size for signed TLS certificates will be 2048 bits. Older 1024 bit certificates will be revoked and web browsers will throw errors on anyone attempting to connect using 1024 bit keys.

Unfortunately, in the context of server-to-server opportunistic encryption, such as used by ESMTPS, this is a dangerous choice. 1024 bit encryption is still far harder to decode than plaintext (which is currently the usual fall-back delivery).

Sadly that's what's happened in some Debian derived releases of Exim4 (using GnuTLS). An affected mail server will likely see something like the following in the logs:

TLS error on connection to mail.example.com [10.81.102.77] (gnutls_handshake): The Diffie-Hellman prime sent by the server is not acceptable (not long enough).

(Even worse, the choice to increase the minimum prime size also breaks connections to many servers that implement EDH - i.e. Ephemeral Diffie-Hellman with smaller encryption keys such as allowed by export.)

The quickest way to check if a remote mail server has a small key is to run a command such as:

$ echo QUIT | openssl s_client -connect mail.example.com:25 -starttls smtp 2>/dev/null| grep "public key is"

If the server public key is less than 2048 bit in size, you may want to contact the postmaster or other administrative contact to let them know they need to generate a new server key.[1] If the key is 2048 bit and above, you may need to use another tool to see what's happening.

As of Exim 4.80 there is a new transport option, tls_dh_min_bits, which lets the minimum key size to be set.

So if this affects you, you could modify the minimum key size for the default transport (add " TLS_DH_MIN_BITS = 512 "). However, for these sort of workarounds it's my preference to add in special-case configuration.

(Filenames assume the split-config of debian deployments.)

Create /etc/exim4/conf.d/transport/40_temp_tls_smallprime (a modified copy of 30_exim4-config_remote_smtp)

remote_smtp_tls_smallprime:
  debug_print = "T: remote_smtp_tls_smallprime for $local_part@$domain"
  driver = smtp
  multi_domain = false
  tls_dh_min_bits = 512
.ifdef REMOTE_SMTP_HEADERS_REWRITE
  headers_rewrite = REMOTE_SMTP_HEADERS_REWRITE
.endif
.ifdef REMOTE_SMTP_RETURN_PATH
  return_path = REMOTE_SMTP_RETURN_PATH
.endif
.ifdef REMOTE_SMTP_HELO_DATA
  helo_data=REMOTE_SMTP_HELO_DATA
.endif
.ifdef DKIM_DOMAIN
dkim_domain = DKIM_DOMAIN
.endif
.ifdef DKIM_SELECTOR
dkim_selector = DKIM_SELECTOR
.endif
.ifdef DKIM_PRIVATE_KEY
dkim_private_key = DKIM_PRIVATE_KEY
.endif
.ifdef DKIM_CANON
dkim_canon = DKIM_CANON
.endif
.ifdef DKIM_STRICT
dkim_strict = DKIM_STRICT
.endif
.ifdef DKIM_SIGN_HEADERS
dkim_sign_headers = DKIM_SIGN_HEADERS
.endif

Then create /etc/exim4/conf.d/router/177_temp_tls_smallprime (i.e. so it appears before the normal external router) with two entries, one for mail servers that have <2048 keys, and ones that negotiate EDH.

dnslookup_tls_smallprime:
  debug_print = "R: dnslookup_tls_smallprime for $local_part@$domain"
  driver = dnslookup
  domains = ! +local_domains : ! +relay_to_domains
  condition = ${if forany{${lookup dnsdb{>: mxh=$domain}}}{match_domain{$item}{+smallkey}}}
  transport = remote_smtp_tls_smallprime
  same_domain_copy_routing = yes
  no_more

dnslookup_tls_export:
  debug_print = "R: dnslookup_tls_edh for $local_part@$domain"
  driver = dnslookup
  domains = ! +local_domains : ! +relay_to_domains
  condition = ${if forany{${lookup dnsdb{>: mxh=$domain}}}{match_domain{$item}{+tlsexport}}}
  transport = remote_smtp_tls_smallprime
  same_domain_copy_routing = yes
  no_more

Then you add in the lists of mail servers to your main config. For example adding the following to /etc/exim4/conf.d/main/10_temp_smallprime

## Servers that present small keys
domainlist smallkey = oldserver.example.com : mx2.example.org
## Hosts that use large keys to sign small "export" size keys for encryption
domainlist tlsexport = *.example.com

[1] It may be more complex than that, of course.[3] While most MTAs operating in client mode would be expected to deal with a 2048 bit key, there are known older email clients that would not be able to cope with keys larger than 1024 bits. Servers may need to maintain backward compatibility for these older clients.

[2] Using GnuTLS to inspect the key negotiation is slightly more involved since you need to do the SMTP negotiation

$ gnutls-cli --crlf --insecure --starttls --port 25 server.example.com
220 server.example.com ESMTP
EHLO my.host.name
250-server.example.com Hello my.host.name
250-AUTH LOGIN
250-AUTH=LOGIN
250-STARTTLS
250 HELP
STARTTLS
220 TLS go ahead
(Hit Ctrl-D)
*** Starting TLS handshake
- Ephemeral Diffie-Hellman parameters
- Using prime: 768 bits
- Secret key: 766 bits
- Peer's public key: 767 bits
[...]
QUIT

[3] You'll note that the example above, adapted from a real "secure email provider", tops out at 768 bits. Which is still the US export limit for asymmetric algorithms used by exported software not in the public domain. They use a 2048 bit key merely to sign the small key used to encrypt the session.