Possible? HAProxy IMAPS / SMTPS only under a virtual domain

Started by 25564rbr, July 20, 2025, 01:59:02 PM

Previous topic - Next topic
Hello everyone,
I've read some posts concerning this but I'm not sure if I understood correctly.
My plan is to create a subdomain (e.g. mail.somedomain.com) wich get's a let's encrypt cert trough cloudflare dns (this works). And only on this domain I'd like to be ports 993/465 (IMAPS/SMTPS) reachable. Those should be forwarded trough HAproxy to an internal server.
The internal server (mailcow) has a self signed ceritifcate.

I've created the real server, backend pool, virtual server and some extra rules & conditions i've read about online.

Configuration:
# Frontend: 0_MAILCOW_frontend_imaps
frontend 0_MAILCOW_frontend_imaps
    bind 0.0.0.0:993 name 0.0.0.0:993 ssl no-tls-tickets ssl-min-ver TLSv1.2 ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/XX.certlist
    mode tcp

    # logging options
    # ACL: traffic_ssl
    acl acl_687b7007ab7f94.09967451 req_ssl_hello_type 1
    # ACL: mail_Subdomain_Check
    acl acl_6877ab1b8aa420.23960963 req.ssl_sni -i mail.somedomain.com

    # ACTION: request_inspect_delay
    # NOTE: actions with no ACLs/conditions will always match
    tcp-request inspect-delay 5s
    # ACTION: request_content_accept_ssl
    tcp-request content accept if acl_687b7007ab7f94.09967451
    # ACTION: mailserver_sni
    use_backend MAILCOW_backend_imaps if acl_6877ab1b8aa420.23960963


    # Backend: MAILCOW_backend_imaps ()
backend MAILCOW_backend_imaps
    # health checking is DISABLED
    mode tcp
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m 
    stick on src
    server MAILCOW_server_IMAPS INTERNAL_IP:993 ssl alpn h2,http/1.1 verify none send-proxy-v2 check-send-proxy

I'm getting a connect with openssl s_client -connect, but on ALL Subdomains / IPs and no IMAP "Hello". Can't see any informational messages in HAproxys logfile (?).

Thank you very much.

Essentially: no, this is not possible, see this discussion for a prominent example: https://github.com/haproxy/haproxy/issues/1659

That is because of HAproxy being unable to handle STARTTLS within applications. What happens is these applications start a TLS session based on a command that exists within their application protocol. For this to work, HAproxy would need to simulate every needed application protocol up to the point where the TLS session actually starts, then hand over the session to the backend, while it also needs to repplay the first steps of the initial conversation (like "EHLO" for SMTP) to the backend server.

The latter could not even work, because for example, with SMTP, there might be DNSBL in place, which needs to know what IP the client uses. With a reverse proxy, it is the HAproxy instance's IP and there seems to be no way to forward the client's IP. For HTTPS, there are methods on how to do that (like specific HTTP headers), that is why this works with HTTPS, but not other STARTTLS-capable protocols.

The best thing you can do is to have HAproxy speak TLS and use the unencrypted version of SMTP, POP (110) or IMAP (143) or even the "pure" TLS versions like POP3S (995), IMAPS (993), but not the STARTTLS "optional" TLS variants. The difference is that the "pure" variants expect a TLS session from the get-go. The same thing goes for SUBMISSION (587 is STARTTLS, 465 is TLS-only). That in turn does rule out a name-based mapping to different backends, though.

That all works with HTTPS, because the first thing that is transmitted is the unencrypted "Host" header, which decides which certificate is presented.

Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+

Hi,
thank you very much for the swift reply!
The biggest point was the dedicated subdomain for me, but as far as I understand this is not possible so I will try to do it with port forwarding instead.

As I said, you can have do HAproxy the TLS part and the certificate prolongation for you, but not much else.
Intel N100, 4* I226-V, 2* 82559, 16 GByte, 500 GByte NVME, ZTE F6005

1100 down / 800 up, Bufferbloat A+