In the previous post on iptables , I had given an introduction about iptables - the firewall installed by default in all Linux distributions. Here I will explain how to go about designing a firewall keeping in mind the needs of a home user. I am assuming that the typical home user will be having a single computer connected to the internet via a cable, DSL, Dialup or ISDN connection. There is no hard and fast rule in designing a firewall. What is good for one situation may not be good for another. But you can arrive at a common ground on certain things.
Here I will explain how you can make your home machine which is connected to the internet , which I am giving the name 'my_machine', more secure. First let us see what are the services that are running on the home machine (my_machine). Usually when you install Linux on your machine, you will be having some default services.They are as follows:
- sshd - Secure Shell server
- portmap - Which is used by file services like NFS
- httpd - Apache web server
- ftp server - File Transfer Protocol server. This is not usually running on a home machine but just make sure about it by checking. In RedHat, you can check by running the command:
If you have nmap installed on your machine, you can run the command :
# chkconfig --list |grep ftp
...to find all the open ports on your machine. The output for my_machine are as follows:
# nmap -sS your_ip_address
Starting nmap 3.50 ( http://www.insecure.org/nmap/ )
at 2005-10-19 09:41 IST
Interesting ports on my_ip_address:
(The 1653 ports scanned but not shown below
are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
3306/tcp open mysql
6000/tcp open X11
32774/tcp open sometimes-rpc11
Nmap run completed -- 1 IP address (1 host up)
scanned in 1.205 secondsAs seen above, I have apache webserver (http) , ssh, mysql server, X Server and rpcbind open to the outside world. rpcbind is used by NFS for mounting a remote drive. Usually a stand alone machine in our case my_machine need not open these services to the internet - except maybe ssh server which you might need to say - connect to your machine from a remote location - that too only if you have a static IP address, which is quite rare.
So lets get a pen and paper and decide how much or how little we want to open up our machine to the outside world. This is what I have decided:
- I want full access to my_machine locally. That is all the services should be available for the localhost or IP address 127.0.0.1 .
- New connections originating from a remote machine to Portmap, ssh, webserver and X server has to be blocked.
- Established and related connections to my_machine has to be allowed. Here I would like to deviate from the topic to explain the terms 'new','established' and 'related'.For that you have to look at how TCP works. TCP is a connection-oriented protocol. Connection-oriented means that it makes sure all the packets reach the destination without any packet loss in transit. If a packet is lost, it re-sends the lost packet. This it achieves by using a set of flags. The flags are called SYN (Synchronize) and ACK (Acknowledge).When you click on a link in your web browser, your machine sends a SYN packet to the remote server which hosts the link. This process is called initiating a connection and is represented as NEW connection. When the remote server receives your request which has the flag SYN set, it sends a acknowledgment back to your machine by setting the SYN-ACK flag. And this is called a related connection.Once your machine receives the SYN-ACK packet, it responds with a final ACK packet which tells the remote machine that we have indeed received the packet. Then the connection is said to be established. This is called the three way handshake.
- Restrict anyone initiating a new connection to my_machine from a remote location.
- Allow all outgoing connections originating from my_machine.
- Restrict all other incoming connections.
Now that we have jotted down what we want to achieve, let us write rules for achieving it.
I usually write the rules in a script file and then execute the file. This allows me to keep everything organized. Also if I make a mistake, I just have to go back and edit the script and re-execute it. One other thing though - all allow rules must precede the deny rules.
Allow localhost access to everything
iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT
Allow all related and established tcp connections to my_machine.
iptables -A INPUT -p tcp -m state
Allow all outgoing connections from my_machine.
... now start writing the deny rules.
iptables -A OUTPUT -j ACCEPT
Deny all new tcp connections from remote machines. And log the same.
iptables -A INPUT -p tcp -m state --state NEW -j LOG
iptables -A INPUT -p tcp -m state --state NEW -j DROP
Block the apache port on my_machine. See the nmap command listing above. Also log the traffic.
Note: LOG rule must precede the corresponding filter rule.
iptables -A INPUT -p tcp -s 0/0 --dport 80 -j LOG
iptables -A INPUT -p tcp -s 0/0 --dport 80 -j DROP
Block ssh to my_machine. Also log the traffic.
iptables -A INPUT -p tcp -s 0/0 --dport 22 -j LOG
iptables -A INPUT -p tcp -s 0/0 --dport 22 -j DROP
Finally Deny everything else.
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP
Now execute the script to load the rules into kernel space. That is it. Now we have got a robust firewall in place. You can check the results by re-running the nmap command listed above.