On Fri, Dec 23, 2022 at 06:58:17PM +0400, Samer Afach <samer.af...@msn.com> 
wrote:

> Dear postfix experts:
> 
> I think I'm getting to the end of this problem. I was able to use haproxy to
> relay connections to my docker container with correct source information
> (and I'm seeing the correct IP addresses in the logs of postfix/dovecot). I
> would appreciate it if you could take a look at my settings before going
> public and changing the MX records back to this server.
> 
> How I tested: I was actively blocking/unblocking firewalls,
> starting/stopping containers (start, test, stop), and in every step, I ran
> swaks, with one of these configurations (in fact, I'm planning to automate
> these tests and run them periodically, what a nice tool this turned out to
> be):
> 
> swaks --to a...@example.com --from=b...@example.com --server 
> mail.example.com:587
> --tls
> swaks --to a...@example.com --from=b...@example.com --server 
> mail.example.com:465
> --tlsc
> swaks --to a...@example.com --from=b...@example.com --server 
> mail.example.com:25
> --tls
> swaks --to a...@example.com --from=b...@example.com --server 
> mail.example.com:25
> 
> I was consistently getting the result "Access denied" in swaks, which I hope
> means that no relaying is possible anymore. Meanwhile, I succeeded in
> sending messages with Thunderbird with proper authentication.
> 
> Email relaying was only possible when sending emails with swaks through
> localhost (even though it's going through the proxy in localhost), i.e.:
> 
> swaks --to a...@example.com --from=b...@example.com --server 127.0.0.1:587 
> --tls
> swaks --to a...@example.com --from=b...@example.com --server 127.0.0.1:465 
> --tlsc
> swaks --to a...@example.com --from=b...@example.com --server 127.0.0.1:25 
> --tls
> swaks --to a...@example.com --from=b...@example.com --server 127.0.0.1:25
> 
> Does this constitute proof that relaying isn't possible anymore?

It looks good. You can also employ and external
testing site such as mxtoolbox.com which includes an
open relay test (enter the hostname, click "MX Lookup",
then click "SMTP Test"). This would require that the
HAproxy address and a hostname is publically available
(even if it isn't yet pointed to by any MX record).

> There are three components to the configuration I added for this, each for
> one port:

I have a few unimportant but informative suggestions below.

> 1. Port 25
> 
> in master.cf:
> 
> ```
> 10024     inet  n       -       n       -       1       postscreen
> smtpd     pass  -       -       n       -       -       smtpd
> ```
> and in main.cf:
> 
> ```
> postscreen_upstream_proxy_protocol = haproxy
> ```
> 
> 2. Port 587 for strict STARTTLS:
> 
> ```
> 10587     inet     n    -    n    -    -    smtpd
>   -o syslog_name=postfix/haproxy_submission
>   -o smtpd_tls_security_level=encrypt
>   -o smtpd_tls_wrappermode=no

smtpd_tls_wrappermode=no is the default and so isn't needed.
It only needs to be set (to yes) for port 465.

>   -o smtpd_enforce_tls=yes

smtpd_enforce_tls=yes is redundant with smtpd_tls_security_level=encrypt.
It's the obsolete equivalent, and so it's ignored when
smtpd_tls_security_level is present.

>   -o smtpd_sasl_auth_enable=yes
>   -o 
> smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject

You probably don't want permit_mynetworks in the above.
"permit_sasl_authenticated,reject" is enough.

>   -o
> smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject

Again, permit_mynetworks isn't needed above.

>   -o smtpd_upstream_proxy_protocol=haproxy
> ```
> 
> 3. Port 465 for strict wrapper mode:
> ```
> 10465     inet  n       -       n       -       -       smtpd
>   -o syslog_name=postfix/haproxy_smtps
>   -o smtpd_tls_wrappermode=yes
>   -o smtpd_sasl_auth_enable=yes
>   -o 
> smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
>   -o
> smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject

You probably don't need smtpd_client_restrictions since 
smtpd_recipient_restrictions
has identical restrictions, and permit_mynetworks isn't needed (SASL is 
necessary
and sufficient).

>   -o smtpd_upstream_proxy_protocol=haproxy
> ```
> 
> The other standard ports (25, 465 and 587) without proxying are unreachable
> from the outside.
> 
> And finally, `postconf -n` (I fixed the issues indicated in the email chain
> after having read their documentation):
> 
> ```
> alias_database = hash:/etc/aliases
> alias_maps = hash:/etc/aliases
> append_dot_mydomain = no
> biff = no
> broken_sasl_auth_clients = yes
> debug_peer_level = 6
> debug_peer_list = 0.0.0.0/0
> disable_vrfy_command = yes
> inet_interfaces = all
> inet_protocols = ipv4
> mailbox_size_limit = 0
> maillog_file = /dev/stdout
> message_size_limit = 0
> milter_default_action = accept
> milter_protocol = 2
> mydestination = localhost
> myhostname = example.com
> mynetworks_style = subnet
> myorigin = localmail.example.com
> non_smtpd_milters = inet:docker-email-opendkim:12301
> postscreen_upstream_proxy_protocol = haproxy
> proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps
> $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains
> $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps
> $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks
> $smtpd_sender_login_maps
> readme_directory = no
> recipient_delimiter = +
> relay_domains =
> relayhost =
> smtp_tls_cert_file = /shared-keys/mail.example.com/fullchain.pem
> smtp_tls_key_file = /shared-keys/mail.example.com/privkey.pem

The above two parameters should probably be renoved.
Specifying a particular key for outgoing TLS connections
is only important when connecting to specific remote
servers that require your server to use a specific
known key. That doesn't look to be the case here.
Usually, you only need to specify the cert/key files
for the smtpd_ versions of these parameters. See below
for comments on those.

> smtp_tls_loglevel = 1
> smtp_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1

The above parameter isn't needed (and maybe the one
above it too). TLSv1 and TLSv1.1 are better than no
encryption at all. And these settings are for outgoing
connections. So even if your mail server is scanned as
part of a naive cookie-cutter security assessment, the
scanner won't know that you are willing to use those
deprecated protocols for sending mail, and so won't
complain. If you don't exclude TLSv1 and TLSv1.1 in the
similar smtpd_tls_protocols parameter, such a scanner
would complain, even though it's still better than no
encryption. Security scanners usually assume that
policies that should apply to a web server (using
mandatory encryption) should also apply to a mail
server (using opportunistic encryption).

> smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
> smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
> smtpd_client_restrictions = permit_mynetworks, reject
> smtpd_helo_restrictions = reject_invalid_helo_hostname,
> smtpd_milters = inet:docker-email-opendkim:12301
> smtpd_recipient_restrictions = check_sender_access
> hash:/etc/postfix/sender_access, permit_sasl_authenticated,
> permit_mynetworks, reject_unauth_destination, reject_invalid_hostname,
> reject_unknown_recipient_domain, reject_unauth_destination,
> reject_rbl_client sbl.spamhaus.org, reject_rbl_client
> b.barracudacentral.org, reject_rbl_client zen.spamhaus.org,
> reject_rbl_client truncate.gbudb.net, reject_rbl_client bl.spamcop.net,
> reject_rbl_client cbl.abuseat.org, permit

In smtpd_recipient_restrictions, permit_mynetworks usually appears
before permit_sasl_authenticated, but that might not matter.
It has reject_unauth_destination twice.
I could be wrong but I think zen.spamhaus.org subsumes sbl.spamhaus.org
so sbl.spamhaus.org can be removed (but I'm not 100% sure of that).

> smtpd_relay_restrictions = permit_sasl_authenticated permit_mynetworks
> reject_unauth_destination
> smtpd_relay_restrictions = permit_sasl_authenticated permit_mynetworks
> reject_unauth_destination

You have smtpd_relay_restrictions appearing twice.
I'm surprised that that happened with postconf -n.
And permit_mynetworks usually appears before permit_sasl_authenticated.

But note that SASL authentication won't happen over port 25 anyway.
Maybe these references to permit_sasl_authenticated shouldn't appear
in main.cf at all (i.e. only in master.cf when permit_sasl_authenticated
is set to yes).

> smtpd_sasl_auth_enable = yes

The above should be removed. Enabling SASL on port 25
just encourages brute force authentication attempts.
Such attempts will happen on ports 587 and 465 anyway,
but there's no need to encourage them on port 25 as
well.

> smtpd_sasl_authenticated_header = yes
> smtpd_sasl_path = /shared-socks/auth_dovecot
> smtpd_sasl_type = dovecot
> smtpd_sender_login_maps =
> proxy:mysql:/etc/postfix/mysql_sender_login_maps.cf
> smtpd_tls_auth_only = yes
> smtpd_tls_ciphers = high
> smtpd_tls_cert_file = /shared-keys/mail.example.com/fullchain.pem
> smtpd_tls_key_file = /shared-keys/mail.example.com/privkey.pem

It's not super important but it would be better to
replace the above two parameters with
smtpd_tls_chain_files referring to a single file that
contains the contents of privkey.pem followed by the
contents of fullchain.pem. If the contents of these
files change on a regular schedule (such as via
LetsEncrypt), then you'd need to automate the creation
of such a file whenever the two source files change.
The benefit of doing this is that it eliminates the
slight chance of a race condition while the files are
being updated and Postfix might read the old version of
one file and the new version of the other file.

> smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1

See the note above about the smtp_ versions of the above two.

> smtpd_tls_security_level = may
> smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

The above parameter isn't needed anymore (since Postfix 2.11).
It should be removed.

> smtpd_use_tls = yes

The above is obsolete/redundant when smtpd_tls_security_level is set.

> virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf
> virtual_gid_maps = static:5000
> virtual_mailbox_base = /var/vmail/
> virtual_mailbox_domains =
> proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf
> virtual_mailbox_limit = 0
> virtual_mailbox_maps =
> proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
> virtual_minimum_uid = 104
> virtual_transport = lmtp:inet:docker-email-dovecot:10024
> virtual_uid_maps = static:5000
> ```
> 
> I would really appreciate your input on this. Have a great day.
> 
> Cheers,
> Sam

cheers,
raf

Reply via email to