Preserve the Correct Source IP When Forwarding Mailcow TCP Traffic

When Mailcow runs on a separate machine, forwarding its TCP traffic through HAProxy can leave the logs showing the forwarding layer instead of the connecting client. That defeats the point of checking the mail logs when the original source IP matters.

The service still receives traffic, so the forwarding path can look healthy at first. The problem becomes visible when investigating delivery, abuse, rate limits, or client behaviour and every connection appears to originate from the proxy instead of the real sender.

Why a TCP proxy changes the picture

HAProxy is often the right choice when it is acting as a proxy and the backend is designed to receive client information through the proxy arrangement. But a TCP proxy terminates and creates connections in a way that can make the backend see the proxy’s address.

For this Mailcow path, preserving the original client address in the service logs mattered more than the features HAProxy was providing. The proxy was doing its forwarding job, but it was not giving Mailcow the source-IP behaviour this topology needed.

Use port forwarding for this path

Replacing HAProxy TCP forwarding with iptables port forwarding gave Mailcow the expected source-IP behaviour. The change keeps the forwarding layer from becoming the address recorded by the mail service for this traffic.

This is intentionally a topology-specific solution. Do not replace a proxy globally just because one mail path needs different source-address handling. HAProxy may still be the appropriate component for HTTP traffic, TLS termination, health checks, or other services that rely on it.

Validate the result with a real connection

After changing the forwarding method, test the exact service and port that clients use. Then inspect the Mailcow logs rather than assuming the rule behaves as intended:

  • Connect or send a test message through the forwarded path.
  • Find the relevant connection in the mail logs.
  • Confirm that the recorded address is the actual client or expected upstream address, not the forwarding host.
  • Repeat from a second source if possible.

Testing from more than one address is worthwhile. It catches cases where a rule works for one network but not another, and it gives you a before-and-after record for later troubleshooting.

Keep the change narrow

Document which ports are forwarded and why. Firewall and NAT rules tend to outlive the incident that introduced them, and an undocumented port forward becomes difficult to audit later.

The practical conclusion is simple: if Mailcow needs to log the real source address and HAProxy TCP forwarding causes it to see the proxy instead, use iptables port forwarding for that specific mail path and verify it from the logs.