1 (edited by thierry_b 2005-07-14 22:01:55)

Topic: problem with iptables

Hello,

I've some problems with iptables.

This is the config file of iptables.

#!/bin/sh
. /etc/functions.sh
WAN=$(nvram get wan_ifname)
LAN=$(nvram get lan_ifname)

## CLEAR TABLES
for T in filter nat mangle; do
  iptables -t $T -F
  iptables -t $T -X
done

iptables -N input_rule
iptables -N output_rule
iptables -N forwarding_rule

iptables -t nat -N prerouting_rule
iptables -t nat -N postrouting_rule

### Allow SSH from WAN
# iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 22 -j ACCEPT
# iptables        -A input_rule      -i $WAN -p tcp --dport 22 -j ACCEPT

### Port forwarding
# iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 22 -j DNAT --to 192.168.1.2
# iptables        -A forwarding_rule -i $WAN -p tcp --dport 22 -d 192.168.1.2 -j ACCEPT

### DMZ (should be placed after port forwarding / accept rules)
# iptables -t nat -A prerouting_rule -i $WAN -j DNAT --to 192.168.1.2
# iptables        -A forwarding_rule -i $WAN -d 192.168.1.2 -j ACCEPT

### INPUT
###  (connections with the router as destination)

  # base case
  iptables -P INPUT DROP
  iptables -A INPUT -m state --state INVALID -j DROP
  iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  iptables -A INPUT -p tcp --syn --tcp-option \! 2 -j  DROP

  # allow
  iptables -A INPUT -i \! $WAN    -j ACCEPT    # allow from lan/wifi interfaces
  iptables -A INPUT -p icmp    -j ACCEPT    # allow ICMP
  iptables -A INPUT -p gre    -j ACCEPT    # allow GRE
  #
  # insert accept rule or to jump to new accept-check table here
  #
  iptables -A INPUT -j input_rule

  # reject (what to do with anything not allowed earlier)
  iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
  iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable

### OUTPUT
### (connections with the router as source)

  # base case
  iptables -P OUTPUT DROP
  iptables -A OUTPUT -m state --state INVALID -j DROP
  iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

  # allow
  iptables -A OUTPUT -j ACCEPT        #allow everything out
  #
  # insert accept rule or to jump to new accept-check table here
  #
  iptables -A OUTPUT -j output_rule

  # reject (what to do with anything not allowed earlier)
  iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
  iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable

### FORWARDING
### (connections routed through the router)

  # base case
  iptables -P FORWARD DROP
  iptables -A FORWARD -m state --state INVALID -j DROP
  iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

  # allow
  iptables -A FORWARD -i br0 -o br0 -j ACCEPT
  iptables -A FORWARD -i $LAN -o $WAN -j ACCEPT
  #
  # insert accept rule or to jump to new accept-check table here
  #
  iptables -A FORWARD -j forwarding_rule

  # reject (what to do with anything not allowed earlier)
  # uses the default -P DROP

### MASQ
  iptables -t nat -A PREROUTING -j prerouting_rule
  iptables -t nat -A POSTROUTING -j postrouting_rule
  iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE

. /etc/firewall.user

I'va add the last line, because I've createdthe file firewall.user.

This is the contenu of firewall.user

### Port forwarding
iptables -t nat -A prerouting_rule -p tcp --dport 80 -j DNAT --to 192.168.0.3
iptables -A forwarding_rule -p tcp --dport 80 -d 192.168.0.3 -j ACCEPT

I wanted to nat the port 80 to the port 80 of my server (192.168.0.3).

It works from outside, but if I try myself to go to my webserver on my public ip, it doesn't work.

I don't understand why.

Thanks.
Bye

2 (edited by kaldek 2005-07-15 06:00:46)

Re: problem with iptables

My friend, you have been bitten by one of the classic mistakes when using NAT.  It's all to do with routing.  Anyway let's assume your PC address is 192.168.0.10, your router's Internet address is 210.10.1.10, and your router's LAN address is 192.168.0.1.

Here's what's going wrong:

1.  Internal PC with IP address of 192.168.0.10 connects to public address 210.10.1.10
2.  Router receives the packet, translates the destination address to 192.168.0.3, and forwards it back into the LAN
3.  Server receives packet, accepts connection, and responds directly (NOT via the router) to 192.168.0.10 with a source IP address of 192.168.0.3
4.  Client PC receives response packet from 192.168.0.3 and says "I never asked to speak to 192.168.0.3!  I was speaking to 210.10.1.10!  Piss off!"
5.  Client PC drops the packet.

The only way to fix this to work in your LAN is to reconfigure your firewall rules so that:

1. Connections from the Internet translate the destination address and forward the packet
2. Connections from the LAN to the Internet address and on port 80 translate the destination address *AND* the source address.

This is just off the top of my head, but try adding this line to the firewall.user file:

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s 192.168.0.0/24 -d 192.168.0.3 --dport 80 -j SNAT --to-source 192.168.0.1

By using the above confifguration, the packet flow changes so that it looks like so:

1.  Internal PC with IP address of 192.168.0.10 connects to public address 210.10.1.10
2.  Router receives the packet, translates the destination address to 192.168.0.3, and sends it to the forwarding_rule chain
3.  The forwarding_rule chain accepts the packet and it is then routed back into the LAN and passed off to the postrouting_rule chain
4.  The postrouting_rule chain alters the source address of the packet to be that of the router's LAN address
5. Server receives the packet, accepts the connection, and responds to the IP address of the router
6. Router receives the packet and - thanks to the state table - performs steps 4 to 1 (in reverse, effectively un-doing all the NAT) and sends the packet back out onto the LAN to the client PC
7. Client PC receives the packet and notes that the source address of the packet matches where it initially sent the connection to.
8. Connection succeeds.

Good Luck!

Kaldek

3 (edited by thierry_b 2005-07-15 09:08:15)

Re: problem with iptables

Thanks.
I twill test it, and I modify this post if it works :-)

Bye

Re: problem with iptables

Euh excuse me.
I read again what you read, but I don't understand something.
We change the source adresss of the packet with the ip lan of router, so when the packet comes to server : he see that the source is 192.168.0.1 and the destination it's itself (192.168.0.3).
So he send the packet to the router, but I don't understand hown the router knows that he has to send the packet to 192.168.0.10 because we have modified the source, so how he remmemmbers?

Thanks.
Bye

Re: problem with iptables

thierry_b wrote:

Euh excuse me.
I read again what you read, but I don't understand something.
We change the source adresss of the packet with the ip lan of router, so when the packet comes to server : he see that the source is 192.168.0.1 and the destination it's itself (192.168.0.3).
So he send the packet to the router, but I don't understand hown the router knows that he has to send the packet to 192.168.0.10 because we have modified the source, so how he remmemmbers?

There is a table (called the conntrack table) that contains the necessary bindings between IPs to do the translation. You can look at it in /proc/net/ip_conntrack.

Re: problem with iptables

i have the same problem so i used this line (small mods to it) but it does not seem to work

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s 192.168.1.0/24 -d 192.168.1.100 -m multiport --dports 59,6967,6968,8394 -j SNAT --to-source 192.168.1.1

anyhelp?

Re: problem with iptables

Vincent Bernat wrote:
thierry_b wrote:

Euh excuse me.
I read again what you read, but I don't understand something.
We change the source adresss of the packet with the ip lan of router, so when the packet comes to server : he see that the source is 192.168.0.1 and the destination it's itself (192.168.0.3).
So he send the packet to the router, but I don't understand hown the router knows that he has to send the packet to 192.168.0.10 because we have modified the source, so how he remmemmbers?

There is a table (called the conntrack table) that contains the necessary bindings between IPs to do the translation. You can look at it in /proc/net/ip_conntrack.

Vincent is right.  IPTables and most other firewalls these days are what is termed "stateful".  That is, once a connection has been established the firewall software remembers about it and knows *exactly* what to do with any response packets.  Prior to the invention of state tracking, we had to create TWO rules for every connection - one to allow the data in and one to allow it out.  It was messy when you had lots of rules.

I spend lots of my days designing & implementing firewall clusters for big corporates (mainly banks), and you would not believe how many people still think they need to do things the old way by creating two rules rather than one.

Kaldek

Re: problem with iptables

Weedy wrote:

i have the same problem so i used this line (small mods to it) but it does not seem to work

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s 192.168.1.0/24 -d 192.168.1.100 -m multiport --dports 59,6967,6968,8394 -j SNAT --to-source 192.168.1.1

anyhelp?

Hmmm that looks like it should pretty much work.  I'll set one up on my router here and see if perhaps my own syntax is wrong.  Like I said earlier, my idea was off the top of my head.  Which, depending on how many glasses of red wine I've had, can be bad. tongue

Kaldek

Re: problem with iptables

i still cant use my internet ip after using that line any help?

Re: problem with iptables

Weedy, you need three IPTables commands in total.  I've just tested these (with example IP addresses), and it works fine.  Edit the IP addresses, interface names, and ports, then place these commands in your firewall.user file.

iptables -t nat -A prerouting_rule -i br0 -p tcp -d 210.10.1.1 --dport 3389 -j DNAT --to 192.168.0.20
iptables -A forwarding_rule -i br0 -p tcp --dport 3389 -d 192.168.0.20 -j ACCEPT
iptables -t nat -A postrouting_rule -o br0 -p tcp -s 192.168.0.0/24 -d 192.168.0.20 --dport 3389 -j SNAT --to-source 192.168.0.254

Kaldek

Re: problem with iptables

so this will work?

iptables -t nat -A prerouting_rule -i $WAN -p  tcp -m multiport --dports 59,6967,6968,8394 -j DNAT --to 192.168.1.100
iptables        -A forwarding_rule -i $WAN -p  tcp -m multiport --dports 59,6967,6968,8394 -d 192.168.1.100 -j ACCEPT
iptables -t nat -A postrouting_rule -o $LAN -p tcp -s 192.168.1.0/24 -d 192.168.1.100 -m multiport --dports 59,6967,6968,8394 -j SNAT --to-source 192.168.1.1

12 (edited by kaldek 2005-07-16 08:57:35)

Re: problem with iptables

Ah, no.  *That* won't work.  You need the first two lines for your "Access from the Internet", and you need two more lines for the "Access from within the LAN".

You need the following in total:

iptables -t nat -A prerouting_rule -i $WAN -p  tcp -m multiport --dport 59,6967,6968,8394 -j DNAT --to 192.168.1.100
iptables -A forwarding_rule -i $WAN -p  tcp -m multiport --dport 59,6967,6968,8394 -d 192.168.1.100 -j ACCEPT

iptables -A -t nat prerouting_rule -i $LAN -p tcp -d 210.x.x.x -m multiport --dport 59,6967,6968,8394 -j DNAT --to 192.168.1.100
iptables -A forwarding_rule -i $LAN -p tcp -m multiport --dport 59,6967,6968,8394 -d 192.168.1.100 -j ACCEPT

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s 192.168.1.0/24 -d 192.168.1.100 -m multiport --dports 59,6967,6968,8394 -j SNAT --to-source 192.168.1.1


The tricky part about this is that you need to know what the WAN IP address is.  If it's dynamic and changes a lot, you have to keep editing the rule.  To get that address into a variable like "$WAN_IP" you'd need to write a script to grab it.


Kaldek

Re: problem with iptables

root@OpenWrt:/etc/init.d# ./S45firewall
iptables: No chain/target/match by that name

i think it is the lack of -t nat in the first $lan line should i put it in?

Re: problem with iptables

Ooops, yes.  Sorry, I mistyped it.  I'll add the "-nat" in to that now.

Kaldek

15 (edited by Weedy 2005-08-20 06:56:16)

Re: problem with iptables

kaldek wrote:

Ooops, yes.  Sorry, I mistyped it.  I'll add the "-nat" in to that now.

Kaldek

by that i think you mean -t nat. and thank you it works now. For anyone wanted to see my finished lines here

## TCP ports
iptables -t nat -A prerouting_rule -i $WAN -p  tcp -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -i $WAN -p  tcp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A prerouting_rule -i $LAN -p tcp -d <IP> -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -i $LAN -p tcp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s <RANGE>/24 -d <LAN> -m multiport --dports <CSP> -j SNAT --to-source <ROUTER>

## UDP ports
iptables -t nat -A prerouting_rule -i $WAN -p  udp -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -i $WAN -p  udp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A prerouting_rule -i $LAN -p udp -d <IP> -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -i $LAN -p udp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A postrouting_rule -o $LAN -p udp -s <RANGE>/24 -d <LAN> -m multiport --dports <CSP> -j SNAT --to-source <ROUTER>

Where:
<CSP> = comma seperated ports 1,2,3,4...
<IP> = your internet ip http://www.whatismyip.com/
<LAN> = the computer you are fwding the ports to (192.168.1.2, 192.168.1.3, 192.168.1.4...)
<RANGE> = the range your ips are in (192.168.1.0)
<ROUTER> = the routers ip (192.168.1.1)

hope this helps people and thanks kaldek

Edit: [mbm] pointed this out to me (thanks):

## TCP ports
iptables -t nat -A prerouting_rule -p tcp -d <IP> -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -p tcp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A postrouting_rule -o $LAN -p tcp -s <RANGE>/24 -d <LAN> -m multiport --dports <CSP> -j SNAT --to-source <ROUTER>

## UDP ports
iptables -t nat -A prerouting_rule -p udp -d <IP> -m multiport --dport <CSP> -j DNAT --to <LAN>
iptables          -A forwarding_rule -p udp -m multiport --dport <CSP> -d <LAN> -j ACCEPT

iptables -t nat -A postrouting_rule -o $LAN -p udp -s <RANGE>/24 -d <LAN> -m multiport --dports <CSP> -j SNAT --to-source <ROUTER>

the interface is not needed since the fwding need to happen on both $lan and $wan (saves 2 lines per rule/port/ip)

Re: problem with iptables

Weedy wrote:

by that i think you mean -t nat

Eeep!  FUBAR'd again.  Sorry about that. tongue

Kaldek

Re: problem with iptables

Just a quick followup (newbie) question: With OpenWRT's iptables, can you specify a range of ports? For example, using 1020:1029 for <CSP> in the examples above to specify port numbers 1020 through 1029.

If this is possible, then is it also possible to use a comma-separated list of port ranges, e.g. "--dport 1020:1029,2020:2029"?

Note that I use the colon syntax because I found mention of it on Google (in the context of general iptables usage in Linux).

Thanks.

18

Re: problem with iptables

HunterZ wrote:

Just a quick followup (newbie) question: With OpenWRT's iptables, can you specify a range of ports? For example, using 1020:1029 for <CSP> in the examples above to specify port numbers 1020 through 1029.

If this is possible, then is it also possible to use a comma-separated list of port ranges, e.g. "--dport 1020:1029,2020:2029"?

Note that I use the colon syntax because I found mention of it on Google (in the context of general iptables usage in Linux).

Thanks.

try it! smile
it should work

Re: problem with iptables

your script worked great for me to internally access internal hosts by the external dyndns-hostname. thanks!

kaldek wrote:

The tricky part about this is that you need to know what the WAN IP address is.  If it's dynamic and changes a lot, you have to keep editing the rule.  To get that address into a variable like "$WAN_IP" you'd need to write a script to grab it.
Kaldek

i've done that by adding a new variable in firewall.user:

WANIP=$(nvram get wan_ipaddr)

now, you can replace your external ip (here: <IP> = your internet ip http://www.whatismyip.com/) by $WANIP

that's it, works great. if your wan ip changes often, you'll have to crontab /etc/init.d/S45firewall

greetz

SoftIce

Re: problem with iptables

I'm having some trouble getting RDP through from work.  Playing around, I modified my firewall.user to match thierry_b but still have some variables that are different.  I tried adding the 3389 port reference entries above, but have still been unsuccessful.  In its sloppiness (I'll clean it all up when everything is working), here 'tis.

#!/bin/sh
. /etc/functions.sh

WAN=$(nvram get wan_ifname)
LAN=$(nvram get lan_ifname)
WANIP=$(nvram get wan_ipaddr)

iptables -F input_rule
iptables -F output_rule
iptables -F forwarding_rule
iptables -t nat -F prerouting_rule
iptables -t nat -F postrouting_rule

### INPUT
### (conections with the router as destination)

### Base case
iptables -P INPUT DROP
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A -p tcp --syn --tcp-option \! 2 -j DROP

### Allow
iptables -A INPUT -i \! $WAN -j ACCEPT   #allow from lan/wifi interfaces
iptables -A INPUT -p icmp    -j ACCEPT   #allow ICMP
iptables -A INPUT -p gre     -j ACCEPT   #allow GRE
#
# insert accept rule or jump to new accept-check table here
#
iptables -A INPUT -j input_rule

# reject (what to do with anything not allowed earlier
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A INPUT -j REJECT --reject-with icmp-port unreachable

### OUTPUT
### (connections with router as source)

# base case
iptables -P OUTPUT DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state RELATED,ESTABLISHED -j ACCEPT

# allow
iptables -A OUTOUT -j ACCEPT #allow everything out
#
# insert accept rule or to jump to new accept-check table here
#
iptables -A OUTPUT -j output_rule

# reject (what to do with anything not allowed earlier)
iptables -A OUTPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -A OUTPUT -j REJECT --reject-with icmp-port-unreachable

### FORWARDING
### (connections through the router)

# base case
iptables -P FORWARD DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# allow
iptables -A FORWARD -i br0 -o br0 -j ACCEPT
iptables -A FORWARD -i $LAN -o $WAN -j ACCEPT
#
# insert accept rule or to jump to new accept-check table here
#
iptables -A FORWARD -j forwarding_rule

# reject (what to do with anything not allowed earlier)
# uses the default -P DROP

### MASQ
iptables -t nat -A PREROUTING -j prerouting_rule
iptables -t nat -A POSTROUTING -j postrouting_rule
iptables -t nat -A POSTROUTING -o $WAN -j MASQUERADE

### Allow PPTP control connections from WAN
iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 1723 -j ACCEPT
iptables        -A input_rule      -i $WAN -p tcp --dport 1723 -j ACCEPT

#iptables -A INPUT -s 0/0 -d 1.2.3.4 -m state --state NEW -p tcp --dport 1723 -i
eth0 -j ACCEPT
#iptables -A INPUT -s 0/0 -d 1.2.3.4 -m state --state NEW -p 47 -j ACCEPT

### Allow GRE protocol (used by PPTP data stream)
iptables        -A output_rule             -p 47               -j ACCEPT
iptables        -A input_rule              -p 47               -j ACCEPT
iptables        -A forwarding_rule         -p 47               -j ACCEPT

### VPN Section
iptables        -A forwarding_rule -s 10.0.0.0/8 -d 10.0.0.0/8 -j ACCEPT
iptables        -A output_rule     -o ppp+ -s 10.0.0.0/8 -d 10.0.0.0/8 -j ACCEPT
iptables        -A input_rule      -i ppp+ -s 10.0.0.0/8 -d 10.0.0.0/8 -j ACCEPT

# allow VPN connections to get out on WAN interface (to internet)
iptables        -A forwarding_rule -i ppp+ -o $WAN -j ACCEPT

### CUSTOM RULES ###

iptables -A forwarding_rule -p 47 -j ACCEPT
iptables -A forwarding_rule -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -p 47 -j ACCEPT
iptables -A INPUT -p TCP --dport 1723 -j ACCEPT

### RDP connectivity

iptables -t nat -A prerouting_rule -i eth0 -p tcp -d $WANIP --dport 3389 -j DNAT
--to 10.0.0.3
iptables -A forwarding_rule -i eth0 -p tcp --dport 3389 -d 10.0.0.3 -j ACCEPT
iptables -t nat -A postrouting_rule -o eth0 -p tcp -s 10.0.0.0/8 -d 10.0.0.3 --d
port 3389 -j SNAT --to-source 10.0.0.254
#iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 3389 -j DNAT --to 10.
0.0.3
#iptables        -A forwarding_rule -i $WAN -p tcp --dport 3389 -d 10.0.0.3 -j A
CCEPT
#iptables        -A forwarding_rule -p tcp --dport 3389 -j ACCEPT
#iptables -A input -p TCP --dport 119 -j ACCEPT
#iptables -j ACCEPT -d 205.162.161.50 -p tcp --dport 1723 -m state --state NEW
#iptables -j ACCEPT -m state --state RELATED,ESTABLISHED

### OPEN PORTS ###

#iptables -A INPUT -i lo -p all -j ACCEPT
#iptables -A INPUT -p TCP --dport 1863 -j ACCEPT
#iptables -A INPUT -i vlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT

### BIG FAT DISCLAIMER
### The "-i $WAN" literally means packets that came in over the $WAN interface;
### this WILL NOT MATCH packets sent from the LAN to the WAN address.

### Allow SSH on the WAN interface
iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 22 -j ACCEPT
iptables        -A input_rule      -i $WAN -p tcp --dport 22 -j ACCEPT

### Port forwarding
#iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 22 -j DNAT --to 10.0.
0.3
#iptables        -A forwarding_rule -i $WAN -p tcp --dport 22 -d 10.0.0.3 -j ACC
EPT

### DMZ (should be placed after port forwarding / accept rules)
# iptables -t nat -A prerouting_rule -i $WAN -j DNAT --to 192.168.1.2
# iptables        -A forwarding_rule -i $WAN -d 192.168.1.2 -j ACCEPT
root@pwn3d:/etc#

Am I missing something blatantly obvious?