haproxy in HTTP mode can add the necessary X-Forwarded-For header and backends
like Apache can use the mod_remoteip.so module with the RemoteIPHeader
parameter to handle the new header.
haproxy in TCP mode can't do that[1], thus haproxy has written a "proxy
protocol v2"[2] that does that, but requires a custom implementation for the
backend[3].
I believe postfix supports this since 2.10 ! (but I've never used it)
postscreen_upstream_proxy_protocol = haproxy
[1]
https://www.haproxy.com/documentation/hapee/latest/load-balancing/client-ip-preservation/enable-proxy-protocol/
[2]
https://www.haproxy.com/blog/using-haproxy-with-the-proxy-protocol-to-better-secure-your-database/
[3]
https://www.haproxy.com/blog/efficient-smtp-relay-infrastructure-with-postfix-and-load-balancers/
On Wed, 21 Dec 2022 12:39:30 +0400 Samer Afach <[email protected]> wrote:
> Thank you. You and Pat actually may be onto something. I grepped the whole
> logs for "connect from", and all the "connect from" and "disconnect from"
> statements seem to be coming from 172.30.0.1, which, if I understand
> correctly, is the NAT bridge address of docker, i.e., the subnet router
> address.
>
>
> What is the correct solution in this case, based on my configuration? Please
> advise. I understand I have to make "mynetworks" just localhost, but specific
> recommendation based on my configuration would be highly appreciated.
>
>
> Best regards,
>
> Sam
>
>
>
> On 21/12/2022 11:51 AM, [email protected] wrote:
>
> > The most common issue when using a proxy/load balancer like haproxy, is
> > that the remote/foreign connections are being forwarded with the IP address
> > of the haproxy machine. Thus, they all appear as "local", which makes
> > postfix think they are "mynetworks" and as a result, postfix becomes a open
> > relay.
> >
> > So check your logs, to make sure remote/foreign connections don't appear as
> > 172.30.0.0/16 in postfix. If they do, then that is the problem.
> >
> >
> >
> > On Wed, 21 Dec 2022 11:35:13 +0400 Samer Afach <[email protected]> wrote:
> >
> > Dear Pat:
> >>
> >> Thank you for throwing this idea, because I really thought it wasn't
> >> possible to retrieve docker logs without setup, but I dug and found the
> >> logs. I have them all. Unfortunately, I can't share them all because
> >> they're like GBs in size. Just the grep on that email address is like
> >> 750 MB in size.
> >>
> >> I cut a snippet of the relevant part (where I see the spam address), and
> >> put it in pastebin. I hope that's allowed in the rules of the list.
> >>
> >> https://pastebin.com/PEir7mDc
> >>
> >> (all from postfix, nothing from dovecot, btw).
> >>
> >> I minimally redacted the logs:
> >>
> >> - The domains example.com and example.org belong to me, seems like both
> >> were involved in this attack.
> >> - My public IP address was replaced with 123.456.789.123
> >>
> >> Please note that 172.30.0.0/16 is the docker-compose subnet for all
> >> dockerized email applications. It was created automatically by
> >> docker-compose.
> >>
> >> If you need any additional information or additional logs, please let me
> >> know.
> >>
> >> Best regards,
> >> Sam
> >>
> >>
> >> On 21/12/2022 10:31 AM, Patrick Proniewski wrote:
> >> Hello,
> >>>
> >>> Do you have the logs (postfix and maybe dovecot) showing the spammer
> >>> interaction with the server?
> >>>
> >>> pat
> >>>
> >>> On 21 Dec 2022, at 05:45, Samer Afach <[email protected]> wrote:
> >>>>
> >>>> Thank you, Phil. Here we go. Here's postconf -n:
> >>>>
> >>>>
> >>>> I hope this helps in better identifying how the spammer was able to use
> >>>> my server to send a spam email.
> >>>>
> >>>>
> >>>> ```
> >>>>
> >>>> 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 = hostname.hosting-service.com,
> >>>> localhost.hosting-service.com, localhost
> >>>> myhostname = localhost
> >>>> mynetworks_style = subnet
> >>>> myorigin = localhost
> >>>> non_smtpd_milters = inet:docker-email-opendkim:12301
> >>>> 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/example.com/fullchain.pem
> >>>> smtp_tls_key_file = /shared-keys/example.com/privkey.pem
> >>>> smtp_tls_loglevel = 1
> >>>> smtp_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> >>>> smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> >>>> smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
> >>>> smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
> >>>> smtpd_client_restrictions = permit_mynetworks
> >>>> 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,
> >>>> smtpd_relay_restrictions = permit_sasl_authenticated permit_mynetworks
> >>>> reject_unauth_destination
> >>>> smtpd_sasl_auth_enable = yes
> >>>> 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_cert_file = /shared-keys/example.com/fullchain.pem
> >>>> smtpd_tls_ciphers = high
> >>>> smtpd_tls_key_file = /shared-keys/example.com/privkey.pem
> >>>> smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> >>>> smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
> >>>> smtpd_tls_security_level = may
> >>>> smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
> >>>> smtpd_use_tls = yes
> >>>> 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
> >>>>
> >>>> ```
> >>>>
> >>>>
> >>>> Best regards,
> >>>>
> >>>> Sam
> >>>>
> >>>>
> >>>> On 21/12/2022 8:35 AM, Phil Stracchino wrote:
> >>>> On 12/20/22 21:39, Samer Afach wrote:
> >>>>> I could share postconf too, but it's huge and I don't want to make this
> >>>>>> a huge burden unless necessary.
> >>>>>> 'postconf -n' is much more concise. Try it.
> >>>>>
> >>>>>
> >>>>>