Change incoming packet source IP

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