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