Port Forwarding in Different Network Scenarios
Port forwarding is useful for rerouting traffic to another port or machine. This is still my iptables version of that setup. The two private networks are 192.168.0.0/24 and 192.168.1.0/24.
Network Configuration
- ClientIP 192.168.0.240
- Machine1 192.168.0.2 port 2020
- Machine2 192.168.1.2 port 1010
Enabling IP Forwarding
The kernel needs to allow forwarding. To do this temporarily, use the sysctl command:
sysctl -w net.ipv4.ip_forward=1
To make it permanent, add /etc/sysctl.d/90-port-forward.conf:
net.ipv4.ip_forward = 1
You can check if IP forwarding is enabled by viewing the content of the /proc/sys/net/ipv4/ip_forward file:
cat /proc/sys/net/ipv4/ip_forward
Setting Up IPTables Rules
Now we need to set up iptables rules to redirect the source port to Machine2’s IP and port. We also need to masquerade the traffic so Machine2 answers to Machine1, which in turn answers to the client.
iptables -t nat -A PREROUTING -i ens18 -p tcp -d 192.168.0.2 --dport 2020 \
-j DNAT --to-destination 192.168.1.2:1010
iptables -t nat -A POSTROUTING -p tcp -s 192.168.0.240 -d 192.168.1.2 --dport 1010 \
-j MASQUERADE
Since traffic is moving from PREROUTING to FORWARD to POSTROUTING, we need to make the FORWARD chain aware and accept the traffic from the client and not drop it before it reaches POSTROUTING.
iptables -A FORWARD -i ens18 -p tcp -s 192.168.0.240 -d 192.168.1.2 --dport 1010 \
-m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -o ens18 -p tcp -s 192.168.1.2 --sport 1010 -d 192.168.0.240 \
-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
To monitor the iptables rules, use these commands:
watch iptables -t nat -L -n -v
watch iptables -L -n -v
Forwarding to Internal Localhost
To forward to localhost, enable route_localnet only on that interface. This weakens the normal martian-address check, so I retain source and port restrictions in the DNAT rule:
sysctl -w net.ipv4.conf.ens18.route_localnet=1
You can set up the forwarding from one host, from one subnet, or even from one MAC address:
iptables -t nat -A PREROUTING -i ens18 -p tcp -s 192.168.0.123 --dport 8001 -j DNAT --to-destination 127.0.0.1:8001
iptables -t nat -A PREROUTING -i ens18 -p tcp -s 192.168.0.0/24 --dport 8001 -j DNAT --to-destination 127.0.0.1:8001
iptables -t nat -A PREROUTING -i ens18 -p tcp -m mac --mac-source 00:0F:EA:91:04:07 --dport 8001 -j DNAT --to-destination 127.0.0.1:8001
You can even block all traffic except for a specific MAC address:
/sbin/iptables -A INPUT -p tcp --dport 22 -m mac ! --mac-source YOUR-MAC-ADDRESS-HERE -j DROP
Persistence is distribution-specific. On Debian/Ubuntu with iptables-persistent:
sudo netfilter-persistent save
Optional nftables Translation
I keep iptables primary because it is what this setup used. For comparison, its main NAT rules translate to:
table ip port_forward {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname "ens18" ip daddr 192.168.0.2 tcp dport 2020 dnat to 192.168.1.2:1010
}
chain postrouting {
type nat hook postrouting priority srcnat;
ip saddr 192.168.0.240 ip daddr 192.168.1.2 tcp dport 1010 masquerade
}
}
This is an optional translation, not a replacement for my tested workflow. nftables NAT documentation
By using these steps, you should be able to successfully forward traffic from one machine to another, or from one network to another, with iptables.
Buy Me a Coffee