1

How can I change the source IP of an incoming packet before it reaches the running service

I have two appliances, a Manager and a Server, connected via VPN and has NAT between them.

Manager Interface IP: A Server Interface IP: B

Manager connects to Server using NAT IP Y and Server sees IP X when manager connects

How do I setup iptables on the Server such a way when packet arrives with source IP X, to alter it to IP.

I know this should be a non issue in a well designed network and product, but we need a workaround for the time being till it is fixed on software side.

So far the below iptables rules have been not helping:

iptables -t nat -A POSTROUTING -s <X> -o eth0 -j SNAT --to <A>

Any help appreciated.

3
  • You saw that probably.
    – Déjà vu
    Aug 28, 2020 at 5:00
  • @e2-e4 yes that's where I got it from Aug 28, 2020 at 14:17
  • I wrote in an earlier comment that it's not possible to SNAT (with conntrack and iptables) incoming packets. Actually this is not possible to do SNAT in prerouting. It 's actually possible to SNAT input packets (ie: packets already routed to the host)
    – A.B
    Sep 1, 2020 at 13:59

1 Answer 1

1

NAT depends on services "asked" by iptables and provided by the conntrack subsystem. SNAT is not made available before the routing decision is made, but is still available once the packet was chosen to be routed to the host: in the rarely used nat/INPUT chain, as documented in the man page:

SNAT

This target is only valid in the nat table, in the POSTROUTING and INPUT chains, and user-defined chains which are only called from those chains. [...]

So as long as the Server is receiving the traffic (not routing it further), when receiving a packet from IP source address <X> on the server's IP destination address <B> through interface eth0, it can be SNATed to appear as source address <A> (which was the original IP source address, but this information is lost) instead, with this:

iptables -t nat -A INPUT -s <X> -d <B> -i eth0 -j SNAT --to <A>

Or using a simpler version:

iptables -t nat -A INPUT -s <X> -j SNAT --to <A>

You could add more restrictions like -p tcp --dport XXXX (XXXX for the actual service reached), and you probably should: if you hit the problem described below, you might prevent yourself from accessing the system through the VPN. Have a backup access method or don't do it remotely unless sure.

The rule above might not be enough, because of routing. If the IP address <A> is not in a known route to the Server (this would happen only if the Server has no default route). While the system will never send a packet back (IP or even ARP) to this destination (replies are un-SNATed), a route to it is still needed for a correct handling by the routing stack which doesn't know SNAT happened.

So if the iptables rule above isn't enough (probably if the Server has no default route), you can add:

  ip route add <A>/32 dev eth0
3
  • The devices sit behind the router that is doing nat. the VPN doesn't terminate on the server itself. Sep 2, 2020 at 15:24
  • Ok, that doesn't change much of the result. If you concur that the server handles iptables and receives traffic. Just replace tun0 or tun+ with just eth0 everywhere it's written. The route command still matters in your server is isolated and has no default route. I'll edit the answer later with those changes
    – A.B
    Sep 2, 2020 at 17:57
  • Just changed (and simplified) the answer: it's the same method.
    – A.B
    Sep 2, 2020 at 21:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .