Redirect all incoming traffic from a secondary public IP to an internal IP address using iptables
I'm currently trying to figure out how I can forward traffic from a secondary public IP address of my dedicated server to an internal IP of my network using iptables in order to make e.g. webservers and the like visible from outside.
My setup is a dedicated server containing three virtual machines which form a "private LAN". The connection between those is established and the virtual machines can connect to the internet through a bridge between the isolated LAN and the physical server. Allowing outgoing traffic is established using the following rule (LAN: 192.168.x.x, Example Public Address: 8.8.8.8):
iptables -t nat -A POSTROUTING -s 192.168.1.101 -j SNAT --to-source 8.8.8.8
This works fine - if I open an internet browser and go to whatismyip.com it will now no longer show the server's main IP address, but instead it will show the secondary IP just the way it's supposed to do.
However, now I'd love to do the other way around and install e.g. a web server on one of the virtual machines and make it available to the public through my secondary IP. I was searching for the answer and found I'm supposed to add a PREROUTING rule in order to accomplish this, thus I tried the following:
iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.1.101
Connecting to port 80 of the public IP will time out, though. It seems like I'm still missing something or there's a mistake in the way I do the rules.
Please note: Rather than opening only a specific port, I'd like to forward all incoming traffic on that specific IP to the virtual machine and handle security over there.
Any advice would be appreciated - perhaps I'm just missing something minor.
Solution 1:
You will need a combination of DNAT and SNAT, and you need ip_forwarding active.
First, check ip_forwarding:
cat /proc/sys/net/ipv4/ip_forward
If it is 1 (enabled), go ahead. If not, you will have to put net.ipv4.ip_forward=1
on /etc/sysctl.conf
and run sysctl -p
.
The first rule is DNAT (assume 8.8.8.8
as the external IP and 192.168.0.10
as the internal):
iptables -t nat -A PREROUTING -d 8.8.8.8 -j DNAT --to-destination 192.168.0.10
When a external system (e.g. 200.100.50.25
) sends a packet reaching 8.8.8.8 will have the DESTINATION
changed to 192.168.0.10
, and sent away. But the source will be 200.100.50.25
, the packet will be processed and the response packet can:
Be dropped by 192.168.0.10 that may not know how to route it. Not desirable.
Be sent by 192.168.0.10 to the default gateway and to internet. As soon as it reaches
200.100.50.25
, this system will had never heard of192.168.0.10
and will drop the packet. Not good.Be dropped on the first hop, as
192.168.0.10
is a private address and not routeable on Internet.
To solve this, you need the second rule, SNAT:
iptables -t nat -A POSTROUTING -s 192.168.0.10 -j SNAT --to-source 8.8.8.8
With this rule, every packet that comes from 192.168.0.10
will have the source changed to 8.8.8.8
and sent away.
The collateral effect is that every log on 192.168.0.10
will show 8.8.8.8
as the client, not the real client. Tracking abusers will be a little harder.