Using the PREROUTING
rule without the MASQUERADE
rule will do what you were asking for. It still won't work, but that is for a different reason.
If you have a client on 192.0.2.1
which send a SYN packet to your server on 198.51.100.2
, then your first rule can change the destination address of that packet to your other server on 203.0.113.3
and forward it as such.
The first problem you could run into with this approach would be that the connection between 198.51.100.2
and 203.0.113.3
might have source IP filtering. This would cause the packet to be dropped because the source address would still be 192.0.2.1
but the router expected 198.51.100.2
. If this is the case in your particular network, it can be worked around by using a tunnel.
However you will run into another problem. Once the packet arrives at 203.0.113.3
a SYN-ACK will be send back to 192.0.2.1
. This will be routed directly to the client without going through the first machine which had applied the DNAT
rule.
The client which send a SYN from 192.0.2.1
to 198.51.100.2
will see a SYN-ACK from 203.0.113.3
to 192.0.2.1
. This will not match any TCP connection on the client, and the client will reply with a RST packet. Once the RST packet reaches 203.0.113.3
the TCP connection is closed on the server side.
In total four packets got transmitted, and the connection got closed on the server side before getting fully established. Those four packets will repeat as many times as the client retransmits the SYN until it times out.
There is a few ways to get around this problem:
- Route all traffic from
203.0.113.3
through 198.51.100.2
to ensure that it gets translated on the way back. Unfortunately this will make the public IP 203.0.113.3
useless for any other purposes.
- Assign a secondary IP to
203.0.113.3
, you could for example give it 10.0.113.3
as the secondary IP address. On 198.51.100.2
you DNAT
to 10.0.113.3
and use a tunnel to 203.0.113.3
in order to get the packets to the proper destination host. On 203.0.113.3
you use a routing policy to ensure that packets with source IP 10.0.113.3
gets routed back through the tunnel, and other packets get routed over your default gateway.
- Stop using NAT and instead use a DSR load balancing approach to send packets from
198.51.100.2
to 203.0.113.3
. If those two are not directly connected with no router between them, this will again require a tunnel. But this time packets inside the tunnel preserve the original destination address, and 203.0.113.3
will not need a routing policy, instead it will send correct replies directly to the client. The drawback of this is that 203.0.113.3
will need to be assigned 198.51.100.2
as a secondary IP, and thus 198.51.100.2
and 203.0.113.3
will not be able to communicate with each other, but they will still communicate just fine with everybody else.
- If you only need to support HTTP, you can use a proxy instead of NAT. Then you can use
X-Forwarded-For
to let 203.0.113.3
know the original client IP. The web server on 203.0.113.3
will then need to trust X-Forwarded-For
on any connections originating from 198.51.100.2
and ignore it on connections from other client IPs.