How to configure traffic from a specific IP hardcoded to an IP to forward to another IP:PORT using iptables?

22,032

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

Share:
22,032

Related videos on Youtube

Smyrnian
Author by

Smyrnian

Updated on September 17, 2022

Comments

  • Smyrnian
    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
      Admin over 13 years
      Just 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
    Smyrnian about 14 years
    I 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
    Massimo about 14 years
    @cclark: see edit above.
  • Smyrnian
    Smyrnian about 14 years
    Thanks. 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.