Iptables – ICMP ECHO REPLY is not being SNATed correctly

iptablesmasqueradenetworkingopenvpnubuntu-14.04

I am trying to provide L3 connectivity between two remote LAN networks (10.0.0.0/24, 10.0.1.0/24) using OpenVPN with the following setup:

+----------------+  +---------------------+  +---------------------+
|VM A            |  |VM B (OpenVPN Server)|  |VM C (OpenVPN Client)|
|eth0:10.0.0.5/24|--|eth0:10.0.0.4/24     |  |eth0:10.0.1.4/24     |
+----------------+  |tun0:10.8.0.1/32     |==|tun0:10.8.0.2/32     |
                    +---------------------+  +---------------------+

Providing following IP table rule:

iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 10.0.0.4

Pinging VMC->VMA(10.0.0.5) ICMP echo request's IP is SNATed correctly on VM B:

VM-B# tcpdump -i eth0 icmp
09:27:36.170555 IP 10.0.0.4 > 10.0.0.5: ICMP echo request, id 4049, seq 2, length 64
09:27:36.171201 IP 10.0.0.5 > 10.0.0.4: ICMP echo reply, id 4049, seq 2, length 64

But pinging VMA->VMC(10.0.1.4) echo reply's IP is NOT SNATed on VM B:

VM-B# tcpdump -i eth0 icmp
09:33:31.791095 IP 10.0.0.5 > 10.0.1.4: ICMP echo request, id 6590, seq 2, length 64
09:33:31.795299 IP 10.0.1.4 > 10.0.0.5: ICMP echo reply, id 6590, seq 2, length 64

which in my case results in dropping the packet by other underlying (VM's host machine) anti-spoofing iptables rules to prevent IP spoofing.

I don't understand why is the ICMP echo reply packet not being SNATed properly and how to make it happen. Thank you.

Best Answer

The ICMP echo-reply is the return half of a connection, and they're handled differently, for a reason.

Firstly, if you did manage to do what you want, you'd break PING: VMA would send an ICMP echo-request to 10.0.1.4, but get an ICMP echo-reply (PONG) from 10.0.0.4. It would not associate that PONG with the PING previously sent, so you'd see 100% packet loss (plus gratuitous PONGs).

The way to handle SNAT on returns is to do DNAT on outbounds, and let the NAT tidy-up logic handle with de-NATting the return half traffic. But you can't do that here, because if you DNAT everything coming into VMB's eth0 to 10.0.0.4, you won't be able to talk to VMB any longer.

So the right thing to do is to fix the underlying problem, and make your host's martian-detection logic fit with your actual IP addressing scheme.

Related Topic