Friday, November 22, 2019

How to Proxy SSL IMAP/POP3/SMTP using HAProxy and Dovecot+Postfix

This post shows how to configure a mail proxy server to connect clients in an intranet to an external mail server. I will use SSL offloading method since the mail proxy server is owned by the same company that's running the main mail server therefore decrypting the data on the proxy server and encrypting them again is not a security concern.

HAProxy - Dovecot configuration

I use HAProxy on the VPS Proxy server to proxy SSL IMAP/POP3/SMTP protocols to the main mail server. The main server is using Dovecot/Postfix to run email service.

First, install HAProxy on the VPS proxy server, generate a valid SSL for its hostname and configure haproxy to proxy IMAP/POP3/SMTP SSL ports to the main mail server :

listen main-pop3
  bind :995 ssl crt /etc/letsencrypt/live/HOSTNAME/fullchainkey.pem no-sslv3
  mode tcp
  balance first
  stick store-request src
  stick-table type ip size 200k expire 15m
  server s1 MAINHOST.FQDN:10110 send-proxy-v2 ssl verify required ca-file ca-certificates.crt

listen main-imap
  bind :993 ssl crt /etc/letsencrypt/live/HOSTNAME/fullchainkey.pem no-sslv3
  mode tcp
  balance first
  stick store-request src
  stick-table type ip size 200k expire 15m
  server s1 MAINHOST.FQDN:10143 send-proxy-v2 ssl verify required ca-file ca-certificates.crt

listen main-smtp
  bind :465 ssl crt /etc/letsencrypt/live/HOSTNAME/fullchainkey.pem no-sslv3
  mode tcp
  stick store-request src
  stick-table type ip size 200k expire 15m
  server s1 MAINHOST.FQDN:10465 send-proxy-v2 ssl verify required ca-file ca-certificates.crt

/etc/letsencrypt/live/HOSTNAME/fullchainkey.pem is a valid certificate generated for the VPS Proxy hostname and it should contain both private key and certificate.

MAINHOST.FQDN is the full hostname of the main mail server, and haproxy is connecting to it securely (send-proxy-v2 ssl) and verifying its SSL against ca-certificates.crt file.

Now, on the main mail server side, we need to configure dovecot to listed on the custom ports for haproxy (10110, 10143, 10465) . Dovecot added support for haproxy since version 2.2.19. We open separate ports for haproxy and enable haproxy in the listeners which will allow dovecot to get the correct data of clients from haproxy server. Add the following code to /etc/dovecot/conf.d/haproxy.conf on the main mail server:

haproxy_trusted_networks = VPS.PROXY.IP/32
service pop3-login {
   inet_listener pop3_haproxy {
     port = 10110
     haproxy = yes
     ssl = yes
   }
}
service imap-login {
  inet_listener imap_haproxy {
    port = 10143
    haproxy = yes
    ssl = yes
  }
}
service submission-login {
  inet_listener submission {
    port = 10465
    haproxy = yes
    ssl = yes
  }
}
submission_relay_host = localhost
submission_relay_port = 25
submission_relay_trusted = yes
submission_client_workarounds = whitespace-before-path

Note that we are not sending queries from haproxy directly to postfix, instead we use submission listener of dovecot to authenticate clients in a similar way as imap/pop3 protocols. To enable submission service, you need to add submission in the list of protocols in dovecot.conf file : 

protocols = imap pop3 submission

Dovecot receives emails on port 10465 from haproxy, authenticate clients using its configured settings, and then send them to submission_relay_host which is postfix in this case. Postfix is running on the same machine as dovecot on port 25. We need to configure postfix to accept XCLIENT data that dovecot sends to it. (Xclient contains data of client that haproxy sends to dovecot). We set dovecot to send the real data of client to postfix by setting submission_relay_trusted = yes in its config file. We also need to set postfix to accept this data from dovecot by adding the following line to /etc/postfix/main.cf file : 

smtpd_authorized_xclient_hosts = 127.0.0.1

Now, clients in a restricted network can connect securely to the VPS proxy server. This Proxy server receives data from clients and sends them securely to the main mail server.

The line submission_client_workarounds = whitespace-before-path is required in configuration of dovecot submission for Microsoft outlook to work properly. I was getting the following error in Microsoft outlook 2016 before setting this variable :

Sending reported error (0x800CCC78): Cannot send the message. Verify the e-mail address in your account properties. The server responded: 501 5.5.4 Invalid FROM: Unexpected whitespace before path

Thursday, November 21, 2019

Postfix smtp_fallback_relay and HAProxy smtp relay in action

It's possible to use HAProxy to add a SMTP relay for a domain mail service which can be used to add a secondary mx record for a domain name to enable its clients in a restricted network reach the mail server :
Clients in a restricted network -> HA Proxy VPS (second priority mx record) -> Main server
HAProxy - Postfix configuration

You'll need to get a VPS with internet access in the restricted network and install HAProxy on it. Then configure HAProxy on the vps to forward SMTP port 25 to the main server : 

frontend ft_smtp
  bind 0.0.0.0:25
  mode tcp
  timeout client 1m
  log global
  option tcplog
  default_backend bk_postfix

backend bk_postfix
  mode tcp
  log global
  option tcplog
  timeout server 1m
  timeout connect 5s
  server postfix YOUR_MAIN_IP_ADDRESS:2525 send-proxy

Now on the postfix of the main server edit the main.cf and set the upstream proxy for postscreen to haproxy: 

postscreen_upstream_proxy_protocol = haproxy

and finally enable smtpd and postscreen in master.cf :

2525    inet  n       -       n       -       1       postscreen
smtpd     pass  -       -       n       -       -       smtpd


One can add a new mx record with a lower priority to the domain with the IP address of the HAProxy server so that clients that aren't able to reach the main mail server can access it through the HAProxy server.

But how can these clients receive emails from the main mail server? Postfix on the main server can't reach these clients directly, so one can use smtp_fallback_relay feature in postfix to reach them through the same VPS that's running HAProxy.

To do so add the IP address of the vps that's running HAProxy as a SMTP Fallback relay to the main.cf file of the main mail server : 

fallback_relay = [YOUR_VPS_FQDN]:5870

You'll need to also add the IP address of your VPS to the SPF records of the main domain.

Now on the vps server, install postfix and set it to run as a relay. Add the IP address of the main mail server to mynetworks in main.cf file of the vps, to allow it to use this vps as a relay mail server. 

 Ensure that the hostname of the vps matches with the PTR record of YOUR_VPS_IP_ADDRESS and the value in /etc/mailname of the vps.

Edit the master.cf file of the postfix on the vps server and add the port you set in fallback_relay there : 

5870    inet  n       -       y       -       -       smtpd

That's it. With this configuration, clients first try to reach the main mx records and they try the second mx record if the first one was inaccessible. Also the server tries to reach mail servers directly and it tries the relay smtp server if they were unreachable. 


How to disable Debian 12 sleep on production servers

 Debian 12 has power saver enabled by default which causes your server to go to sleep if there is no mouse / keyboard interaction. To resolv...