# quick iptables port forwarding question

## Seather

Heya

Moving my router/gateway box from FreeBSD to Linux, I'm trying to convert my ipfw firewall to iptables, but I'm stuck with something.

My gateway gateway box connects to the net with a 56k ppp0 dialup connection (dynamic IP), and is connected to my switch with eth0 (192.168.0.45), which uses ip masquerading to share the internet connection to my whole network (192.168.0.*).

Now, my servers such as webserver (192.168.0.254), are all on seperate boxes inside the network. How to I portforward port 80 so that http://mydialupip will show 192.168.0.254's webserver?

My current testing iptables ruleset is as follows:

```

IPTABLES=/sbin/iptables

EXTIF="ppp0"

INTIF="eth0"

printf "\nExternal Interface:  $EXTIF\nInternal Interface:  $INTIF\n\n"

#CRITICAL:  Enable IP forwarding since it is disabled by default since

#

echo "Enabling forwarding.."

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

echo "Enabling DynamicAddr.."

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

echo "Clearing any existing rules and setting default policy.."

$IPTABLES -P INPUT ACCEPT

$IPTABLES -F INPUT 

$IPTABLES -P OUTPUT ACCEPT

$IPTABLES -F OUTPUT 

$IPTABLES -P FORWARD DROP

$IPTABLES -F FORWARD 

$IPTABLES -t nat -F

echo "FWD: Allow all connections OUT and only existing and related ones IN"

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT

$IPTABLES -A FORWARD -j LOG

echo "Enabling SNAT (MASQUERADE) functionality on $EXTIF"

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

```

Thanks!

----------

## eNut

These lines should work.  If not then you may have to get your external IP in the ip.up script for ppp0 and set it to an environment variable to use it in the prerouting line.  I'll see if I can hunt down that script.

```

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 80 -j DNAT --to 192.168.0.254:80

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

```

----------

## eNut

Ok, this is taken directly from the IP-Masqerading HOW-TO that can be found at http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/IP-Masquerade-HOWTO.html.  This is a great source of info for setting up anything with IPTables.  I would suggest reading the whole document.  It helps everything make more sense.

Karl

```

#   PPP users:

#   ----------

#   If you aren't already aware, the /etc/ppp/ip-up script is always run when 

#   a PPP connection comes up.  Because of this, we can make the ruleset go and 

#   get the new PPP IP address and update the strong firewall ruleset.

#

#   If the /etc/ppp/ip-up file already exists, you should edit it and add a line

#   containing "/etc/rc.d/rc.firewall" near the end of the file.

#

#   If you don't already have a /etc/ppp/ip-up sccript, you need to create the 

#   following link to run the /etc/rc.d/rc.firewall script.

#

#       ln -s /etc/rc.d/rc.firewall /etc/ppp/ip-up

#

#   * You then want to enable the #ed out shell command below *

#

#

# Determine the external IP automatically:

# ----------------------------------------

#

#  The following line will determine your external IP address.  This

#  line is somewhat complex and confusing but it will also work for

#  all NON-English Linux distributions:

#

EXTIP="`$IFCONFIG $EXTIF | $AWK \

 /$EXTIF/'{next}//{split($0,a,":");split(a[2],a," ");print a[1];exit}'`"

```

For this code block you'd have to make an alias for ifconfig or replace $IFCONFIG with /path-to/ifconfig. And then you can change

```
$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 80 -j DNAT --to 192.168.0.254:80 
```

to

```
$IPTABLES -t nat -A PREROUTING -p tcp -d $EXTIP --dport 80 -j DNAT --to 192.168.0.254:80 
```

----------

## Seather

Thanks, I have tried it out, still not working though, for some reason. Any ideas perhaps? Here is my full /etc/init.d/firewall file. Excuse the start() blah blah stuff, it is so I can use `/etc/init.d/firewall restart` etc.

Anyhow, here goes, this is what it's like currently:

```

#!/sbin/runscript

IPTABLES=/sbin/iptables

EXTIF="ppp0"

INTIF="eth0"

IFCONFIG=/sbin/ifconfig

LSMOD=/sbin/lsmod

DEPMOD=/sbin/depmod

MODPROBE=/sbin/modprobe

GREP=/bin/grep

AWK=/bin/awk

SED=/bin/sed

start() {

        ebegin "Loading Firewall"

printf "\nExternal Interface:  $EXTIF\nInternal Interface:  $INTIF\n\n"

#CRITICAL:  Enable IP forwarding since it is disabled by default since

#

echo "Enabling forwarding.."

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

# Dynamic IP users:

#

#   If you get your IP address dynamically from SLIP, PPP, or DHCP, 

#   enable this following option.  This enables dynamic-address hacking

#   which makes the life with Diald and similar programs much easier.

#

echo "Enabling DynamicAddr.."

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

# Set external device IP Address VAR

EXTIP="`$IFCONFIG $EXTIF | $AWK \

 /$EXTIF/'{next}//{split($0,a,":");split(a[2],a," ");print a[1];exit}'`"

echo "Exernal ip is $EXTIP"

#Clearing any previous configuration

#

#  Unless specified, the defaults for INPUT and OUTPUT is ACCEPT

#    The default for FORWARD is DROP (REJECT is not a valid policy)

#

echo "Clearing any existing rules and setting default policy.."

$IPTABLES -P INPUT ACCEPT

$IPTABLES -F INPUT 

$IPTABLES -P OUTPUT ACCEPT

$IPTABLES -F OUTPUT 

$IPTABLES -P FORWARD DROP

$IPTABLES -F FORWARD 

$IPTABLES -t nat -F

echo "FWD: Allow all connections OUT and only existing and related ones IN"

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT

$IPTABLES -A FORWARD -j LOG

echo "Enabling SNAT (MASQUERADE) functionality on $EXTIF"

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 80 -j DNAT --to 192.168.0.254:80

$IPTABLES -t nat -A PREROUTING -p tcp -d $EXTIP --dport 80 -j DNAT --to 192.168.0.254:80

printf "\n"

        eend 0

}

stop() {

        ebegin "Clearing Firewall"

        iptables -F

        eend 0

}

```

I have read the IP Masquerading Howto (most of my firewall script came from it anyway), I really need to get this going so I can change the servers  :Sad:  Thanks a million hey

Btw, this is what comes up in /var/log/messages when I try to http://ipaddress to the gateway from an outside box from the other side of the world:

Aug 21 23:47:28 aeon kernel: IN=ppp0 OUT=eth0 SRC=208.178.220.4 DST=192.168.0.254 LEN=60 TOS=0x08 PREC=0x00 TTL=42 ID=39012 DF PROTO=TCP SPT=49832 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 

Aug 21 23:47:31 aeon kernel: IN=ppp0 OUT=eth0 SRC=208.178.220.4 DST=192.168.0.254 LEN=60 TOS=0x08 PREC=0x00 TTL=42 ID=39013 DF PROTO=TCP SPT=49832 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 

Aug 21 23:47:37 aeon kernel: IN=ppp0 OUT=eth0 SRC=208.178.220.4 DST=192.168.0.254 LEN=60 TOS=0x08 PREC=0x00 TTL=42 ID=39014 DF PROTO=TCP SPT=49832 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 

Aug 21 23:47:49 aeon kernel: IN=ppp0 OUT=eth0 SRC=208.178.220.4 DST=192.168.0.254 LEN=60 TOS=0x08 PREC=0x00 TTL=42 ID=39015 DF PROTO=TCP SPT=49832 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0 

Aug 21 23:48:13 aeon kernel: IN=ppp0 OUT=eth0 SRC=208.178.220.4 DST=192.168.0.254 LEN=60 TOS=0x08 PREC=0x00 TTL=42 ID=39016 DF PROTO=TCP SPT=49832 DPT=80 WINDOW=5840 RES=0x00 SYN URGP=0

Maybe that helps?

----------

## FuzzeX

This is just an off the top of my head guess as netfilter.org is not responding to requests at the moment, but try adding a line like:

```
$IPTABLES -A FORWARD -p tcp -d $EXTIP --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j nat
```

It's looking like your web requests are getting caught by the line:

```
$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT
```

Just a guess. Hope it works.

----------

## eNut

Ok.  I think I see the problem.  The last part of your code block should look like this (my entries are commented):

```
#Clearing any previous configuration 

# 

#  Unless specified, the defaults for INPUT and OUTPUT is ACCEPT 

#    The default for FORWARD is DROP (REJECT is not a valid policy) 

# 

echo "Clearing any existing rules and setting default policy.." 

$IPTABLES -P INPUT ACCEPT 

$IPTABLES -F INPUT 

$IPTABLES -P OUTPUT ACCEPT 

$IPTABLES -F OUTPUT 

$IPTABLES -P FORWARD DROP 

$IPTABLES -F FORWARD 

$IPTABLES -t nat -F 

echo "FWD: Allow all connections OUT and only existing and related ones IN" 

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT 

$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT 

### INSERT

### Allow HTTP traffic

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT 

###

$IPTABLES -A FORWARD -j LOG 

echo "Enabling SNAT (MASQUERADE) functionality on $EXTIF" 

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE 

### INSERT

###  Forwarding HTTP Traffic

$IPTABLES -t nat -A PREROUTING -p tcp -d $EXTIP --dport 80 -j DNAT --to 192.168.0.254:80 

###

printf "\n" 
```

That should work.

Karl

----------

## Seather

Okay, I've tried the suggestions, but still no go at all  :Sad: . Though, lets leave ip masquerading for sharing the internet connection out of it for now, and try it cleanly. Let 192.168.0.45 on eth0 route all http traffic through to 192.168.0.69 also using eth0.

This is what I've tried, what I think should do it, am I right? Cause it doesn't work either? What else may be wrong, kernel option? proc/sys option? Anyhow, thanks guys

```

IPTABLES=/sbin/iptables

# Enable port Forwarding

echo "Enabling forwarding.."

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

# Enable Dynamic Addressing:

echo "Enabling DynamicAddr.."

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

# Accept all from everywhere, etc yada

echo "Clearing any existing rules and setting default policy.."

$IPTABLES -P INPUT ACCEPT

$IPTABLES -F INPUT

$IPTABLES -P OUTPUT ACCEPT

$IPTABLES -F OUTPUT

$IPTABLES -P FORWARD ACCEPT

$IPTABLES -F FORWARD

$IPTABLES -t nat -F

#  Forwarding HTTP Traffic

echo "Adding rules for forwarding trafic.."

$IPTABLES -t nat -A PREROUTING -p tcp -d 192.168.0.45 --dport 80 -j DNAT --to 192.168.0.69:80

```

According to me this should work!? What else should be done to enable iptables to do this kind of thing?

----------

## FuzzeX

Hmm...

My two suggestions before we start kernel mucking would be:

1. Make sure that your DNAT command is all on one line (it's hard to tell if it's just wrapping in the forum or if the destination ip is on a seperate line). You can use multiple lines for the command, they just need to be "\" escaped.

2. Try without the -d 192.168.0.45

Checkout the netfilter howto for destination NAT and see if it turns on any light bulbs: http://www.netfilter.org/documentation/HOWTO//NAT-HOWTO-6.html#ss6.2

If none of this works out. Post your kernel options for netfilter and we'll see from there.

----------

## Seather

Great, I finally got it working, with help from this site: http://kreiger.linuxgods.com/kiki/?Port+forwarding+with+netfilter

However it's not working perfectly, and there are some other issues that still needs to be addressed, but, getting there! This is what it looks like now:

```

#!/sbin/runscript

IPTABLES=/sbin/iptables

EXTIF="ppp0"

INTIF="eth0"

IFCONFIG=/sbin/ifconfig

LSMOD=/sbin/lsmod

DEPMOD=/sbin/depmod

MODPROBE=/sbin/modprobe

GREP=/bin/grep

AWK=/bin/awk

SED=/bin/sed

WEBSERVER="192.168.0.254"

start() {

        ebegin "Loading Firewall"

printf "\nExternal Interface:  $EXTIF\nInternal Interface:  $INTIF\n\n"

#CRITICAL:  Enable IP forwarding since it is disabled by default since

#

echo "Enabling forwarding.."

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

# Dynamic IP users:

#

#   If you get your IP address dynamically from SLIP, PPP, or DHCP, 

#   enable this following option.  This enables dynamic-address hacking

#   which makes the life with Diald and similar programs much easier.

#

echo "Enabling DynamicAddr.."

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

# Set external IP Var

INTIP="192.168.0.45"

echo "Internal ip is $INTIP"

#Clearing any previous configuration

#

#  Unless specified, the defaults for INPUT and OUTPUT is ACCEPT

#    The default for FORWARD is DROP (REJECT is not a valid policy)

#

echo "Clearing any existing rules and setting default policy.."

$IPTABLES -P INPUT ACCEPT

$IPTABLES -F INPUT 

$IPTABLES -P OUTPUT ACCEPT

$IPTABLES -F OUTPUT 

$IPTABLES -P FORWARD ACCEPT

$IPTABLES -F FORWARD 

$IPTABLES -t nat -F

echo "FWD: Allow all connections OUT and only existing and related ones IN"

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A FORWARD -i $INTIF -o $EXTIF -j ACCEPT

$IPTABLES -A FORWARD -j LOG

echo "Enabling SNAT (MASQUERADE) functionality on $EXTIF"

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

# This is for forwarding http requests to the webserver.

# It's still kind off dodgy, but it works at the moment so thats good.

#

echo "Forwarding all http requests to $WEBSERVER"

# Forward packets coming in from the outside

iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $WEBSERVER:80

# Allow forwarded packets

iptables -A FORWARD -p tcp --dport 80 -d $WEBSERVER -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# Make responses on the internal network go through the firewall

iptables -t nat -A POSTROUTING -p tcp -d $WEBSERVER --dport 80 -j SNAT --to-source $INTIP

printf "\n"

        eend 0

}

stop() {

        ebegin "Clearing Firewall"

        iptables -F

        eend 0

}

```

Now, it forwards all connections coming from the lan to eth0/192.168.0.45 just great and dandy, but, stuff coming over the ppp0 dialup connection doesn't work yet. That's kind of critical.

Secondly, The 'FORWARD' policy used to be drop, and not accept like it is now. However the moment I change it back to drop, the forwarding doesn't work anymore, and I have tried numerous rules to make those connections go through, but it still doesn't work. Anyone can suggest a try?

Thanks Folks!

----------

## Beekster

I have found this script generator to be very useful.  See what it generates, and compare.

----------

## Seather

errrrr :/ that firewall generator site won't help me at all, just for the record...

----------

## Beekster

It's options expand as you say what you need...??  I thought it could/would provide a working script for you.  Oh well.   :Sad: 

----------

## sschlueter

 *Seather wrote:*   

> 
> 
> # This is for forwarding http requests to the webserver.
> 
> # It's still kind off dodgy, but it works at the moment so thats good.
> ...

 

Mmh... you don't need DNAT and SNAT. Responses will be handled correctly when you use the DNAT command.

----------

## Seather

Okay...It's *still* not working and I've read up everything I could find on iptables/netfilter by now. It is changed though. But it still doesn't forward http requests at all.

The webserver's gateway is set to the firewall box's ip, and the webserver isn't running any firewall or nat software at all.

This is what it looks like at the moment:

```

#!/sbin/runscript

IPTABLES=/sbin/iptables

EXTIF="ppp0"

INTIF="eth0"

IFCONFIG=/sbin/ifconfig

LSMOD=/sbin/lsmod

DEPMOD=/sbin/depmod

MODPROBE=/sbin/modprobe

GREP=/bin/grep

AWK=/bin/awk

SED=/bin/sed

WEBSERVER="192.168.0.57"

# Flush tables and set policies

echo "Clearing any existing rules and setting default policy.."

$IPTABLES -t filter -P INPUT ACCEPT

$IPTABLES -t filter -F INPUT

$IPTABLES -t filter -P OUTPUT ACCEPT

$IPTABLES -t filter -F OUTPUT

$IPTABLES -t filter -P FORWARD ACCEPT

$IPTABLES -t filter -F FORWARD

$IPTABLES -t nat -P PREROUTING ACCEPT

$IPTABLES -t nat -F PREROUTING

$IPTABLES -t nat -P POSTROUTING ACCEPT

$IPTABLES -t nat -F POSTROUTING

$IPTABLES -t nat -P OUTPUT ACCEPT

$IPTABLES -t nat -F OUTPUT

start() {

        ebegin "Loading Firewall"

# Enable IP forwarding

echo "Enabling Forwarding.."

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

# Enable Dynamic IP

echo "Enabling DynamicAddr.."

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

# Set external IP

EXTON=`ifconfig | grep $EXTIF`

if [ $? -eq 0 ]

then

   EXTIP=`ifconfig $EXTIF | grep inet | cut -d : -f 2 | cut -d ' ' -f 1`

   echo "External interface is $EXTIF with ip address: $EXTIP"

else

   echo "External interface is $EXTIF"

fi

# Set internal IP

INTIP=`ifconfig $INTIF | grep inet | cut -d : -f 2 | cut -d ' ' -f 1`

echo "Internal interface is $INTIF with ip address: $INTIP"

# Set up gateway/routing

echo "Enabling SNAT (MASQUERADE) functionality on $EXTIF"

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

# Port forward http requests to the web server

echo "Set up http forwarding to $WEBSERVER"

$IPTABLES -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $WEBSERVER:80

        eend 0

}

stop() {

        ebegin "Clearing Firewall"

        eend 0

}

```

PLEASE someone help? Why doesn't it forward http requests?

----------

