How to get postfix to relay incoming email to a specific host and outgoing mail to any host required

emailpostfixPROXY

I have a postfix setup like this:

     __________                     +-----+     |F|        +-----+
  __(          )____               /     /|     |I|       /     /|
 (___  (         ___)             /     / |     |R|      /     / |
    _(  Internet )     <=====>   +-----+  |  <==|E|==>  +-----+  |
   (___,     )   _)              |  M  |  |     |W|     |  H  |  |
       (_________)               |  A  |  +     |A|     |  O  |  +
                                 |  I  | /      |L|     |  S  | /
                                 |  L  |/       |L|     |  T  |/
                                 +--+--+        | |     +-----+

I have things configured right now to relay email from mail to host. Here's the output of postconf -n on mail:

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
config_directory = /etc/postfix
inet_interfaces = all
inet_protocols = ipv4
mailbox_size_limit = 0
message_size_limit = 41943040
mydestination =
myhostname = example.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 203.0.113.190
readme_directory = no
recipient_delimiter = +
relay_domains = host.example.com, example.com, example.org,
relayhost = [host.example.com]:587
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_loglevel = 1
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination,
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination,
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = smtpd
smtpd_sasl_security_options = noanonymous, noplaintext,
smtpd_sasl_tls_security_options = noanonymous,
smtpd_sasl_type = cyrus
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5,
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3,
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
tls_preempt_cipherlist = yes

This works perfectly – I can send mail from gmail and other providers and they properly end out in my mailbox on host.

However, when I try to send email from host I'm pretty sure it's trying to relay the email back from mail to host. I see this in the host logs:

Dec 28 16:44:28 host postfix/submission/smtpd[29743]: warning: hostname mail2.example.com does not resolve to address 203.0.113.14: Name or service not known
Dec 28 16:44:28 host postfix/submission/smtpd[29743]: connect from unknown[203.0.113.14]
Dec 28 16:44:28 host postfix/submission/smtpd[29743]: Anonymous TLS connection established from unknown[203.0.113.14]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Dec 28 16:44:28 host postfix/submission/smtpd[29743]: NOQUEUE: reject: RCPT from unknown[203.0.113.14]: 454 4.7.1 <me@gmail.com>: Relay access denied; from=<wayne@example.com> to=<me@gmail.com> proto=ESMTP helo=<example.com>
Dec 28 16:44:28 host postfix/submission/smtpd[29743]: disconnect from unknown[203.0.113.14]

And then on mail I'm getting these logs:

Dec 28 16:54:27 mail postfix/smtp[17899]: Untrusted TLS connection established to host.example.com[203.0.113.190]:587: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Dec 28 16:54:28 mail postfix/smtp[17899]: 7B6A620FFB: to=<me@gmail.com>, relay=host.example.com[203.0.113.190]:587, delay=1064, delays=1063/0.01/0.71/0.08, dsn=4.7.1, status=deferred (host host.example.com[203.0.113.190] said: 454 4.7.1 <me@gmail.com>: Relay access denied (in reply to RCPT TO command))

On host, here's my postconf -n output:

alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
config_directory = /etc/postfix
inet_interfaces = all
inet_protocols = ipv4
mailbox_size_limit = 0
message_size_limit = 41943040
mydestination = host, host.example.com, example.com
myhostname = host.example.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
readme_directory = no
recipient_delimiter = +
relay_domains = $mydestination
relayhost = example.com:587
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_loglevel = 1
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination,
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination,
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = smtpd
smtpd_sasl_security_options = noanonymous, noplaintext,
smtpd_sasl_tls_security_options = noanonymous,
smtpd_sasl_type = cyrus
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5,
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3,
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
tls_preempt_cipherlist = yes
postconf: warning: /etc/postfix/main.cf: unused parameter: compatibility_level=2

Basically what I want:

On host or mail:

  • if email is sent to wayne@host, wayne@mail, wayne@host.example.com, wayne@example.com, wayne@example.org I want that to be delivered to the local user on `host.
  • if email is sent to anywhere elseasdf@asdf.com, foo@bar.com, me@gmail.com or wherever it happens to be – I want host to relay through mail, and I want mail to send the email to whatever server that it's supposed to send it to.

How do I configure postfix to properly do this?

Best Answer

Turns out this was way easier than I expected it to be. The clue was found in the documentation for relay_transport:

In order of decreasing precedence, the nexthop destination is taken from $relay_transport, $sender_dependent_relayhost_maps, $relayhost, or from the recipient domain. This information can be overruled with the transport(5) table

(emphasis mine)

I wanted to flip that around - I wanted the recipient domain to come first and then the relayhost. Since the docs said I could look at the transport(5) table, that's what I did. And I found this tidbit:

local_transport (default: local:$myhostname)
          This is the default for final delivery to  domains  listed  with
          mydestination,  and  for  [ipaddress]  destinations  that  match
          $inet_interfaces or $proxy_interfaces. The default nexthop  des-
          tination is the MTA hostname.

That looked promising. If I understood it correctly that means that I could use smtp:host.example.com:587 as my local_transport and use mydestination instead of relay_domains. And guess what? It worked!

So instead of:

mydestination =
relay_domains = host.example.com, example.com, example.org,
relayhost = [host.example.com]:587

I just had

mydestination = host.example.com, example.com, example.org,
local_transport = smtp:[host.example.com]:587

And it works exactly as desired, success!