How to configure traffic from a specific IP hardcoded to an IP to forward to another IP:PORT using iptables?
Solution 1
Your NAT rule seems ok, but have you also added an ACCEPT rule for this traffic?
Otherwise, NAT will kick in finely, but then the resulting packet will silently be dropped...
Update:
You need this rule in the FORWARD chain (which is where packets going thorugh the firewall but not directly related to it are processed).
FORWARD rules are applied after PREROUTING rules (like NAT), so when this rule is applied the packets will appear like they're coming from the original IP but directed to the modified new destination IP. The rule should thus be somewhat like this:
/sbin/iptables -A FORWARD -s $CUSTIP -d $NEW_SERVER_IP -j ACCEPT
Solution 2
I presume you're using the linux box as a router and that this linux box can see the new IP.
I believe that the NAT table only kicks in when /proc/sys/net/ipv4/ip_forward is set to 1. To make this persistent, put the following line in /etc/sysctl.conf:
net.ipv4.ip_forward = 1
Solution 3
There is a sysctl setting preventing dnat to loopback. replace eth0 below with your external interface traffic is coming in on.
To allow it
sysctl -w net.ipv4.conf.eth0.route_localnet=1
or
echo 1 > /proc/sys/net/ipv4/conf/eth0/route_localnet
and to check the setting.
cat /proc/sys/net/ipv4/conf/eth0/route_localnet
now you can dnat to 127.0.0.1
Related videos on Youtube
Smyrnian
Updated on September 17, 2022Comments
-
Smyrnian almost 2 years
Unfortunately we have a client who has hardcoded a device to point at a specific IP and port. We'd like to redirect traffic from their IP to our load balancer which will send the HTTP POSTs to a pool of servers able to handle that request. I would like existing traffic from all other IPs to be unaffected.
I believe iptables is the best way to accomplish this and I think this command should work:
/sbin/iptables -t nat -A PREROUTING -s $CUSTIP -j DNAT -p tcp --dport 8080 -d $CURR_SERVER_IP --to-destination $NEW_SERVER_IP:8080
Unfortunately it isn't working as expected. I'm not sure if I need to add another rule, potentially in the
POSTROUTING
chain?Below I've substituted the variables above with real IPs and tried to replicate the layout in my test environment in incremental steps.
$CURR_SERVER_IP = 192.168.2.11 $NEW_SERVER_IP = 192.168.2.12 $CUST_IP = 192.168.0.50
-
Port forward on the same IP
/sbin/iptables -t nat -A PREROUTING -p tcp -d 192.168.2.11 --dport 16000 -j DNAT --to-destination 192.168.2.11:8080
Works exactly as expected.
-
IP and port forward to a different machine
/sbin/iptables -t nat -A PREROUTING -p tcp -d 192.168.2.11 --dport 16000 -j DNAT --to-destination 192.168.2.12:8080
Connections seem to timeout.
-
Restrict IP and port forward to only be applied to requests from a specific IP
/sbin/iptables -t nat -A PREROUTING -p tcp -s 192.168.0.50 -d 192.168.2.11 --dport 16000 -j DNAT --to-destination 192.168.2.12:8080
I've added the
ACCEPT
rule as @Massimo suggested but still not seeing any success.I started fresh and have run the following commands:
# /sbin/iptables -t nat -A PREROUTING -p tcp -d 192.168.2.11 --dport 16000 -j DNAT --to-destination 192.168.2.12:8080 # iptables -A FORWARD -j ACCEPT
And the rules now look like:
# iptables -L -v --line-numbers (see FORWARD rule 7) Chain INPUT (policy ACCEPT 1115M packets, 889G bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT udp -- virbr0 any anywhere anywhere udp dpt:domain 2 0 0 ACCEPT tcp -- virbr0 any anywhere anywhere tcp dpt:domain 3 0 0 ACCEPT udp -- virbr0 any anywhere anywhere udp dpt:bootps 4 0 0 ACCEPT tcp -- virbr0 any anywhere anywhere tcp dpt:bootps Chain FORWARD (policy ACCEPT 112 packets, 5936 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT all -- any virbr0 anywhere 192.168.122.0/24 state RELATED,ESTABLISHED 2 0 0 ACCEPT all -- virbr0 any 192.168.122.0/24 anywhere 3 0 0 ACCEPT all -- virbr0 virbr0 anywhere anywhere 4 0 0 REJECT all -- any virbr0 anywhere anywhere reject-with icmp-port-unreachable 5 0 0 REJECT all -- virbr0 any anywhere anywhere reject-with icmp-port-unreachable 6 0 0 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED 7 6 336 ACCEPT all -- any any anywhere anywhere Chain OUTPUT (policy ACCEPT 813M packets, 428G bytes) num pkts bytes target prot opt in out source destination
and
# iptables -L -t nat -v --line-numbers Chain PREROUTING (policy ACCEPT 3108K packets, 242M bytes) num pkts bytes target prot opt in out source destination 1 0 0 DNAT tcp -- any any anywhere 192.168.2.11 tcp dpt:16000 to:192.168.2.12:8080 Chain POSTROUTING (policy ACCEPT 13M packets, 790M bytes) num pkts bytes target prot opt in out source destination 1 8644 1979K MASQUERADE all -- any any 192.168.122.0/24 anywhere Chain OUTPUT (policy ACCEPT 13M packets, 792M bytes) num pkts bytes target prot opt in out source destination
Does anyone see obvious issues that would cause a browser to time out when I go to http://192.168.2.11:16000?
-
Admin over 13 yearsJust a comment; an easier way of showing us your iptables rules is to run
iptables-save
; the output of this is typically more useful (since it shows the actual commands used to create the rule). This is for future reference and not a request to change your current question.
-
-
Smyrnian about 14 yearsI have not added any ACCEPT rules. I'm new to iptables so I'll do some more research but are you suggesting I need this rule on $CURR_SERVER_IP to accept from $CUST_IP or on $NEW_SERVER_IP?
-
Massimo about 14 years@cclark: see edit above.
-
Smyrnian about 14 yearsThanks. Still no dice. I've updated and included the rules list above in hopes that a little more information might shed some light on the issue.