Search code examples
network-programmingdockerpostfix-mta

Docker and inconsistent IP addresses from host


I am trying to setup some containers to manage my personal emails on my VPS.

I've set up TLS encryption for the postfix server. While setting up SPF to detect forged emails, I discovered that the reported IP is not the same depending if encryption is used:

When receiving email from some senders:

Received: from zproxy.mydomain.com (zproxy110.mydomain.com [137.**.**.**])
    by localhost (Postfix) with ESMTP id 5250459F

When receiving email from my GMail account (TLS-enabled):

Received: from mail-lf0-x241.google.com (dockerhost [172.18.0.1])
    (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
    (No client certificate requested)
    by localhost (Postfix) with ESMTPS id 2EDEF59F

When receiving email from some other network:

Received: from cabale.usenet-fr.net (dockerhost [172.18.0.1])
    by localhost (Postfix) with ESMTP id 834F8520

It looks like the reported IP is the IP of the Docker host on a... random basis, using IP 172.18.0.1. Besides being a problem by itself, it also affects SPF as emails from Google are tagged as SoftFail as the IP is not allowed.

I haven't been able to understand why some servers (always) report the dockerhost IP, and some don't. This is not related to the TLS encryption as I though in the first place.

Here is my master.cnf file:

# 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/postfix-cert.pem
smtpd_tls_key_file = /etc/ssl/private/postfix-cert.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination check_policy_service unix:private/policy-spf
myhostname = localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = /etc/mailname, 11687faae091, localhost.localdomain, 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
virtual_gid_maps = static:5000
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2,!SSLv3,TLSv1,TLSv1.1,TLSv1.2
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,TLSv1,TLSv1.1,TLSv1.2
smtpd_tls_mandatory_exclude_ciphers = aNULL,MD5,RC4
smtpd_tls_mandatory_ciphers = high
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_mandatory_protocols = !SSLv2,!SSLv3,TLSv1,TLSv1.1,TLSv1.2
smtp_tls_protocols = !SSLv2,!SSLv3,TLSv1,TLSv1.1,TLSv1.2
smtp_tls_mandatory_exclude_ciphers = aNULL,MD5,RC4
policy-spf_time_limit = 3600s

And my main.cnf file:

smtp       inet  n       -       n       -       -       smtpd
pickup     unix  n       -       n       60      1       pickup
cleanup    unix  n       -       n       -       0       cleanup
qmgr       unix  n       -       n       300     1       qmgr
tlsmgr     unix  -       -       n       1000?   1       tlsmgr
rewrite    unix  -       -       n       -       -       trivial-rewrite
bounce     unix  -       -       n       -       0       bounce
defer      unix  -       -       n       -       0       bounce
trace      unix  -       -       n       -       0       bounce
verify     unix  -       -       n       -       1       verify
flush      unix  n       -       n       1000?   0       flush
proxymap   unix  -       -       n       -       -       proxymap
proxywrite unix  -       -       n       -       1       proxymap
smtp       unix  -       -       n       -       -       smtp
relay      unix  -       -       n       -       -       smtp
showq      unix  n       -       n       -       -       showq
error      unix  -       -       n       -       -       error
retry      unix  -       -       n       -       -       error
discard    unix  -       -       n       -       -       discard
local      unix  -       n       n       -       -       local
virtual    unix  -       n       n       -       -       virtual
lmtp       unix  -       -       n       -       -       lmtp
anvil      unix  -       -       n       -       1       anvil
scache     unix  -       -       n       -       1       scache
maildrop   unix  -       n       n       -       -       pipe flags=DRhu
    user=vmail argv=/usr/bin/maildrop -d ${recipient}
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}
dovecot   unix  -       n       n       -       -       pipe
    flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -a ${recipient}
submission inet n       -       -       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
policy-spf  unix  -       n       n       -       -       spawn
    user=nobody argv=/usr/bin/policyd-spf

Where does this behavior come from and how can I patch it so that the reported IP is the actual one?

EDIT: OK, I just tested from another provider and it looks like encryption may have nothing to do with it:

Received: from o1.30e.fshared.sendgrid.net (o1.30e.fshared.sendgrid.net [167.89.55.41])
    (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))

Solution

  • This is a known bug in current (2016-10-10) Docker versions: The userland proxy is used to bind the container ports to the host port but has the inconsistencies you experienced. I'm having the same problem myself.

    References:

    • https://github.com/docker/docker/issues/15086 - base issue regarding the problem, suggested best solution is to disable the userland proxy and use iptables instead to route the port(s)
    • https://github.com/docker/docker/issues/14856 - efforts are made to disable the userland proxy by default but are currently blocked, see below
    • using "--userland-proxy=false" can cause serious problems with the host networking so it is currently not recommended, see docker issue #5618