Corpus Christi, Texas Linux User Group

How to configure iptables firewalls using the bash shell

By Anthony Weitekamp
Security is a major topic these days. Here we will discuss how to configure a common firewall used by Debian and its downstream Linux distributions for user machines, not for servers. For the purposes of this article, it is assumed that the user is behind a hardware router, on their own private network. The iptables firewall is the default firewall used by many Linux distributions. You can enjoy higher security on your network and byond by configuring your firewall to suit your needs. This "How To" is part of a series of articles where I take a layered approach to firewall configuration. Setting rules directly with iptables places limitations directly on your "always conected" firewal settings. This should provide basic security for your system. Then when you use gufw to configure the "Uncomplicated Firewall" or ufw, you add a layer that can be turned on/off as needed depending on your circumstances. I develop software for the web, OpenGL, and some cryptographic applications. There are times when I want extremely tight firewall settings to test new software and other times when I need a more open approach.

Generally speaking, there are a couple of good rules to follow when using the command line to configure your firewall. Firet, read the 'man' or manual for the command. These man pages are generally written by software developers so educated users can use the command iine to quickly get work done. Another excellent rule is to have a script that will reset your firewall to its default settings before you start playing arond with the configuration. Finally, build a well documented script file with each command listed out along with a comment describing the action each line or group of lines will take. You do not want to go through the whole learning experience again to make a few changes six months or a year down the road.

Take a look at the man page for iptables by issuing the command...
$ man iptables 
Iptables is used to set up, maintain, and inspect the tables of IPv4 packet filter rules in the Linux kernel. Several different tables may be defined. Each table contains a number of built-in chains and may also contain user-defined chains.

Each chain is a list of rules which can match a set of packets. Each rule specifies what to do with a packet that matches. This is called a `target', which may be a jump to a user-defined chain in the same table.

A firewall rule specifies criteria for a packet and a target. If the packet does not match, the next rule in the chain is the examined; if it does match, then the next rule is specified by the value of the tar‐ get, which can be the name of a user-defined chain or one of the special values ACCEPT, DROP, QUEUE or RETURN.

ACCEPT means to let the packet through. DROP means to drop the packet on the floor. QUEUE means to pass the packet to userspace. (How the packet can be received by a userspace process differs by the particular queue handler. 2.4.x and 2.6.x kernels up to 2.6.13 include the ip_queue queue handler. Kernels 2.6.14 and later additionally include the nfnetlink_queue queue handler. Packets with a target of QUEUE will be sent to queue number '0' in this case. Please also see the NFQUEUE target as described later in this man page.) RETURN means stop traversing this chain and resume at the next rule in the previous (calling) chain. If the end of a built-in chain is reached or a rule in a built-in chain with target RETURN is matched, the target specified by the chain policy determines the fate of the packet.
This man page is well written and includes examples of how to compose commands to write rules for the firewall. It is still very well documented. Most people can figure it out with a little trial and error. We will be creating rules for these four (4) chains; user-input, user-limit, user-limit-accept, and user-output. Let's start out by creating a script that will show us what our settings currently are. type the following command.
 $ vim display_settings 
Now copy the following lines and paste them into your file.
#!/bin/bash
echo "#################################"
echo "Table Filter Rules "
iptables --table filter -S
echo "#################################"
echo "Table nat Rules "
iptables --table nat -S
echo "#################################"
echo "Table mangle Rules "
iptables --table mangle -S
echo "#################################"
echo "Table raw Rules "
iptables --table raw -S
echo "#################################"
echo "Table security Rules "
iptables --table security -S
echo "#################################"
	
Now press the escape key and type :wq then press enter to write and quit vim. Don't forget to change the mode of your file to executable.
$ chmod +x display_settings 
Now execute your script.
$ sudo ./display_settings 
The next script we will prepare will reset our firewall settings to their default in the event we make an error along the way.
$ vim reset_rules 
#!/bin/bash
echo "Reset iptables rules to default"
iptables --table filter -F
iptables --table filter -X
iptables --table nat -F
iptables --table nat -X
iptables --table mangle -F
iptables --table mangle -X
iptables --table raw -F
iptables --table raw -X
iptables --table security -F
iptables --table security -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
echo "Default rules set"
	
Write and quit the file, then make it executable.
$ chmod +x reset_rules 
Now we are ready to start setting rules on the firewall. Open 2 terminal sessions. Use the first session to test your rules and the second to record the rules in a file. Test your settings each time you write a rule to make sure you did not break something important. You can always return to your current position by resetting the rules then running your successful rules script.

The default settings for iptables is another way of saying that your computer is always connected. It will allow all services and software to communicate freely over the network. It is now time to decide which services and other applications you want to allow through the firewall and which ones you want to deny. Personally, I dislike torrent downloads, so that is one service that I would block on my computers. Make a list of everything you have on the computer that needs to "talk" on the network. Then go to wikipedia to get a list of common ports and match them up like this.
Allow These
	
Program				Port
Thunderbird
	POP2			109 (outgoing only)
	POP3 			110 (outgoing only)
	POP3 (Secure)		995 (outgoing only)
		
FireFox				80, 443 (outgoing only)
Apache Server			80, 443 (in and out)
	But only allow from computers on my subnet or
	only allow from specific computers.
	Make sure to include the address of the computer you are using.
MySQL				3306
	ALLOW from this computer
	DENY ALL Incoming
	
	
Deny These

Program				Port
BitTorrent			6881–6890, 6891–6901 (incoming)
Torrent Tracker	6969	(incoming)
kTorrent
amule					( in and out )
vnc					(incoming)
ssh					(incoming)
	Note: Blocking these ports will also stop "Windows Live Messenger" services
	


This is not an exhaustive list, but it is an example of what you can limit from the outside world. I personnaly dislike torrents and it is nearly impossible to keep the software from being installed in Linux. So, I will not let the software communicate through my firewall. Did you see how I added the direction (in/out) of the communication? I did this to reduce the number of rules I will be writing on the firewall. 'Outgoing only' rules do not need a line in the configuration but you can include them if you are going to explicitly deny services from using these ports. 'Incoming or in and out' rules must have an entry. Bittorrent is an in/out connection, therefore it needs a rule. But in setting rules on torrents I will limit my use of "Windows Live Messenger". I do not use software from Microsoft so it is no problem.

For the rest of this session we will be setting rules on the filter table of the firewall. Now we will create default policies and name some rules. This will make administration a lot easier as we get further along in the process.

Policy Rules

#!/bin/bash
# Default Policies
iptables --table filter -P INPUT DROP
iptables --table filter -P FORWARD DROP
iptables --table filter -P OUTPUT ACCEPT
	

Rule Names

# Name Chains
iptables --table filter -N user-input
iptables --table filter -N user-limit
iptables --table filter -N user-limit-accept
iptables --table filter -N user-output
	

Append Rules to the names and provide comments

# Add rules to chains

	# Chain user-input
iptables --table filter -A user-input -p tcp -m tcp --dport 6881 -j DROP
iptables --table filter -A user-input -p udp -m udp --dport 6881 -j DROP
iptables --table filter -A user-input -p udp -m udp --dport 4444 -j DROP
iptables --table filter -A user-input -p tcp -m multiport --dports 2234:2239 -j DROP
iptables --table filter -A user-input -p tcp -m tcp --dport 2242 -j DROP
iptables --table filter -A user-input -p tcp -m tcp --dport 2240 -j DROP
iptables --table filter -A user-input -p tcp -m multiport --dports 6881:6891 -j DROP
iptables --table filter -A user-input -p udp -m multiport --dports 6881:6891 -j DROP
iptables --table filter -A user-input -p tcp -m tcp --dport 4662 -j DROP
iptables --table filter -A user-input -p udp -m udp --dport 4672 -j DROP

# FTP 
iptables --table filter -A user-input -p tcp -m tcp --dport 20 -j DROP
iptables --table filter -A user-input -p tcp -m tcp --dport 21 -j DROP

# SSH
iptables --table filter -A user-input -p tcp -m tcp --dport 22 -j DROP

# TELNET
iptables --table filter -A user-input -p tcp -m tcp --dport 23 -j DROP

# SMTP
iptables --table filter -A user-input -p tcp -m tcp --dport 25 -j DROP

# VNC
iptables --table filter -A user-input -p tcp -m tcp --dport 5900 -j DROP
iptables --table filter -A user-input -p udp -m udp --dport 5900 -j DROP

# APP Discovery and Access Protocol
iptables --table filter -A user-input -p tcp -m tcp --dport 6350 -j DROP
iptables --table filter -A user-input -p udp -m udp --dport 6350 -j DROP

# Apache Webserver
iptables --table filter -A user-input -p tcp -m tcp --dport 80 -j ACCEPT
iptables --table filter -A user-input -p udp -m udp --dport 80 -j ACCEPT
iptables --table filter -A user-input -p tcp -m tcp --dport 443 -j ACCEPT
iptables --table filter -A user-input -p udp -m udp --dport 443 -j ACCEPT


	# Chain user-limit
iptables --table filter -A user-limit -m limit --limit 3/min -j LOG --log-prefix "[LIMIT BLOCK] "
iptables --table filter -A user-limit -j REJECT --reject-with icmp-port-unreachable
iptables --table filter -A user-limit-accept -j ACCEPT

	# Chain user-output
# Torrent programs
iptables --table filter -A user-output -p tcp -m tcp --dport 6881 -j DROP
iptables --table filter -A user-output -p udp -m udp --dport 6881 -j DROP
iptables --table filter -A user-output -p udp -m udp --dport 4444 -j DROP
iptables --table filter -A user-output -p tcp -m tcp --dport 4662 -j DROP
iptables --table filter -A user-output -p udp -m udp --dport 4672 -j DROP
iptables --table filter -A user-output -p tcp -m multiport --dports 6881:6891 -j DROP
iptables --table filter -A user-output -p udp -m multiport --dports 6881:6891 -j DROP

iptables --table filter -A user-output -p tcp -m tcp --dport 443 -j ACCEPT
	
This completes this lesson on how to configure your iptables firewall using the bash shell.