netfilter/iptables is a de facto IP packet filtering tool used in Linux operating system (OS). iptables provides features for system administrator to filter packets coming in and going out of the system by inspecting packets' header. The packet filtering operation is performed at OSI layer 4 and below within the kernel itself.
iptables uses tables to provide comprehensive packet filtering functions. In this tutorial series, I will be covering three main features provided by iptables...
Filter: provides the main packet filtering operation
Conntrack: allows iptables to be configured as a stateful firewall
NAT: provides network address translation (NAT) operation
iptables Packet Flow
It is important to understand the packet flow and the filtering points of iptables to fully grasp your packet filtering configuration.
PREROUTING: filter packets that first arrived to the system.
Routing Decision: determine whether packets is destined for the local system or forwarded / routed using a routing table.
INPUT: filter packets that is destined for the local system.
OUTPUT: filter packets that is sent from the local process.
FORWARD: filter packets that is routed through the local system.
POSTROUTING: filter packets prior to leaving the system.
The INPUT and OUTPUT filtering points are heavily used by system administrators to filter IP packets while PREROUTING is an interesting filter point that is used to configure NAT.
In this tutorial, I'll be covering different filtering functions provided by iptables. By the end of the tutorial, you will be able to configure your iptables to filter packets coming in and going out of your Linux system, configure your iptables as a stateful firewall, configure your iptables to perform NAT, and administer your iptables using fwbuilder.
I'll be using two Linux machines for my tutorial demonstration:
iptables running on a Red Hat machine (IP address: 192.168.1.10), and
a client machine, running Ubuntu (IP address: 192.168.1.20), attempting to communicate with my Redhat server.
iptables will look into its configuration file, /etc/sysconfig/iptables, when the service is starting.
Default iptables Rules
To look at the executing packet filters, simply use the command service iptables status.
Default iptables Status
The default iptables filter suggest that all IP packets that reaches the INPUT and FORWARD filtering point to be handled by a rule chain named RH-Firewall-1-INPUT. We will not be using the default filtering rules in this tutorial. First backup the default iptables configuration (good practice):
# cp /etc/sysconfig/iptables /etc/sysconfig/iptables.orig
flush all existing filtering rules and overwrite the configuration file such that iptables will not boot into the default filtering rule in the future.
iptables-save > /etc/sysconfig/iptables
Writing your first filter
A firewall is useless without any filtering rule. Here we see that my Ubuntu machine can ping my Redhat machine without any problem.
We can add a rule to drop all packets from my Ubuntu machine...
iptables -A INPUT -s 192.168.1.20 -j DROP
and my Ubuntu machine can no longer communicate with my Redhat machine...
Append v. Insert
iptables filtering rules are read by the system as an ordered list, the order of the filters are very important. Here, we append an ACCEPT rule after the DROP rule...
iptables -A INPUT -s 192.168.1.20 -j ACCEPT
Ubuntu will still not able to ping the Redhat machine.
Now we remove the DROP rule...
Ubuntu can ping Red Hat machine again...
Now, let's look at the difference between appending (-A) and inserting (-I). Here, we insert an ACCEPT rule before the DROP rule...
iptables -I INPUT -s 192.168.1.20 -j ACCEPT
Ubuntu can communicate with my Redhat machine as the ACCEPT rule was read by the iptables before the DROP rule.
Filtering your Network Interface and OUTPUT filtering point
For machines with multiple network interfaces, iptables allows you to set rules specifically for one of your many network interfaces. Here, I allowed all localhost packets and DROP all packets destined to my Ubuntu machine from my network interface eth1.
iptables -I OUTPUT -o eth1 -d 192.168.1.20 -j DROP
iptables filter DROP all outgoing packets to my Ubuntu machine,
and Ubuntu will not be able to receive any reply from my Redhat machine.
OSI Layer 4 (Transport) Filtering
A firewall is not particular useful if it can only filter packets based on IP addresses and subnets. iptables is usually used to filter packets based on transport protocols and ports. If your server is running a web server but does not allow SSH connection to it...
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j DROP
and, you need DNS services...
# iptables -A INPUT -p udp --sport 53 -j ACCEPT
Last but not least, it is always a good practice to append a "catch-all" DROP rule at the bottom of all firewall configuration.
# iptables -A INPUT -j DROP
Fail-safe defaults: "Base access decisions on permission rather than exclusion. [...] design must be based on arguments why objects should be accessible, rather than why they should not. In a large system some objects will be inadequately considered, so a default of lack of permission is safer. A design or implementation mistake in a mechanism that gives explicit permission tends to fail by refusing permission, a safe situation, since it will be quickly detected. On the other hand, a design or implementation mistake in a mechanism that explicitly excludes access tends to fail by allowing access, a failure which may go unnoticed in normal use."
Jerome H. Saltzer and Michael D. Schroeder.
The Protection of Information in Computer Systems. 1975.
iptables- save and restore
Before you switch off your local system, you can see that /etc/sysconfig/iptables is still empty after despite all the configuration you have made. You can save your new configuration using iptables-save.
Or, you can restore your default iptables filters using iptables-restore
# cp /etc/sysconfig/iptables.orig /etc/sysconfig/iptables
If you are confuse with the syntax, man iptables is your best friend.
3. Stateful Packet Filter
We have been configuring our iptables filters, to ACCEPT or DROP packets based on packets' header information so far, as a stateless packet filter. Such filters can easily by circumvent by communicating with the server as though you are responding to it rather than initiating one. Stateful packet filters addresses the drawback of stateless packet filters that consider each packet in isolation by keeping a table containing record of all current connection.
iptables has the ability to track four type of connection states:
NEW: packet belongs to a new connection.
ESTABLISHED: packet belongs to an existing connection (i.e. reply packet).
RELATED: packet belongs to a related existing connection.
INVALID: unidentified packet.
To ACCEPT all ESTABLISHED or RELATED packets...
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
If you are running a SMTP server, you will need to accept NEW connection to your server...
# iptables -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT
DROP all other NEW or INVALID packets...
# iptables -A INPUT -m state --state NEW,INVALID -j DROP
4. Network Address Translation (NAT)
NAT is a process of modifying IP address information in packets' header allowing you to hide internal sensitive IP addresses to your public IP address.
To hide your HTTP request behind a proxy...
# iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-dest 192.168.1.2:3128
or behind another machine...
# iptables -t nat -A POSTROUTING -p tcp --dport 80 -j SNAT --to-source 192.168.1.3
If you are running a web server using your internal IP address...
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest 192.168.1.10
5. Firewall Builder
In this last bit of the tutorial, I will be demonstrating (on my CentOS 6 machine) how you can easily manage iptables using a GUI tool -- fwbuilder. First, obtain a copy of the RPM here. Install fwbuilder and start it up!
Create a new firewall object (a representation of your machine that is running iptables).
Using the one of the template provided..
As I'm running a Web service on my CentOS machine, I will need machines from my "inside network" to be able access TCP port 80. I will have to insert the rule the "catch-all" deny rule...
Lastly, I will need to compile and install my new packet filtering rules.
And, now I have my new rules up and running without in-depth understanding of iptables' syntax.