Skip to content

RTFM · Networking

HAProxy for MailDragon

Use HAProxy as a deliberate TCP edge for MailDragon when the mail server lives on a private server network or when one public edge host serves several backends. Keep SMTP and IMAP protocol ownership clear.

Saphira Linux dragon mascot

What HAProxy does for mail—and what it does not

HAProxy accepts a TCP connection on the public edge and opens a TCP connection to the MailDragon backend. It can make the backend private, concentrate public firewall rules on one edge host, and health-check the TCP path. It does not create MX records, sign DKIM, set PTR, or turn a blocked ISP port 25 into an available one.

Mail TCP edge
Internet SMTP peer
    │ TCP 25
    ▼
203.0.113.10 HAProxy edge
    │ TCP 25 over the server network
    ▼
192.0.2.25 MailDragon / Postfix

Internet mail client
    │ TCP 465, 587, or 993 as intentionally offered
    ▼
HAProxy edge
    ▼
MailDragon / Postfix or Dovecot

A proxy cannot compensate for an unsuitable sending address. Decide which public IP MailDragon uses for outbound SMTP and verify PTR and FCrDNS for that address before treating inbound proxying as a mail-deliverability solution.

Choose the smallest listener set

Mail services to expose
PortPurposePublish when
25/TCPServer-to-server SMTPYou accept Internet mail and the provider/ISP permits it.
465/TCPSubmission with implicit TLSYou deliberately support this client submission method.
587/TCPAuthenticated message submission, normally STARTTLSMail clients need submission.
993/TCPIMAP with implicit TLSUsers need IMAP mailbox access.
143, 110, 995/TCPOptional IMAP/POP variantsOnly when MailDragon is configured to provide the specific protocol.

Do not copy every port into HAProxy merely because mail software can support it. Confirm MailDragon's Postfix and Dovecot listeners first, then publish the smallest useful subset. An internal health check can prove TCP reachability but does not replace protocol-specific authentication and TLS tests.

A complete TCP pass-through configuration

This example leaves TLS with MailDragon. That is usually the clearest choice for SMTP and IMAP: HAProxy is a TCP transport edge, while Postfix and Dovecot present their own certificates and negotiate their own TLS. Replace the private backend address only after proving it is reachable from the proxy host.

MailDragon TCP pass-through
# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0

defaults
    mode tcp
    log global
    option tcplog
    timeout connect 5s
    timeout client  5m
    timeout server  5m

frontend smtp_in
    bind :25
    default_backend mail_smtp

backend mail_smtp
    server maildragon 192.0.2.25:25 check

frontend submission_implicit_tls
    bind :465
    default_backend mail_submission_implicit_tls

backend mail_submission_implicit_tls
    server maildragon 192.0.2.25:465 check

frontend submission_starttls
    bind :587
    default_backend mail_submission_starttls

backend mail_submission_starttls
    server maildragon 192.0.2.25:587 check

frontend imaps
    bind :993
    default_backend mail_imaps

backend mail_imaps
    server maildragon 192.0.2.25:993 check

HAProxy's native command accepts -f for a configuration file and -c for a configuration check. Always use the check before reload. On a normal Saphira OpenRC host, the package provides /etc/haproxy/haproxy.cfg and the haproxy service; on a selected systemd installation, first prove the matching unit exists before using systemctl.

Validate and operate the proxy
haproxy -c -f /etc/haproxy/haproxy.cfg

# OpenRC
rc-service haproxy restart
rc-service haproxy status
rc-update add haproxy default

# systemd only where the unit is installed
systemctl status haproxy.service
systemctl restart haproxy.service

Firewall, DNS, and proof

The public firewall belongs on the HAProxy edge. The backend firewall should accept the selected mail ports only from the HAProxy server network, not from every client network. Public MX records point to the public mail hostname; that hostname resolves to the public edge address. The backend's private address never appears in public MX, A, AAAA, or PTR records.

Evidence from edge, backend, and Internet
# Edge: expected public listeners.
ss -lntp '( sport = :25 or sport = :465 or sport = :587 or sport = :993 )'

# Backend: expected private listeners.
ss -lntp '( sport = :25 or sport = :465 or sport = :587 or sport = :993 )'

# From an independent network.
dig +short MX example.test
dig +short A mail.example.test
openssl s_client -connect mail.example.test:465 -servername mail.example.test
openssl s_client -starttls smtp -connect mail.example.test:587 -servername mail.example.test
  • Connection refused at the edge: HAProxy is not listening, its firewall denies the port, or the router/provider has not delivered the connection.
  • HAProxy accepts but cannot connect: test 192.0.2.25 from the edge, then check backend routing and firewall policy.
  • TLS certificate name is wrong: TLS terminates at MailDragon in this design, so inspect the MailDragon certificate—not an HAProxy HTTP certificate setting.
  • Mail is accepted but remote delivery is poor: test the actual outbound public sender with the reverse-DNS chapter; inbound HAProxy success is a different path.