# Are this iptable rules safe and sound?

## pa1983

Hello!

My English is not the best I'm afraid but I hope its not to much of a problem.

I had my firs linux router back in 1999-2000 something and a friend wrote a basic but working iptable script for me. I have built on that script ever sens but I feel like I would want something new.

I have been reading some guides on netfilter home page and other links I received from gentoo irc channel and well but a new script together.

I recently added a wlan card to my gentoo router and done some fixes so this is a overhaul I waned to do fore some time.

I have eth0 connected to my ADSL2+ modem and eth1 is connected to my switch and wlan0 runs as an access point using hostapd and have MAC filtering and WPA encryption for security.

So basically I want to the router to route, forward and well block incoming traffic to ports by default unless other is specified and do some port forwarding. I have that functionality in my old script but its become a bit messy I think and I have probably messed it up a bit over the years I suspect. I was told to prioritize safety on the WAN side and not bother with security on the LAN so much and sens its my privet home network it makes sens.

I ended up using the ! "NOT"option a lot I dont know if its good in all seniors but it made the script the most compact but it might not be secure? 

I'm not a network expert by any means so thats why I'm not afraid of what I have been thinking of its what I haven't been thinking of.

And It seems to be hard to find expertise on iptables.

eth1 and wlan0 runs on two different subnets also but that seems to work fine. I have tested the script and seems to do what I want but well I'm not sure if its good and secure or just crap.

Maybe I have been to generous with the allowed  traffic on the LAN side etc compromising security in some way on the WAN side?

Well any way here is the script.

```
#!/bin/sh

# Network interfaces

WAN="eth0"

LAN="eth1"

WLAN="wlan0"

#make sure ssh don't get disconnected

iptables -P INPUT ACCEPT

# Flush old rules

iptables -F

iptables -X

iptables -t nat -F

# NATar and enables ipv4 forwarding and packet filter

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

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

echo 1 > /proc/sys/net/ipv4/conf/$WAN/rp_filter

# Set access for localhost

iptables -A INPUT -i lo -j ACCEPT

# Accept packets belonging to established and related connections

iptables -A INPUT -m state --state ESTABLISHED,RELATED -i $WAN -j ACCEPT

# Accept packages on LAN and WLAN

iptables -A INPUT ! -i $WAN -j ACCEPT

# Open ports on WAN

iptables -A INPUT -i $WAN -p UDP --dport 88 -j ACCEPT #xbox360

iptables -A INPUT -i $WAN -p UDP --dport 3074 -j ACCEPT #xbox360

iptables -A INPUT -i $WAN -p TCP --dport 3074 -j ACCEPT #xbox360

# Forward packages between interfaces

iptables -A FORWARD ! -i $WAN ! -o $WAN -j ACCEPT

iptables -A FORWARD -i $WAN ! -o $WAN -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD ! -i $WAN -o $WAN -j ACCEPT

# Forwarding ports from WAN

iptables -A PREROUTING -t nat -p udp -i $WAN --dport 88 -j DNAT --to 192.168.0.99 #xbox360

iptables -A PREROUTING -t nat -p udp -i $WAN --dport 3074 -j DNAT --to 192.168.0.99 #xbox360

iptables -A PREROUTING -t nat -p tcp -i $WAN --dport 3074 -j DNAT --to 192.168.0.99 #xbox360

# Default fallback rules

iptables -P INPUT DROP

iptables -P FORWARD DROP

iptables -P OUTPUT ACCEPT
```

----------

## Jimini

 *Quote:*   

> 
> 
> ```
> iptables -P INPUT ACCEPT
> ```
> ...

 

This policy allows all incoming traffic, if it is not explicitly forbidden. Do you really want that? It would be better to forbid all traffic (iptables -P INPUT DROP) and allow traffic for single ports and/or ip-addresses.

 *Quote:*   

> 
> 
> ```
> iptables -F
> 
> ...

 

"iptables -X" deletes one user-defined chain. In your case, you can delete this line - you only need it, if you define a custom chain.

 *Quote:*   

> 
> 
> ```
> echo 1 > /proc/sys/net/ipv4/conf/$WAN/rp_filter
> ```
> ...

 

I would replace "$WAN" with "all" - or use this:

```
for FILTER in /proc/sys/net/ipv4/conf/*/rp_filter; do

 echo 1 > $FILTER

done
```

 *Quote:*   

> 
> 
> ```
> iptables -A INPUT -i lo -j ACCEPT
> ```
> ...

 

Then you should allow outgoing local traffic, too:

```
iptables -A OUTPUT -o lo -j ACCEPT
```

 *Quote:*   

> 
> 
> ```
> iptables -A FORWARD ! -i $WAN ! -o $WAN -j ACCEPT
> 
> ...

 

Hm, what are you trying to do here? I can't figure this out - but the first and the last line are identic.

 *Quote:*   

> 
> 
> ```
> iptables -A PREROUTING -t nat -p udp -i $WAN --dport 88 -j DNAT --to 192.168.0.99 #xbox360
> 
> ...

 

As far as I know, it should be "--to-destination 192.168.00.99"

 *Quote:*   

> 
> 
> ```
> iptables -P INPUT DROP
> 
> ...

 

Correct. But you should take a look at the beginning of your rules - there you defined a policy, which allowed all incoming traffic.

Regarding filtering the traffic from LAN to WAN, I always allow traffic from the "inside" to reach the "outside", this should be secure enough (except you  want to control the traffic from your network really strictly).

For testing purposes, you could run a port scan, like this one. Or you use something like nessus or nmap from the "outside" to scan your firewall for open ports.

Best regards,

Jimini

----------

## pa1983

```
iptables -P INPUT ACCEPT
```

I put that in the beginning suggested by a guide. Any way it was to make sure ssh if you ran the script over ssh that you didn't got disconnected.

```
iptables -P INPUT DROP
```

From what I understood putting this after the first one that accepted input should put the INPUT policy to DROP making the first on invalid thats why I put it in the bottom after all input rules for the LAN and WLAN was in place.

This was just to make sure on didn't get disconnected over ssh when running the script during testing. 

But I don't know if thats a good idea but I could remove that to I suppose. 

```
iptables -X
```

I put that there because my old firewall scrip have a user defined chain called firewall so that was to make sure I got rid of it nothing else. Just makes it easier during testing but I could clean tat up once I know my new script is good yes.

```
echo 1 > /proc/sys/net/ipv4/conf/$WAN/rp_filter
```

I wasn't sure about that so will fix that.

```
iptables -A FORWARD ! -i $WAN ! -o $WAN -j ACCEPT

iptables -A FORWARD -i $WAN ! -o $WAN -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD ! -i $WAN -o $WAN -j ACCEPT
```

The first line allows forwarding from any interface except eth0 to any interface except eth0 because I used "!" (NOT) before -i and -o on both I didn't do that on the last line. Basically was meant to allow forwarding between eth1 and wlan0 so the LAN and WLAN computers can talk to etch other.

The second line allows forwarding from eth0 to eth1 and wlan0 or any other interface but this are the once I have and I added --state ESTABLISHED,RELATED for added security as recommended by most guides.

The last line allows any interface except eth0 to forward to eth0 so it allows eth1 and wlan0 to forward to eth0 basically. I only have "!" on the -i not the -o thats the difference from the first line.

I don't know if the way I did this is good at all but I was recommended to keep things compact and efficient so this was the best I could come up with but I'm not that good at this thats why I need some input from other people.

```
iptables -A PREROUTING -t nat -p udp -i $WAN --dport 88 -j DNAT --to 192.168.0.99 #xbox360

iptables -A PREROUTING -t nat -p udp -i $WAN --dport 3074 -j DNAT --to 192.168.0.99 #xbox360

iptables -A PREROUTING -t nat -p tcp -i $WAN --dport 3074 -j DNAT --to 192.168.0.99 #xbox360

```

My old script used --to also and the guide I was using but I checked the man pages and --to-destination exist and seems be specific for IP addresses and Ports so I could change to that that makes sens.

```
iptables -A OUTPUT -o lo -j ACCEPT
```

Good you mentioned that. I was wondering the same thing. I have read both but I wasn't sure what was correct. I'm not sure but shouldn't "iptables -P OUTPUT ACCEPT" in the bottom of the script allow this to or is that an exception?

Btw how would you suggest one best allows internal traffic to reach the outside?

Thanks for the input it gave me something to think about.

----------

## Jimini

 *Quote:*   

> 
> 
> ```
> iptables -P INPUT ACCEPT
> ```
> ...

 

Okay, that's how I do it, too. But it doesn't matter where you put your policies - if a packet arrives, it goes through all your chains and rules. If none of your rules matches, it's handled as set in the policy. 

Example:

[...]

iptables -P INPUT DROP

iptables -P OUTPUT DROP

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

[...]

Now you try to connect to the SSH server on your firewall. Although the default policy is "DROP", the packet can reach the deamon, because the rule in the last line allows this. The SSH daemon can answer, because all packets belonging to an established connection or which are related which an established connection are allowed. 

Now you try to connect to port 80 on your firewall. This packet will be dropped, because there is no rule which allows incoming traffic on port 80 - and the policy still says "DROP that".

 *Quote:*   

> 
> 
> ```
> iptables -A FORWARD ! -i $WAN ! -o $WAN -j ACCEPT
> 
> ...

 

Ah okay, now I get it. I've never bridged networks yet, so I'm not experienced with this routing-procedure.

 *Quote:*   

> 
> 
> ```
> iptables -A OUTPUT -o lo -j ACCEPT
> ```
> ...

 

If your OUTPUT-policy allows all outgoing traffic, which is not forbidden by your rules, then of course you don't have to allow local outgoing traffic. But this is very insecure. It is always better to forbid all traffic and to allow it for single ports and/or addresses. So your policy should be like "iptables -P OUTPUT DROP", afterwards, you allow local traffic

```
iptables -A INPUT -i lo -j ACCEPT

iptables -A OUTPUT -o lo -j ACCEPT
```

 *Quote:*   

> Btw how would you suggest one best allows internal traffic to reach the outside?

 

This is how this section in my firewall looks like:

```
### default policy: drop everything

iptables -P INPUT DROP

iptables -P OUTPUT DROP

iptables -P FORWARD DROP

### default policy: first nat everything, then drop/forward/allow it in single cases

iptables -t nat -P PREROUTING ACCEPT

iptables -t nat -P POSTROUTING ACCEPT

iptables -t nat -P OUTPUT ACCEPT

### accept connection attempts from the inside

iptables -A FORWARD -s $intern -i $lan -o $wan -j ACCEPT

iptables -A INPUT -s $intern -i $lan -j ACCEPT (you don't need this rule if your firewall machine is just a gateway and doesn't offer any services to the network)

### allow lokal traffic

iptables -A INPUT -i lo -j ACCEPT

iptables -A OUTPUT -o lo -j ACCEPT

### accept all traffic belonging to an existing connection

iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

### mask all traffic from lan to wan

iptables -t nat -A POSTROUTING -o $wan -j MASQUERADE

iptables -t nat -A POSTROUTING -o $wan -j SNAT --to-source $external_ip
```

 *Quote:*   

> Thanks for the input it gave me something to think about.

 

You're welcome :)

Best regards,

Jimini

----------

## d2_racing

Hi, are you sure that you need to open them ?

```

iptables -A INPUT -i $WAN -p UDP --dport 88 -j ACCEPT #xbox360

iptables -A INPUT -i $WAN -p UDP --dport 3074 -j ACCEPT #xbox360

iptables -A INPUT -i $WAN -p TCP --dport 3074 -j ACCEPT #xbox360 

```

I think that it's your XBOX that will open theses ports.

So that rule will be only required : 

```
iptables -A INPUT -m state --state ESTABLISHED,RELATED -i $WAN -j ACCEPT 
```

Finally, if you really need them, you can use this :

```

iptables -A INPUT -i $WAN -p UDP --dport 88 -j ACCEPT #xbox360

iptables -A INPUT -i $WAN -p all --dport 3074 -j ACCEPT #xbox360

```

----------

## Hu

 *pa1983 wrote:*   

> Well any way here is the script.

 Whenever possible, avoid using a shell script to configure iptables.  Instead, use a saved rules file, which you can load atomically.  The Gentoo initscripts handle this for you, so once you have configured the firewall to your liking, you should add iptables to the default runlevel and execute /etc/init.d/iptables save to save the active rules so they are used on next reboot.

 *pa1983 wrote:*   

> 
> 
> ```
> #make sure ssh don't get disconnected
> 
> ...

 This is unnecessary.  Your script has no ability to exit early, so barring explicit user interruption, it will always run to the end and set the policy to DROP.  Additionally, it is unsafe to make the policy be ACCEPT when your table is empty, since that could allow an incoming connection to be established while the rules are being added.

 *pa1983 wrote:*   

> 
> 
> ```
> iptables -A FORWARD ! -i $WAN ! -o $WAN -j ACCEPT
> 
> ...

 Specifying these rules together is unnecessary.  By simplification, these could be reduced to a single rule which has no qualifier on the output interface.

 *pa1983 wrote:*   

> 
> 
> ```
> iptables -A PREROUTING -t nat -p udp -i $WAN --dport 88 -j DNAT --to 192.168.0.99 #xbox360
> 
> ...

 I do not think these rules will work in isolation.  Since they are DNAT rules, they are meant to allow an unsolicited incoming connection to be mapped to an internal machine.  However, you have no rule in FORWARD which would allow the packets mapped by these DNAT rules to reach their destination.

 *Jimini wrote:*   

> Ah okay, now I get it. I've never bridged networks yet, so I'm not experienced with this routing-procedure.

 Bridging is an entirely different type of network construct.  :Smile: 

----------

## Jimini

 *Hu wrote:*   

> Whenever possible, avoid using a shell script to configure iptables.

 

Why? Because of the possible security vulnerability through the access rights of the script?

 *Hu wrote:*   

>  *Jimini wrote:*   Ah okay, now I get it. I've never bridged networks yet, so I'm not experienced with this routing-procedure. Bridging is an entirely different type of network construct. :)

 

You got me ;)

Best regards,

Jimini

----------

## pa1983

It's a lot to think about. The more I learn the more confused I get about the howl thing  :Very Happy: 

Need to think all this over and see what I can come up with.

----------

## Hu

 *Jimini wrote:*   

>  *Hu wrote:*   Whenever possible, avoid using a shell script to configure iptables. Why? Because of the possible security vulnerability through the access rights of the script?

 Loading iptables through a shell script has two problems.  First, the rules are inserted one at a time, so incoming traffic could be processed by a half-loaded firewall.  The results would likely not be what was intended.  Second, most people who write a shell script to load their firewall rules provide no error checking, so if any one rule fails to load, the script ignores it and continues adding more rules.  Again, the result is an improperly loaded firewall that is likely not behaving as the operator intended.  The proper fix to both problems is to load the rules atomically through iptables-restore, which is what the Gentoo initscript does for you.  As an added safety precaution, you can mark that starting the rules is a prerequisite to starting the network, so that a failure to load the rules prevents the interface from coming up on its own.

----------

