# iptables commands wont work as a script [SOLVED]

## Keiko

Hia,

I've managed to set my iptables firewall up, by typing in each rule, line by line and then using iptables-save > /etc/init.d/filename to save the file, i then edited this file and added a 'sating' and 'edning' section, which i copied from another script, effectively turning this into a script, which could be run by placing an entry in /etc/conf.d/local.start.

Now this works fine, i've rebooted several times, and it starts automatically and works as i like, i can even add more rules to the scrip, by typing a command, and the re-saving, with the above save command.

The problem is that, this file isn't very neat, and is disguised with junk put in by  the iptables-save command, which makes it difficult for me to improove and work with, and well i just dont like it, so i  created a new script, i copied this file, and then re-wrote all of the commands, only real difference is that i annotated it with notes about what i had done, to aid debugs and improovements.

Anyway getting to the point, it doesn't work, i changed my entry in /etc/conf.d/local.start to run this to test it, and it didn't seem to work, so i used coppied the rules into a new file and used iptables-restore/etc/init.d/newfilename but iptables spat out errors indicating a certain line failed, but when i checked that line, it was a normal iptables command, what i had used earlier, i deleted some of these to test it again, and it spat out more lines that had failed, and upon checking a few more, one was even just an empty line.

I'm struggling to figure out what could be wrong, can someone please help me.

Thank you, Keiko.Last edited by Keiko on Wed Mar 08, 2006 1:39 pm; edited 1 time in total

----------

## m8ryx

check the lines preceding the lines that error.  Can you post an example of an erroring line and any lines that precede it?

----------

## Keiko

Hia,

I've just tried again to use iptables-restore to test my new rules (without the script sections) with the following command: "iptables-restore < filename"

and i recieved: "iptables-restore: line 26 failed

Here is lines 1 to 30 of my rules:

==============================

#----------------------------------- This Script -----------------------------------------------------#

#

# This is my iptables firewall script, it contains the rules that will correctly configure iptables.

#

# This script was created from a very good guide on "http://www.pettingers.org/code/firewall.html" and with

# support and help from various people.

#

# Created on 06/03/2006 by Keiko.

#

#

# If you want this script to automatically setup iptables when you boot your computer (Gentoo), ensure it is

# named firewall-rules and place it into your /etc/init.d/ directory. 

# Now using your preffered editor open /etc/conf.d/local.start and add the following line (without quotes)

# "/etc/init.d/firewall-rules start" these rules will then be passed to iptables upon boot.

# To test that the rules have been passed to iptables correctly as super user (root) type the following in a

# terminal (without quotes) "iptables -L" this will list the rules and chains that iptables is using.

#

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

# The defaul policy of the INPUT chain is now changed, to allo all packets to enter, this is only temporary

# however and will be changed later.

iptables -P INPUT ACCEPT

# We will now flush (delete) any rules for the chains, which could affect the new rules we are going to implement.

	iptables -F INPUT

=========================

.

I've embolded the line thats producing the error (26), it seems fine to me.

 - I've just commented out that line, and tried again, and it still says line 26 failed... strange.

[edit] I've just tried deleting the tab space, preceeding the rule on line 26 and it still says line 26 failed.

Thanks, Keiko.

----------

## m8ryx

what you're are trying to do should just be a normal shell script...try not running it through iptables-restore

----------

## Keiko

Hia,

Yes i know, its written as a script, i've just found a posting bin, so heres my current versions of it http://rafb.net/paste/results/AuXyOt57.txt

The trouble is, this doesn't work, either when i try to run it from local.start or just run itself, the rules arn't passed or iptables configuration doesn't change, i only used iptables-restore to try and troubleshoot it but it didn't work.

Keiko.

----------

## m8ryx

can you post what the output of running your script as root is (from command line).  Please paste in the command you use to call the script, as well as any output.  Also, iptables -L would be handy.

----------

## Keiko

Hia,

My intent is to run the script with the following entry in /etc/conf.d/local.start, "/etc/init.d/new-iptables-script start" this has worked with my other script, but for now i'll initiate the script myself, to save rebooting,

i do this as root with: /etc/init.d/new-iptables-script start

This retuns no output at all.

I then ran iptables-save, which then showed the output of iptabels -L automatically.

To check if the script was loaded, and so far it hasn't worked, to test i changed my input policy from DROP to ACCEPT so i can compare the output, as i know that the script, or rule i'm running know shoe that the default policy for INPUT is DROP.

Iptables -L as generated the following output, if the script as worked, then i guess my INPUT chain should say ACCEPT, problem is that it says ACCEPT in one area and DROP in another, can you help me figure out if it has worked please...

------------------------------------------------------------------

# Generated by iptables-save v1.3.4 on Tue Mar  7 13:56:36 2006

*nat

:PREROUTING ACCEPT [10357:843297]

:POSTROUTING ACCEPT [46735:4812065]

:OUTPUT ACCEPT [46735:4812065]

COMMIT

# Completed on Tue Mar  7 13:56:36 2006

# Generated by iptables-save v1.3.4 on Tue Mar  7 13:56:36 2006

*mangle

:PREROUTING ACCEPT [679214:604085884]

:INPUT ACCEPT [679214:604085884]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [602067:301696394]

:POSTROUTING ACCEPT [606406:302379610]

COMMIT

# Completed on Tue Mar  7 13:56:36 2006

# Generated by iptables-save v1.3.4 on Tue Mar  7 13:56:36 2006

*filter

:INPUT DROP [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [602067:301696394]

:BLACKLIST - [0:0]

:LOGDROP - [0:0]

:SPAM - [0:0]

:THRU - [0:0]

:WEB - [0:0]

-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT 

-A INPUT -i lo -j ACCEPT 

-A INPUT -i eth0 -p tcp -m tcp --dport 25 -j SPAM 

-A INPUT -i eth0 -p tcp -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j WEB 

-A INPUT -j BLACKLIST 

-A INPUT -j THRU 

-A INPUT -m limit --limit 1/sec -j LOG --log-prefix "drop_packet" --log-level 7 

-A INPUT -j DROP 

-A BLACKLIST -s 81.156.126.41 

-A BLACKLIST -s 213.145.191.238 -j LOGDROP 

-A BLACKLIST -s 69.93.81.10 -j LOGDROP 

-A BLACKLIST -s 165.228.11.218 

-A BLACKLIST -s 165.228.11.218 -j LOGDROP 

-A LOGDROP -p tcp -m tcp --dport 25 -m limit --limit 1/sec -j LOG --log-prefix "spam_blacklist" --log-level 7 

-A LOGDROP -p tcp -m tcp --dport 80 -m limit --limit 1/sec -j LOG --log-prefix "web_blacklist" --log-level 7 

-A LOGDROP -p tcp -m tcp --dport 22 -m limit --limit 1/sec -j LOG --log-prefix "ssh_blacklist" --log-level 7 

-A LOGDROP -j REJECT --reject-with icmp-host-prohibited 

-A THRU -p icmp -m limit --limit 1/sec -m icmp --icmp-type 8 -j ACCEPT 

-A THRU -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT 

COMMIT

# Completed on Tue Mar  7 13:56:36 2006

--------------------------------------------------------

if you think this as worked, do i then just have to rename this new script to match my existing entry in /etc/conf.d/local.start ?

Thank You, Keiko.

----------

## m8ryx

there should be output...at least you should see Starting firewall.  Try removing the depend clause and run it again.

rick

----------

## Keiko

Hia rick,

I've just deleted the following :

  depend() {

   need net

  }

and then i re-ran the command : /etc/init.d/new-iptables-script start

and again i recieved no output at all. This is really screwing my head up, i can't figure out why it doesn't work, it seems all i can do is input commands and then save the output, and its really frustrating.

Thanks, Keiko.

[EDIT] Made another copy to try soem thigns, renamed the /sbin/runscript to ./bin/sh, that didn't work, tried ti with and without the depend lines, tried adding an echo statement at the begin to look for output still nothing returned, it seems like the script can't run at all, which is something i just can't understand as the code seems perfectly valid and is used on many other scrips i've seen, including the one where i took the script code portions from... totally lost.

Keiko.

----------

## Keiko

Hia,

I may be on to something, i changed the " sbin/runscript " header to " bin/bash ", which gave loads of errors saying " iptables command not found " so i added a path to iptables, and now

i get the following output when i run the script.

-----------------------------------------------------------------------------

iptables: Chain already exists:

iptables: Chain already exists:

iptables: Chain already exists:

iptables: Chain already exists:

iptables: Chain already exists:

Warning: Wierd charecter in interface '-j' (No aliases, : , | or * ).

Bad argument 'ACCEPT'

Try 'iptables -h' or 'iptables --help' for more information.

Warning: Wierd charecter in interface '-eth0' (No aliases, : , | or * ).

Bad argument '-'

Try 'iptables -h' or 'iptables --help' for more information.

Bad argument 'icmp'

Try 'iptables -h' or 'iptables --help' for more information.

------------------------------------------------------------------------------

The source for this versions is http://rafb.net/paste/results/7f7AI691.txt

Any ideas, what i should try next, does this look like i'm heading in the right direction, i've had to delete some lines for this so it will need some work, main priority now, is to get it to run though.

Keiko.

----------

## pteppic

```
# This rule allows in all packets from the localhost interface.

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

should read

```
# This rule allows in all packets from the localhost interface.

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

next...

```
# the originating ip address is one known to the system as a spammer's address.

   iptables -A INPUT -i -eth0 -p tcp -m tcp --dport 25 -j SPAM
```

should read

```
# the originating ip address is one known to the system as a spammer's address.

   iptables -A INPUT -i eth0 -p tcp -m tcp --dport 25 -j SPAM
```

and

```
# the "tcp-flags" are optional, in this case, they are set to look for new connections with "SYN,RST,ACK SYN".

   iptables -A INPUT - eth0 -p tcp -m tcp --dport 80 -j --tcp-flags SYN,RST,ACK SYN WEB
```

should read

```
# the "tcp-flags" are optional, in this case, they are set to look for new connections with "SYN,RST,ACK SYN".

   iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 -j --tcp-flags SYN,RST,ACK SYN WEB
```

lastly

```
# We will allow pings (ICMP type 8) but limit there use to one every 30 seconds.

   iptables -A -P icmp -m limit --limit 2/min -m icmp --icmp-type 8 -j ACCEPT
```

should read

```
# We will allow pings (ICMP type 8) but limit there use to one every 30 seconds.

   iptables -A -p icmp -m limit --limit 2/min -m icmp --icmp-type 8 -j ACCEPT
```

Basic syntax really....

----------

## Keiko

Hia Rick,

Good news, i've solved all of the above errors. I took a tip from the Advanced Bash Scripting Guide (ABS.pdf) and added extra echo lines, to help me identify where the errors where in my code.

So near the start i added " echo " Error Marker-1 = Passed ", then in the next section i added " echo " Error Marker-2 = Passed " and so on, until i had 5. This time, when i ran my script, i recieve a message saying something like:

-------------------------------------

Starting firewall

Error Marker-1 = Passed

<error>

<error>

Error Marker-2 = Passed

Error Marker-3 = Passed

<error>

Error Marker-4 = Passed

<error>

Error Marker-5 = Passed

-------------------------------------

This then enabled me to look at a specific section to find the error, all of them where very basic syntax errors, i crossrefrenced, this code with my original rules, and found them all, when i run my script now, i get:

==============================

Starting firewall

Error Marker-1 = Passed

Error Marker-2 = Passed

Error Marker-3 = Passed

Error Marker-4 = Passed

Error Marker-5 = Passed

==============================

Whatever i did earlier, managed to stop my system from booting, so i'm a little nervous this time, but i'm going to try and test this with iptables now, if it works, then i can improove it.

Things i want to improove are:

 1. To be able to call the script with 'start', 'status', 'restart' and 'stop'

 2. Improovements witth the rules.

I'll keep you posted, Thanks for all the help and support, Keiko.

----------

## Keiko

Hia pteppic,

Hey didn't see your message there,   :Razz:   thanks for that,  at least i now i can use those 'error markers', i love that idea.

Thanks for the help.

Keiko.

----------

## Keiko

Hia,

Couln't put my script down... and its paid off, its working properly now as expected, all thats left to do is improove it.

Thanks for all your help.

Keiko.

----------

## m8ryx

great news, congrats!  It'd be cool if you edit the first post and put a (solved) in the header.  Even better, you could post your final script (to this site, not an external one) and others can benefit from your efforts.

Some scripting tips for the future (debugging, that is):

1) what you did is totally key

2) when working with variables (not in this case, but it happens  :Wink:  copy it and put an echo in front of the whole thing...the first, copy, not the second

3) comment everything out and start adding stuff

4) along the same lines, use stub functions to simplify

One other tip...since I just use my box for home use, and I'm a bit tired of all the stupid bot hack attempts, I pulled a list of asian IP addresses from http://www.dayomon.net/fw/ and put it into my iptables.  Haven't had any problems with it yet, and they generate a snappy set of iptables rulesets for you.

----------

## Keiko

Hia,

Yeah, sure [sovled] it is forgot to do it earlier, and heres my latest version, i've made a few improovements on it.

Hmm, i dont get your second point there, dont understand could you clarify for me, also are stub functions similar to procedures, i've used them in pascal and it really improoves the code, imho...

Anyways heres my script, and thanks again, couldn't have done it without this help.

[edit] I'm not sure what else i can do with it, i've got several ideas, but everything i've thought of so far, is redundent, as my linux bos, is a local network client, and the internet connection is achieved with an ethernet router connected to our switch, so anything to do with NAT, masquarading, or even stopping pings, or blocking the majority of my open ports, is either pointless, or counter productive, so within this constrain, any ideas from what i can improove on...

Keiko.

=====================================

#!/bin/bash

IPTABLES=/sbin/iptables

	echo "Starting firewall ... "

#----------------------------------- This Script -----------------------------------------------------#

#

# This is my iptables firewall script, it contains the rules that will correctly configure iptables.

#

# This script was created from a very good guide on "http://www.pettingers.org/code/firewall.html" and with

# support and help from various people within the linux community, Thanks must go to those who helped me a

# great deal on the Gentoo forums," https://forums.gentoo.org/ ".

#

# Created on 08/03/2006 by Keiko.

#

#

# If you want this script to automatically setup iptables when you boot your computer (Gentoo), ensure it is

# named firewall and place it into your /etc/init.d/ directory. 

# Now using your preffered editor open /etc/conf.d/local.start and add the following line (without quotes)

# "/etc/init.d/firewall" these rules will then be passed to iptables upon boot.

# To test that the rules have been passed to iptables correctly as super user (root) type the following in a

# terminal (without quotes) "iptables -L" this will list the rules and chains that iptables is using.

#

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

# The defaul policy of the INPUT chain is now changed, to allow all packets to enter, this is only temporary

# however and will be changed later.

	iptables -P INPUT ACCEPT 

# We will now flush (delete) any rules for the existing chains, which could affect the new rules we are going to implement.

	iptables -F

# And delete any existing custom chains.

	iptables -X

# We are going to create five custom chains. We will use these as targets for our new rules.

	iptables -N SPAM

	iptables -N WEB

	iptables -N BLACKLIST

	iptables -N THRU

	iptables -N LOGDROP

#echo " Error Marker-1 = Passed "

#---------------------------------------- The Rules-----------------------------------------------------#

# The first rule bellow, will allow parckets through if they are part of an established connection, and the

# second rule will allow packets through if they are part of a related connection, such as a program like

# bittorrent openning up new ports. However we will only permit related connections to open related ports

# between port numbers 1025 and 65535.

	iptables -A INPUT -i eth0 -m state --state ESTABLISHED -j ACCEPT

	iptables -t filter -A INPUT -p tcp --dport 1025:65535 -m state --state RELATED -j ACCEPT  

# This rule allows in all packets from the localhost interface.

	iptables -A INPUT -i lo -j ACCEPT

# The next rule will send any packets coming in from port 25 to our SPAM custom chain, to be checked, if

# the originating ip address is one known to the system as a spammer's address.

	iptables -A INPUT -i eth0 -p tcp -m tcp --dport 25 -j SPAM

# The following rule does the same thing but checks for wbe hackers instead of spammers via the WEB custom chain,

# the "tcp-flags" are optional, in this case, they are set to look for new connections with "SYN,RST,ACK SYN".

	iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 --tcp-flags SYN,RST,ACK SYN -j WEB

# The next rule, ensures that any packets that have gotten through the above rules will be jumped to our 

# "general blacklist" the BLACKLIST custom chain.

	iptables -A INPUT -j BLACKLIST

# Simirly this rule will jump any packets that have gotten through the BLACKLIST chain to our THRU custom chain.

# The THRU custom chain, is used to allow packets in if they are explictley allowed, such as form trusted hosts.

	iptables -A INPUT -j THRU

#echo " Error Marker-2 = Passed "	

# Next we will create a log entry for the logging daemon each time we drop a packet, however to reduce the riks of

# denial-of-service attacks this logging will be restricted to one entry per second. The log level 7, means that,

# the priority will be set to debug, so these log entries can be exported to a file with syslog / syslog-ng by

# matching "facility(kernel) and level(debug).

	iptables -A INPUT -m limit --limit 1/sec -j LOG --log-prefix "drop_packet" --log-level 7

# Some IP addresses that we require to block, due to recent ssh breakin attemptsl, from these addresses.

	iptables -A BLACKLIST -s 81.56.126.41 -j LOGDROP

	iptables -A BLACKLIST -s 213.145.191.238 -j LOGDROP

	iptables -A BLACKLIST -s 69.93.81.10 -j LOGDROP

	iptables -A BLACKLIST -s 165.228.11.218 -j LOGDROP

#echo " Error Marker-3 = Passed "

# We are now going to setup some rules, that will explictley allow packets into particular ports to ensure

# the services we run (i.e webserver, mail server, ssh server) will continue to fuction.

# - NOTE - By default only port 22 will be open for ssh, other populor service ports are included bellow for

# 	   completness and will need to be un-commented  (remove the preceding #) if you require them open.

# We will allow pings (ICMP type 8) but limit there use to one every 30 seconds.

	iptables -A THRU -p icmp -m limit --limit 2/min -m icmp --icmp-type 8 -j ACCEPT

# FTP (tcp port 21)

#	

#	iptables -A THRU -i eth0 -p tcp --dport 21 -j ACCEPT

# SSH (tcp port 22)

	iptables -A THRU -i eth0 -p tcp --dport 22 -j ACCEPT

# SMTP (tcp port 25)

#

#	iptables -A THRU -i eth0 -p tcp -m tcp --dport 25 -j ACCEPT

# HTTP (tcp port 80)

#

#	iptables -A THRU -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT

# POP3 (tcp port 110)

#

#	iptables -A THRU -i eth0 -p tcp -m tcp --dport 110 -j ACCEPT

# If you require to find out what port number your particular service uses, a complete listing of ports and services

# can be found here:  http://www.iana.org/assignments/port-numbers

#echo " Error Marker-4 = Passed "

# We will now add our final rule to the INPUT chain, which will drop all packets, that havn't been accepted

# via any of the previous rules, we will also now change the default policy for INPUT to DROP.

	iptables -A INPUT -j DROP

	iptables -P INPUT DROP

# We will alos set the default policy for the FORWARD chain to DROP, as it should not be used, in this configuration.

	iptables -P FORWARD DROP

# The following rules are for our final custom chain LOGDROP. These will place descriptive annotations

# on the log entries, to aid with log analysis later on.

	iptables -A LOGDROP -p tcp -m tcp --dport 22 -m limit --limit 1/sec -j LOG --log-prefix "ssh_blacklist" --log-level 7

	iptables -A LOGDROP -p tcp -m tcp --dport 25 -m limit --limit 1/sec -j LOG --log-prefix "spam_blacklist" --log-level 7

	iptables -A LOGDROP -p tcp -m tcp --dport 80 -m limit --limit 1/sec -j LOG --log-prefix "ssh_blacklist" --log-level 7

# The following line specifies how we will respond to packets that have gone through the LOGDROP custom chain.

	iptables -A LOGDROP -j REJECT --reject-with icmp-host-prohibited

#

#

# - NOTE -  To make use of our various blacklists, you can manually add rules to the respective chain, such

# as the following examples:

#

#	iptables -A BLACKLIST -s 192.168.254.5 -j LOGDROP

#	iptables -A BLACKLIST -s 192.168.220.9/24 -p tcp --dport 22 -j LOGDROP

#	iptables -A SPAM -s scum.spammers.org -j LOGDROP

#	iptables -A WEB -s script.kiddies.com -j LOGDROP

#

# - NOTE - the " -s " flag indicates a source.

#	

#--------------------------------------- End of Configuration----------------------------------------------#

#echo " Error Marker-5 = Passed "

	echo "Firewall started and configured"

exit

----------

