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?
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:
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:
There is a sysctl setting preventing dnat to loopback. replace eth0 below with your external interface traffic is coming in on.
To allow it
or
and to check the setting.
now you can dnat to 127.0.0.1
I had posted a similar question and found the answer for it my self. Here is the link : -
How to use iptables to forward requests to a jBoss server running on a different machine?