How to formulate IP forwarding rule using iptables

19,873

Solution 1

Here is a total non-answer answer.
as Jens Bradler said in his comment, the simplest thing to do here is to bind the service to the public IP address on port 8000, rather than NAT the connection. You can secure access to the single Server A by iptables rules like so;

 -A INPUT -s 192.168.0.5/32 -p tcp -m tcp --dport 8000 -j ACCEPT
 -A INPUT -p tcp -m tcp --dport 8000 -j REJECT

Solution 2

Tom H's non-answer answer is better, but if you don't like it, here is a direct answer:

Sorry, my iptables skills are best when I can tinker, test, check, logs, repeat... and I don't have your system to play with, but here is my advice anyway. You probably will need to debug using the logs.

Change the direction of your redirect, as stated by Jens Bradler:

echo "1" > /proc/sys/net/ipv4/ip_forward

Prove it is right

cat /proc/sys/net/ipv4/ip_forward

Output from cat:

1

Add a rule to ACCEPT using the FORWARD table also.

sudo iptables -A FORWARD -i wlan0 -p tcp --dport 8000 -j ACCEPT

Remove the "-m state" stuff from the incoming rule (optional... unnecessary I think):

sudo iptables -A INPUT -i wlan0 -p tcp --dport 8000 -j ACCEPT

Probably anywhere that you added "ESTABLISHED", you should also have "RELATED" (Not sure but I think a return packet that starts a connection is related, but not established).

sudo iptables -A OUTPUT -o wlan0 -p tcp --sport 8000 -m state --state RELATED,ESTABLISHED -j ACCEPT

The FORWARD rule to go with the above accept, reverse of the other FORWARD.

sudo iptables -A FORWARD -o wlan0 -p tcp -s 127.0.0.1 --sport 8000 -m state --state RELATED,ESTABLISHED -j ACCEPT

Instead of using Wireshark, use -j LOG.

First check to see that there aren't already LOG rules (the default ones are better than the following... but you used flush; mine will spam your server hard):

sudo iptables --list --line-numbers -v
sudo iptables -t nat --list --line-numbers -v

If not, then add them:

sudo iptables -A INPUT -j LOG
sudo iptables -A OUTPUT -j LOG
sudo iptables -A FORWARD -j LOG
sudo iptables -t nat -A PREROUTING -j LOG

Watch the logs

tail -F /var/log/firewall

# or if that file doesn't exist:
tail -F /var/log/messages

Solution 3

System B:

sysctl -w net.ipv4.conf.wlan0.route_localnet=1
iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 8080 -j DNAT --to 127.0.0.1

Solution 4

You can't ever perform -j DNAT --to 127.0.0.1.

127.0.0.1 is a super-duper-special address; it would only accept connections from 127.0.0.1.

@Tom H's answer is the way you should set up your server.

Share:
19,873

Related videos on Youtube

user907810
Author by

user907810

Updated on September 18, 2022

Comments

  • user907810
    user907810 over 1 year

    I have two Systems A and B. A is a TCP Client and sends a message to TCP Server on B.

    ------------------                --------------------------
    
      System A                        System B
      192.168.0.5 wlan0               192.168.0.3 wlan0
      127.0.0.1   lo                  127.0.0.1 lo
      TCP Client    <------------>    TCP Server on 127.0.0.1
    ------------------                ----------------------------
    

    The TCP Client sends message to 192.168.0.3.

    This should be redirected to the local interface of B as the TCP Server is running on 127.0.0.1 at Port 8000 of System B.

    Therefore, I wrote the following ip table rules, however my Server at B doesn't receive any messages. Oh btw these two systems are Ubuntu linux systems.

    Here is what I did on System B:

    #Enable IP Forwarding for NAT
    echo "1" > /proc/sys/net/ipv4/ip_forward
    
    #Flush all iptable chains and start afresh
    sudo iptables -F
    
    #Forward incoming packets on 192.168.0.3 at wlan0 interface to 127.0.0.1
    sudo iptables -t nat -A PREROUTING -p tcp -i wlan0 -d 192.168.0.3 --dport 8000 -j DNAT --to 127.0.0.1:8000
    
    #Explicitly allow incoming connections on port 8000 
    sudo iptables -A INPUT -i wlan0 -p tcp --dport 8000 -m state --state NEW,ESTABLISHED -j ACCEPT
    
    #Explicitly allow outgoing messages from port 8000
    sudo iptables -A OUTPUT -o wlan0 -p tcp --sport 8000 -m state --state ESTABLISHED -j ACCEPT
    

    Then I start the Server on B and send a message from TCP Client on A. I can see the packets on wireshark from 192.168.0.5 on wlan0 but they never get forwarded :(

    Please help.

    UPDATE:

    After inputs from experts here, I have made a more realistic "NAT" scenario for applying the forwarding rules but I have still issues: I have explained this in my newer post: Iptables: Forwarding packets doesn't work

    • Vizious Developer
      Vizious Developer about 12 years
      There is a simple bug in your code. I believe it should be echo "1" > /proc/sys/net/ipv4/ip_forward Additionally I'm not sure why you'd like to use NAT anyway. It doesn't make sense. NAT is something where you hide a network behind the NATting host and act in place of the origin host.
    • user907810
      user907810 about 12 years
      Oops that was really a typo error! Let me edit it!
  • Peter
    Peter about 12 years
    BTW I've done similar to the above a bunch, but I have never used "-j DNAT"
  • user907810
    user907810 about 12 years
    Thanks Peter. I am going to try this now and let you know :)
  • user907810
    user907810 about 12 years
    Oh I guess even the first FORWARD rule should omit -m state, am I right?
  • user907810
    user907810 about 12 years
    Hi Peter, I tried exactly what you said, however when the client on System A sends a packet to Server on B, the log message only shows the SYN requeston System B at 192.168.0.5 but that is all. The server doesnt receive the message as it doesnt get forwarded I guess :(
  • Peter
    Peter about 12 years
    Yes, the "-m state"| on its own is just a mistake. (I'll remove it now)
  • Peter
    Peter about 12 years
    The log should include any "DROP" and "REJECT" results (anything that makes it to the LOG line because there was no ACCEPT line)... so if it only has the SYN then maybe that is what is rejected. Does it say that it is rejected? For example of a drop log (having to do with rpc I think), see next comment.
  • Peter
    Peter about 12 years
    Apr 26 12:45:53 linux-esae kernel: [697677.775154] IN=eth0 OUT=eth2 SRC=10.5.0.55 DST=10.6.0.66 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=32045 DF PROTO=UDP SPT=51528 DPT=111 LEN=64
  • Peter
    Peter about 12 years
    Oh actually you should add --log-prefix "drop: " or your line won't say that it was dropped.
  • user907810
    user907810 about 12 years
    Hi Peter, var/log/messages show that the SYN packets on INPUT are being dropped. What is the problem??
  • user907810
    user907810 about 12 years
    Hi Peter, I changed the setup a bit to have a more real scenario of forwarding with NAT. But I have the same problem as here. Please check my new post: serverfault.com/questions/385251/…
  • Peter
    Peter about 12 years
    Shouldn't a NAT (the t being for "translation") translate the source address to the 127.0.0.1 so the listening process will think it is accepting something from there?