# [SOLVED] Please check my firewall script

## Re-JeeP

Hi!

I am for the first time trying to set up a firewall with iptables and I am also for the first time trying to create a bash-script.

Could someone please give it a look and give comments on it?

Also. It doesn't work. Gives me: -bash: ./firewall: /sbin/runscript^M: bad interpreter: No such file or directory

```
#!/sbin/runscript

IPTABLES=/sbin/iptables

depend()

{

   need net

   after iptables

}

start()

{

   ebegin "Starting firewall"

   # Drop all incomming and forwarding traffic. Accept all outgoing traffic.

   $IPTABLES -P INPUT DROP

   $IPTABLES -P FORWARD DROP

   $IPTABLES -P OUTPUT ACCEPT

   flush

   # Drop any attempt to ping this computer.

   $IPTABLES -A INPUT -p icmp -j DROP

   # Drop any packet that is not in the state table.

   $IPTABLES -A INPUT -m state --state INVALID -j DROP

   # Accept packets that originate from an already established connection.

   $IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

   # Accept SSH

   $IPTABLES -A INPUT -p tcp --destination-port 22 -j ACCEPT

   # Accept HTTP

   $IPTABLES -A INPUT -p tcp --destination-port 80 -j ACCEPT

   sleep 2

   eend $?

}

stop()

{

   ebegin "Stopping firewall"

   flush

   # Accepts all

   $IPTABLES -P FORWARD ACCEPT

   $IPTABLES -P INPUT   ACCEPT

   $IPTABLES -P OUTPUT  ACCEPT

   sleep 2

   eend $?

}

restart()

{

   stop; start

}

flush()

{

   # Flushes all rules.

   $IPTABLES -F

   $IPTABLES -t nat -F

   $IPTABLES -X

}
```

----------

## frostschutz

Are you using Windows style CRLF line delimiters? That would explain the ^M in your error message. Also, there should be no need to write your own init script for iptables only, as the default iptables script already is capable of saving and restoring iptables rules. You create rules once, then run /etc/init.d/iptables save, and in the future your saved iptables rules will be restored automatically. iptables won't even start without such a saved rules table, so I don't know if your 'after iptables' requirement will ever be met. It doesn't make sense since iptables only sets iptables rules, only to be flushed by your script afterwards.

----------

## Re-JeeP

 *frostschutz wrote:*   

> Are you using Windows style CRLF line delimiters? That would explain the ^M in your error message.

 

I solved that with dos2unix.

 *frostschutz wrote:*   

> Also, there should be no need to write your own init script for iptables only, as the default iptables script already is capable of saving and restoring iptables rules. You create rules once, then run /etc/init.d/iptables save, and in the future your saved iptables rules will be restored automatically. iptables won't even start without such a saved rules table, so I don't know if your 'after iptables' requirement will ever be met. It doesn't make sense since iptables only sets iptables rules, only to be flushed by your script afterwards.

 

Ok!

Well, your solution sounds better than mine...   :Very Happy: 

Since it's my first time setting up iptables. Could you give me some comments on my rules? Do they seem ok? Do they block all incomming traffic except ssh and http?

```
# Drop all incomming and forwarding traffic. Accept all outgoing traffic.

$IPTABLES -P INPUT DROP

$IPTABLES -P FORWARD DROP

$IPTABLES -P OUTPUT ACCEPT

# Flushes the tables.

$IPTABLES -F

$IPTABLES -t nat -F

$IPTABLES -X

# Drop any attempt to ping this computer.

$IPTABLES -A INPUT -p icmp -j DROP

# Drop any packet that is not in the state table.

$IPTABLES -A INPUT -m state --state INVALID -j DROP

# Accept packets that originate from an already established connection.

$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Accepted incomming protocolls. SSH and HTTP are allowed.

$IPTABLES -A INPUT -p tcp --destination-port 22 -j ACCEPT

$IPTABLES -A INPUT -p tcp --destination-port 80 -j ACCEPT
```

----------

## frostschutz

Well, first of all, since your default policy is DROP anyway, you can remove all rules that DROP unless they match packets that would also be matched by one of your ACCEPT rules later on. Other than that, yes, they should drop everything except for already established connections / related packets and packets that go to port 22/80. However, be aware that if you don't want to accept connections to certain ports from the internet, it's best to not provide services on these ports in the first place.

I use iptables more for classifying traffic (QoS) than actually firewalling / dropping traffic, so I don't know wether you're dropping too much or not.

----------

## mv

```
# Drop all incomming and forwarding traffic. [...]

$IPTABLES -P INPUT DROP
```

As a rule, it is better to REJECT than to DROP: Reasonable programs will then not retry. (You might make an exception for the ports 135 137:139 445 which are typically used by worms or stupid window programs which retry anyway).

To avoid DOS you can REJECT until a certain rate-limit is reached and only then start to DROP.

```
# Drop any attempt to ping this computer.

$IPTABLES -A INPUT -p icmp -j DROP
```

icmp is not only ping. It is not a good idea to drop all icmp; e.g. you will probably want to get informed about destination-unreachable source-quench time-exceeded parameter-problem. I would even suggest to accept echo-reply echo-request (i.e. ping) on a rate-limited basis. If you really want to avoid replying to ping you perhaps better configure this in your kernel with 

```
echo 1 >/proc/sys/net/ipv4/icmp_echo_ignor_all
```

```
$IPTABLES -A INPUT -p tcp --destination-port 22 -j ACCEPT
```

I would also use a rate-limit here (with the recent module) to limit the bandwidth used by dictionary attacks. Alternatively, you might use a port-knocking solution.

```
$IPTABLES -A INPUT -p tcp --destination-port 80 -j ACCEPT
```

Are you really sure that you want to offer your web-server to everybody? Otherwise, you might think about tunelling it through ssh.

----------

## Re-JeeP

 *frostschutz wrote:*   

> Well, first of all, since your default policy is DROP anyway, you can remove all rules that DROP unless they match packets that would also be matched by one of your ACCEPT rules later on.

 

Do you mean with this that I can remove

```
$IPTABLES -A INPUT -m state --state INVALID -j DROP
```

because I have

```
$IPTABLES -P INPUT DROP
```

?

 *frostschutz wrote:*   

> Other than that, yes, they should drop everything except for already established connections / related packets and packets that go to port 22/80. However, be aware that if you don't want to accept connections to certain ports from the internet, it's best to not provide services on these ports in the first place.

 

Ok, So if I dont have any service responding to a port it wont do much harm?

 *mv wrote:*   

> 
> 
> ```
> # Drop all incomming and forwarding traffic. [...]
> 
> ...

 

Ahh... With "135 137:139 445". Do you mean the ports 135, 137, 138, 139 and 445?

 *mv wrote:*   

> 
> 
> ```
> # Drop any attempt to ping this computer.
> 
> ...

 

Didn't know that... I don't have any good reason to block ping so I'll leave it open then...   :Cool: 

 *mv wrote:*   

> 
> 
> ```
> $IPTABLES -A INPUT -p tcp --destination-port 80 -j ACCEPT
> ```
> ...

 

Well... Now that I think about it... I only want to provide the webserver in my home network...

I have one question about this line in my rules:

```
$IPTABLES -t nat -F
```

I read some about NAT and from what I understod this is often used if you are using the computer as a router/firewall. Am I right?

So if I don't have NAT avaliable in my kernel. Is there really any reason for me to have these lines in my rules?

```
$IPTABLES -P FORWARD REJECT 

$IPTABLES -t nat -F
```

----------

## desultory

Moved from Portage & Programming to Networking & Security.

----------

## mv

 *Re-JeeP wrote:*   

> Ahh... With "135 137:139 445". Do you mean the ports 135, 137, 138, 139 and 445?

 

Yes.

 *Quote:*   

> I don't have any good reason to block ping so I'll leave it open then...  

 

But some of icmp might also be dangerous, so completely accepting icmp is not a good idea either. You might want to have a look at the rules generated by some simple firewall scripts, e.g. of firewall.zip from http://www.mathematik.uni-wuerzburg.de/~vaeth/download/index.html

 *Quote:*   

> I only want to provide the webserver in my home network...

 

So you should bind it also to the source address range of your local network (and - depending on your topology - also to the appropriate interface to avoid spoofing).

 *Quote:*   

> So if I don't have NAT avaliable in my kernel. Is there really any reason for me to have these lines in my rules?
> 
> ```
> $IPTABLES -P FORWARD REJECT 
> 
> ...

 

If you really don't have NAT in your kernel, you also won't have a corresponding table, and the second command would even give an error. The first command is probably not necessary but won't hurt either.

----------

## Re-JeeP

 *mv wrote:*   

>  *Quote:*   I don't have any good reason to block ping so I'll leave it open then...   
> 
> But some of icmp might also be dangerous, so completely accepting icmp is not a good idea either. You might want to have a look at the rules generated by some simple firewall scripts, e.g. of firewall.zip from http://www.mathematik.uni-wuerzburg.de/~vaeth/download/index.html

 

Thanks!   :Very Happy: 

I have some trouble using emerge. Can that be because I don't have this rule?

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

I tried to add it but I get the message:

 *Quote:*   

> iptables: No chain/target/match by that name

 

I tried to add "state" match support in the kernel but the same message appears...

----------

## mv

 *Re-JeeP wrote:*   

> I tried to add it but I get the message:
> 
>  *Quote:*   iptables: No chain/target/match by that name 
> 
> I tried to add "state" match support in the kernel but the same message appears...

 

This message means that something is missing from your kernel. Besides "state" match support you also need to have netfilter connection tracking support and probably connection tracking support for certain protocols. The setting differs slightly in 2.6.18/19/20 (in some kernel versions you have to enable the options in core netfilter *and* in netfilter IP).

----------

## Re-JeeP

 *mv wrote:*   

>  *Re-JeeP wrote:*   I tried to add it but I get the message:
> 
>  *Quote:*   iptables: No chain/target/match by that name 
> 
> I tried to add "state" match support in the kernel but the same message appears... 
> ...

 

netfilter connection tracking did the job, thanks!   :Wink: 

I now have my script (below) finished and it works great:

```
#!/bin/bash

IPTABLES=/sbin/iptables

# Clear and flush tables.

$IPTABLES -F

$IPTABLES -Z

# Accept all outgoing traffic.

$IPTABLES -P OUTPUT ACCEPT

# Accept packets that originate from an already established connection.

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

# Drop traffic on ports: 135, 137, 138, 139 and 445

$IPTABLES -A INPUT -p tcp --destination-port 135 -j DROP

$IPTABLES -A INPUT -p tcp --destination-port 137:139 -j DROP

$IPTABLES -A INPUT -p tcp --destination-port 445 -j DROP

# Accept SSH.

$IPTABLES -A INPUT -p tcp --destination-port 22 -j ACCEPT

# Reject all incomming and forwarding traffic.

$IPTABLES -A INPUT -j REJECT

$IPTABLES -A FORWARD -j REJECT
```

frostschutz said in his post that when I was finished with my rules I should run it as a script and then run /etc/init.d/iptables save.

I do so and it says that it has saved my rules. But when I restart the computer iptables -L shows me nothing...

----------

## frostschutz

Is iptables started? Check rc-update show wether it lists iptables in boot / default runlevel. If it does not, start iptables manually (/etc/init.d/iptables start), and check then wether your rules are there or not. If they are, add iptables to a runlevel 'rc-update add iptables boot' or similar.

----------

## Re-JeeP

 *frostschutz wrote:*   

> Is iptables started? Check rc-update show wether it lists iptables in boot / default runlevel. If it does not, start iptables manually (/etc/init.d/iptables start), and check then wether your rules are there or not. If they are, add iptables to a runlevel 'rc-update add iptables boot' or similar.

 

Ahh... How stupid of me! You are right.

Thanks very much both for your help!

----------

