If you’re self-hosting Mail-in-a-Box (MIAB) in a Proxmox LXC container like I am, and suddenly your server can’t send emails to any provider (ProtonMail, Gmail, Outlook—all timing out with “Connection timed out” in postfix logs), this post is for you. It took some tcpdump detective work, but we nailed it. Spoiler: it was a sneaky private IP NAT block on outbound port 25.

The Problem: No Outbound Mail, Clean Timeouts#

My postfix/smtp logs looked like this:

Mar  8 12:01:51 mail postfix/smtp[28689]: connect to mail.protonmail.ch[176.119.200.128]:25: Connection timed out
Mar  8 12:02:51 mail postfix/smtp[28689]: connect to mail.protonmail.ch[185.70.42.128]:25: Connection timed out

Provider swore port 25 wasn’t blocked. Server patched, rebooted. Local firewall clear (iptables -L OUTPUT -n -v | grep 25 empty). Even telnet mail.protonmail.ch 25 timed out. Inbound mail worked fine. Queued emails piling up.

Time for tcpdump to see if SYNs were even leaving.

Step 1: tcpdump Outbound SMTP Only#

Capture outgoing port 25:

tcpdump -i any -n -Q out port 25 -w /root/smtp_capture.pcap

(Flush queue in another terminal: postqueue -f. Wait 90s. Ctrl+C.)

Read it back:

tcpdump -r /root/smtp_capture.pcap -n -v

The Smoking Gun: Private Source IP + Silent Drops#

Key lines:

12:18:15.681899 eth0  Out IP ... 192.168.100.94.35641 > 185.70.42.128.25: Flags [S]  # SYN out

Every SYN sourced from private 192.168.100.94 (my LXC’s eth1 IP). No SYN-ACKs, no RSTs—just silence.

But inbound worked from public 6.x.x.x:

6.x.x.x.25 > 158.94.208.215.50114: Flags [S.]  # Server greeting

Diagnosis: Provider NAT drops outbound port 25 from private IPs. Common anti-spam measure. Packets hit the gateway, get silently dropped. Support often doesn’t know/admit it upfront.

Quick Fix: Disable Private eth1 in Proxmox#

Proxmox UI → my LXC → Hardware → Network Device (eth1) → Remove or Edit → Disable.

Reboot container. Boom—mails delivered instantly. tcpdump now shows SYNs from 6.x.x.x. Direct public routing bypassed NAT.

Why Did It Work Fine for 6 Months, Then Break?#

DHCP on eth1 (192.168.100.170) installed competing routes:

default via 6.x.x.x dev eth0 proto static 
default via 192.168.100.1 dev eth1 proto dhcp src 192.168.100.170 metric 1024 
1.1.1.1 via 192.168.100.1 dev eth1 ...  # Host routes override defaults!
8.8.8.8 via 192.168.100.1 dev eth1 ...

ip route get 8.8.8.8 → eth1 (bad). ip route get 185.70.42.128 → eth0 (lucky).

DHCP renewals, reboots, or bring-up order changed—suddenly more traffic (including some MXes) hit eth1/NAT/drop.

After disabling eth1:

default via 6.x.x.x dev eth0 proto static 
6.x.x.x/29 dev eth0 ...
192.168.100.0/24 dev eth1 ...  # But eth1 down now
ip route get 8.8.8.8 → dev eth0 src 6.x.x.x  # Perfect

Future: Keep eth1 for Inter-VM, Force Outbound via eth0 (MIAB-Safe)#

I want eth1 up for private VM communication. Solution: static eth1, no gateway in Proxmox LXC config.

On the Proxmox host:

nano /etc/pve/lxc/<CTID>.conf

Change:

net1: name=eth1,bridge=vmbr1,ip=dhcp  # OLD - installs bad routes

To:

net1: name=eth1,bridge=vmbr1,ip=192.168.100.170/24  # NEW - no gw!

pct restart <CTID>. Now eth1 routes only 192.168.100.0/24 locally. All internet → eth0.

MIAB bonus: No Postfix changes needed (they’d get overwritten anyway). Routing fixes everything.

Quick Checks for “Is My Routing Still Good?”#

ip route | grep '`default'  # Only one, via eth0?
ip route get 8.8.8.8       # dev eth0 src public IP?
ip route get 185.70.42.128 # Same?