0

I'm trying to figure it out how to reverse proxy based on condition email servers or how to deal with sending/receiving emails from different servers on only 1 public IP address?

My current configuration is as below:

enter image description here

I have successfully managed to proxy web servers (OpenLiteSpeed) based on condition with OPNsense + HAproxy e.g. domain1.com -> Web Server1; domain2.com -> Web Server2; etc.

A records of every domain is pointed at my public IP address and web traffic is handled by OPNsense and HAproxy to specific local server based on conditions.

The problem is that i can't make it work to do the same thing with Postfix/Dovecot. So every mail server e.g. mail.domain1.com, mail.domain2.com etc. A record and MX record is also pointed at my public IP address but handled internally by separated server.

I know i can port forward, 25,465,993 etc. from my dedicated server to specific mail server but that works only at specific server and others will be unable to handle mails.

Any idea how to solve this?

I just read about that but not sure if it can work as it should ->

global
    # ... (unchanged)

defaults # ... (unchanged)

frontend email_frontend bind :993 ssl crt /path/to/ssl_certificate.pem # IMAPS bind :995 ssl crt /path/to/ssl_certificate.pem # POP3S bind *:25 ssl crt /path/to/ssl_certificate.pem # SMTP mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 }

acl is_domain1 req_ssl_sni -i domain1.com
acl is_domain2 req_ssl_sni -i domain2.com

use_backend backend_domain1 if is_domain1
use_backend backend_domain2 if is_domain2

backend backend_domain1 mode tcp server mail_server_domain1 172.16.0.2:993 check # IMAPS server mail_server_domain1 172.16.0.2:995 check # POP3S server mail_server_domain1 172.16.0.2:25 check # SMTP

backend backend_domain2 mode tcp server mail_server_domain2 172.16.0.3:993 check # IMAPS server mail_server_domain2 172.16.0.3:995 check # POP3S server mail_server_domain2 172.16.0.3:25 check # SMTP

EAK TEAM
  • 103

3 Answers3

3

TL;DR: You can use HAproxy in front of SMTP servers that are MX hosts only to do load balancing. You can not use it to select which server to route a request to based on some domain name. All the backends should be similar, in particular, all of them must introduce themselves with the same server name in the initial greeting. This is all due to the nature of SMTP protocol and various expectations of the SMTP server behaviour the world is converged on.

Caution: Having multiple distinct mail servers (that introduce themselves differently) behind single public IP is a very bad idea. For example what will happen: you'll get that IP blacklisted.

Overall, if I understand your intention correctly, it is impossible to achieve what you want.


You have three ways to have a load balanced setup for various email-related services:

  1. For RAW TLS ports (465, 993, 995): strip TLS/SSL on HAproxy, but then you need to use their unencrypted counterparts for backends: a SMTP submission backend will go to 587 (instead of 465, where HAproxy front-end should be listening), an IMAP to 143 (instead of 993) and POP3 to 110 (instead of 995). Then you need a certificate and a key on the HAproxy machine.
  2. For RAW TLS ports: don't strip TLS, but parse unencrypted TLS headers and act accordingly (as you do with acl ... req_ssl_sni ...). In that case, your backend will need to have a certificate configured, and HAproxy doesn't need it.
  3. For any port: don't strip and don't parse TLS, and let HAproxy just handle TCP streams; all the TLS/SSL handling will be done on back-end servers. In this case, you should not set up any certificates on HAproxy, but set them up on the real back-end servers.

Port 25 is not a RAW TLS port; the set-up as in options 1 or 2 above are not available (at least, that easy). SSL/TLS here is only supported in so called STARTTLS mode. Instead of ClientHello, the conversation starts as usual SMTP, e.g. first server sends a greeting, and then client sends EHLO, and if server indicates the support for STARTTLS, the client may (or may not) issue the STARTTLS command and only then ClientHello appears. Totally the same works 587. Ports 110 and 143 work in a very similar manner: client waits for server indication for STARTTLS and then issues the STARTTLS command, the only difference is that conversation starts as usual POP3 and IMAP, respectively.

Unfortunately, this is not the scheme HAproxy expects. You can not expect it to follow the SMTP conversation, find the TLS within it, and extract the SNI on the port 25, as you have it in configuration. The other three client-related ports you can not expose at all, using their raw TLS counterparts (for which options 1 or 2 are available); but, for the port 25 this is impossible and you have to process SSL for it in-band, using STARTTLS, on the real mail servers. There is no RAW counterpart for that service, for compatibility reasons. The only option available for it is option 3 from above: don't do any TLS-related processing on the HAproxy at all.

This also implies you can't have "purely name-based SMTP virtual hosts on the single IP" as you do with HTTPS through SNI.


A side note: I wrote about ports 465 and 587, but I don't see them in your configuration. It seems you don't use a dedicated submission/smtpd service for client e-mail submissions and I suspect you are doing authenticated submissions on port 25. This is not a good and secure setup and it's way harder to get managed correctly. Make your life easier: remove any authentication support on port 25; it's only for reception of mail from other mail servers. Enable submission or/and smtps services in master.cf and only support authentication for these, and update client configurations in a similar way to only use submission service for submitting mail.

Another side note: are you really using POP3? Why? Anything you can do using POP3 you can do through IMAP. Just don't set it up, as if it never existed :)

2

The multiplexing is handled by the application protocol. Haproxy knows HTTP so it can deal with the HTTP traffic. OTOH it doesn't speak SMTP. While you could route the traffic based on Postfix transport maps, Postfix has explicit functionality to act a relay at the receiving end. But this would require some DNS gymnastics to provision a split zone reporting the internal address as the MX. I'd be using a Postfix recipient map, something like:

recipient_canonical_maps = hash:/etc/postfix/mydomains

Where the latter contains....

@domain1.com @vm1.internalzone
@domain2.com @vm3.internalzone
...

NB some caution - you need additional config to prevent this becoming an open relay (relay_domains should work). Make sure you test the config.

But I can't help feeling that this is essentially a bad architecture - tying the the domains to specific instances. I would be more tempted to consolidate by function. And based on the information provided, the opensense VM is adding no value to the service.

symcbean
  • 23,767
  • 2
  • 38
  • 58
1

With postfix you don't need to reverse proxy, postfix can handle multiple domains

In your postfix main.cf you create

transport_maps = hash:/etc/postfix/transport

And also specify for which domains this server will be accepting mail

mydestination = example.com example2.com example3.net

And in the transport file you specify the mail server responsible for each domain

example.com    smtp:[mailserver1.example.com]
example2.com   smtp:[mailserver2.example.com]

Then run postmap /etc/postfix/transportand restart or reload postfix

Turdie
  • 2,945