OpenWrt Forum Archive

Topic: Port Forward Confusion...

The content of this topic has been archived on 19 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Ok so i followed the Getting started tips and it does not forward as i would like.

I used the awk script as a guide as to what i need (b/c i thought it really emulated what the stock Linksys had done).

I have a webserver on the other side of my router that only accepts https connections (port 443).  Let's pretend that the public web address is hugemikeyd.com, now i would like to be able to type "https://www.hugemikeyd.com" on my LAN and should be able to resolve it properly, but it does not seem to work.  Now here is my firewall script:

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

WAN=$(nvram get wan_ifname)

IPT=/usr/sbin/iptables

for T in filter nat mangle ; do
  $IPT -t $T -F
  $IPT -t $T -X
done

$IPT -t filter -A INPUT -m state --state INVALID -j DROP
$IPT -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A INPUT -p icmp -j ACCEPT

#SSH Forwarding
$IPT -A FORWARD -p tcp -i $WAN --dport 22 -j ACCEPT
$IPT -A PREROUTING -t nat -p tcp -i $WAN --dport 22 -j DNAT --to-destination 192.168.1.8:22
$IPT -A INPUT -p tcp -i $WAN --dport 22 -j ACCEPT

#HTTPS Forwarding
$IPT -A FORWARD -p tcp --dport 443 -j ACCEPT
$IPT -A PREROUTING -t nat -p tcp --dport 443 -j DNAT --to-destination 192.168.1.8:443
$IPT -A INPUT -p tcp --dport 443 -j ACCEPT

$IPT -t filter -A INPUT -i $WAN -p tcp -j REJECT --reject-with tcp-reset
$IPT -t filter -A INPUT -i $WAN -j REJECT --reject-with icmp-port-unreachable
$IPT -t filter -A FORWARD -m state --state INVALID -j DROP
$IPT -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP
$IPT -t filter -A FORWARD -o $WAN -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE

As you can see i would like both port 22 and 443 to go to my server, but i would also like to be able to resolve it from my lan.

I must be missing something stupid...

i just got finished checking into the stock code : /WRT54GS_3_37_2_1109_US/release/src/router/rc/firewall.c

and it looks like there is a file that is created on the fly based on what was input into the web interface and that file is created to: /tmp/.ipt

Is there anyway we could get the data from that file?  I guess with HyperWRT or something, anybody want to offer the info for me?

$IPT -A INPUT -p tcp --dport 443 -j ACCEPT
You don't need that rule unless you're running an https server on the router itself.  Even then, it will never be followed because the rule immediately preceding it will match it first.

The crux of your problem is that the DNAT rules you have in place that perform the port forwarding don't work when for LAN --> LAN, only WAN --> LAN.  Here's what's happenning:

1. Your host tries to initiate a connection to your https server www.hugemikeyd.com.  That DNS resolves to your router, so your host tries to initiate the https conenction with your router.

2. Your router takes the SYN packet, and alters the destination address to point to your https server, but leaves the source address unchanged.

3. The packet gets put back onto your LAN, where it's picked up by your https server, and it returns an ACK, but since the source address was left untouched by your router, it sends the ACK directly to your host, circumventing the router.

4. Your host receives the ACK packet, but instead of completing the three-way handshake, it tosses it away and resets the connection. Why? Because from your host's perspective, that ACK packet is not related to any connection that it knows about.  Your host initiated a connection with the router, and it was expecting an ACK from your router.  It knows nothing about your actual https server, and nothing about any packets it receives from it.

There are several solutions to your dilemma, the easiest probably being to just use a different DNS that resolves to the LAN IP of your https server.  Alternatively, you could also provide an SNAT rule to correctly alter the source address.

well it looks like i need to grab a book on iptables huh...

I am going to see if i can figure out how Linksys does it and post it up on this thread.  I am pretty sure that they don't use SNAT to get things done.

I am not trying to go against you, i just have no idea how to do this...

Hi,

I had the same Problem and just solved it by adding the "-s ! 127.0.0.0/8" to the forward rules. Seems the packets were going in an endless loop before.
Here's my S45firewall script:
[code]
#!/bin/sh
. /etc/functions.sh

WAN=$(nvram get wan_ifname)
PFORW="81@10.0.0.128 443@10.0.0.128 993@10.0.0.128 8021@10.0.0.128 4660:4670@10.0.0.16 1564:1565@10.0.0.16"

IPT=/usr/sbin/iptables

for T in filter nat mangle ; do
  $IPT -t $T -F
  $IPT -t $T -X
done

for forw in $PFORW; do
        port=$(echo $forw | awk -F "@" '{print $1;}')
        ip=$(echo $forw | awk -F "@" '{print $2;}')
        $IPT -t nat -A PREROUTING -p tcp -s ! 127.0.0.0/8 --destination-port $port -j DNAT --to $ip
        $IPT -t filter -A FORWARD -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
        $IPT -t filter -A INPUT -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
done

$IPT -t filter -A INPUT -m state --state INVALID -j DROP
$IPT -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A INPUT -p icmp -j ACCEPT
$IPT -t filter -A INPUT -i $WAN -p tcp -j REJECT --reject-with tcp-reset
$IPT -t filter -A INPUT -i $WAN -j REJECT --reject-with icmp-port-unreachable
$IPT -t filter -A FORWARD -m state --state INVALID -j DROP
$IPT -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
#$IPT -t filter -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP
$IPT -t filter -A FORWARD -o $WAN -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
[/code]
[/code]

WOW thanks!

So this just throws out the packet if it has a source of localhost?

Hi,

So this just throws out the packet if it has a source of localhost?

Yep, exactly. It should prevent infinite loops within the router. I just noticed the flaw that all outgoing packets for port 443 were forced to my internal https server :oops: so I fixed that:

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

WAN=$(nvram get wan_ifname)
LAN=$(nvram get lan_ifname)
PFORW="81@10.0.0.128 443@10.0.0.128 993@10.0.0.128 8021@10.0.0.128 4660:4670@10.0.0.16 1564:1565@10.0.0.16"

IPT=/usr/sbin/iptables

for T in filter nat mangle ; do
  $IPT -t $T -F
  $IPT -t $T -X
done

for forw in $PFORW; do
        port=$(echo $forw | awk -F "@" '{print $1;}')
        ip=$(echo $forw | awk -F "@" '{print $2;}')
        $IPT -t nat -A PREROUTING -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j DNAT --to $ip
        $IPT -t nat -A PREROUTING -i $LAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j DNAT --to $ip
        $IPT -t filter -A FORWARD -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
        $IPT -t filter -A INPUT -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
done

$IPT -t filter -A INPUT -m state --state INVALID -j DROP
$IPT -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A INPUT -p icmp -j ACCEPT
$IPT -t filter -A INPUT -i $WAN -p tcp -j REJECT --reject-with tcp-reset
$IPT -t filter -A INPUT -i $WAN -j REJECT --reject-with icmp-port-unreachable
$IPT -t filter -A FORWARD -m state --state INVALID -j DROP
$IPT -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
#$IPT -t filter -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP
$IPT -t filter -A FORWARD -o $WAN -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Edit:
Had to fix issue with local routing ->

for forw in $PFORW; do
        port=$(echo $forw | awk -F "@" '{print $1;}')
        ip=$(echo $forw | awk -F "@" '{print $2;}')
        $IPT -t nat -A PREROUTING -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j DNAT --to $ip
        $IPT -t nat -A PREROUTING -i $LAN -p tcp -d ! 10.0.0.0/16 --destination-port $port -j DNAT --to $ip
        $IPT -t filter -A FORWARD -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
        $IPT -t filter -A INPUT -i $WAN -p tcp -s ! 127.0.0.0/8 --destination-port $port -j ACCEPT
done

Ok i modified my S45firewall to be:

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

WAN=$(nvram get wan_ifname)
LAN=$(nvram get lan_ifname)
#WANIP='/sbin/ifconfig ppp0 | grep 'inet addr' | awk '{print $2}' | sed -e s/.*://'

IPT=/usr/sbin/iptables

for T in filter nat mangle ; do
  $IPT -t $T -F
  $IPT -t $T -X
done

$IPT -t filter -A INPUT -m state --state INVALID -j DROP
$IPT -t filter -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A INPUT -p icmp -j ACCEPT

#SSH Forwarding
$IPT -A FORWARD -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 22 -j ACCEPT
$IPT -A PREROUTING -t nat -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 22 -j DNAT --to-destination 192.168.1.8:22
$IPT -A PREROUTING -t nat -p tcp -i $LAN -d ! 192.168.1.0/16 --dport 22 -j DNAT --to-destination 192.168.1.8:22
$IPT -A INPUT -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 22 -j ACCEPT

#HTTPS Forwarding
$IPT -A FORWARD -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 443 -j ACCEPT
$IPT -A PREROUTING -t nat -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 443 -j DNAT --to-destination 192.168.1.8:443
$IPT -A PREROUTING -t nat -p tcp -i $LAN -d ! 192.168.1.0/16 --dport 443 -j DNAT --to-destination 192.168.1.8:443
$IPT -A INPUT -p tcp -i $WAN -s ! 127.0.0.0/8 --dport 443 -j ACCEPT

#$IPT -A PREROUTING -p tcp -m tcp -d $WANIP --dport 443 -j DNAT --to-destination 192.168.1.8
#$IPT -A FORWARD -p tcp -m tcp -d 192.168.1.8 --dport 443 -j ACCEPT

$IPT -t filter -A INPUT -i $WAN -p tcp -j REJECT --reject-with tcp-reset
$IPT -t filter -A INPUT -i $WAN -j REJECT --reject-with icmp-port-unreachable
$IPT -t filter -A FORWARD -m state --state INVALID -j DROP
$IPT -t filter -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPT -t filter -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP
$IPT -t filter -A FORWARD -o $WAN -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE

I still cannot resolve my web server from inside of my network...

Hi,

I had the same problem, and it worked for me after using ppp0 as WAN-Interface...

Hi,

You've just hit a routing / NAT problem. Check this:

Example:

Client IP on LAN: 192.168.1.10
Router IP on LAN: 192.168.1.1
Server IP on LAN: 192.168.1.2
Public IP:        175.224.2.22

Your client tries to connect to the webserver using the public IP address: 192.168.1.10 -> 175.224.2.22
Next, this request is translated by the DNAT rule to: 192.168.1.10 -> 192.168.1.2 and sent to the server on your LAN.

Guess where all the replies from your server are going to? Indeed, directly to your client: 192.168.1.2 -> 192.168.10 !

Of course, the IP stack on your client doesn't recognise this connection and silently discards the traffic. Solution: Perform SOURCE NAT for all connections you DNAT from the LAN interface. So, something like

iptables -t nat -I PREROUTING -i $LAN -s 192.168.1.0/24 -d 175.224.2.22/32 -p tcp --dport 443
-j MASQUERADE

Now all traffic sent from the LAN to the public IP is masqueraded to come from the router itself. Just make sure the DNAT'ed traffic comes back to the router itself.

This should do the trick (by example, of course). I know this isn't a "nice" workaround, and also the rule-order is _very_ important.

If this information isn't enough to make it work, let me know. Then I'll dive into your ruleset and provide a working ruleset.

Regards,

Michel

How do I forward the tcp port 1122 from WAN to port 22 on the internal IP 192.168.1.11? I tried the following rule in my /etc/firewall.user conf file, but it didn't appear to work..

iptables -t nat -A prerouting_rule -i $WAN -p tcp --dport 1122 -j DNAT --to 192.168.1.11:22
iptables        -A forwarding_rule -i $WAN -p tcp --dport 1122 -d 192.168.1.11 -j ACCEPT

Any help would be greatly appreaciated. Thanks,

Ville

va1210 wrote:

iptables        -A forwarding_rule -i $WAN -p tcp --dport 1122 -d 192.168.1.11 -j ACCEPT

Pre-routing happens before forward, so you need to change the bolded port above to the now DNAT'd to 22.

Great, now it works perfectly! Thanks a lot for the help!

The discussion might have continued from here.