Sysadmin tools: How to use iptables
If you want to fully manage network traffic to and from your Linux system, the iptables
command is what you need to learn. In this article, I provide general advice on creating iptables
entries and several generic examples to get you started. The unfortunate fact about iptables
is that there are options don't make intuitive sense. For those, you'll just have to commit them to memory or use this article as an iptables
cheat sheet.
I need to mention that iptables
rules go into effect immediately after entering them. There's no daemon to restart or configuration to reload. For this reason, you have to be extremely careful or you will lock yourself out of the system you're using. Always issue rules that allow you into the system before you enter those that don't.
Don't run both firewalld and iptables at the same time. Disable firewalld to run iptables.
Show, don't tell
There are many ways to look at your iptables
rules list, but I generally only use one, which covers the two things I want to see: the rules and the line numbers. For example:
$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 192.168.1.0/24 anywhere tcp dpt:ssh
2 DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
The line numbers are important when you attempt to delete a rule. If you don't care about the line numbers, then a simple iptables -L
will work for you:
$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 192.168.1.0/24 anywhere tcp dpt:ssh
DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
As you can see from the above listing, there are three sections to the iptables
command's output: INPUT, FORWARD, and OUTPUT. FORWARD rules are between interfaces on the system.
Rules of order
If you decide that the order of your rules is awkward, not organized, or just plain wrong, then you change their order by exporting the rules with:
$ sudo iptables-save > ~/iptables.txt
Make your edits in your favorite editor—which is, of course, vi
—and then import the new version back into iptables
:
$ sudo iptables-restore < ~/iptables.txt
Because iptables
rules are read from top to bottom, this factor can become an issue if conflicting rules are read in the wrong order.
INPUT vs. OUTPUT
When you create a new rule, it will typically be in the form of adding an INPUT or an OUTPUT. INPUT rules govern traffic coming into the protected system, and OUTPUT rules govern traffic leaving the system. I'm not sure why INPUT and OUTPUT were used rather than the more descriptive INCOMING and OUTGOING or INBOUND and OUTBOUND, but like so many other things in life, no one asked my opinion prior to implementation.
So, the general form of an INPUT rule is:
iptables -I INPUT <other options>
And, OUTPUT rules are:
iptables -I OUTPUT <other options>
Adding entries
There are two ways that I add iptables
rules. One is with append (-A
), but I only use that one time per system. The second is insert (-I
), which is the way I add all other rules to a system. My explanation is that append puts the rule at the bottom of the list, and there's only one rule I want at the very bottom: the classic DENY ALL. It's simple to add.
$ sudo iptables -A INPUT -j DROP
This entry appends the DENY ALL rule to the bottom of whatever list of rules already exists. On a new system, there won't be any, but it's a good practice to start with. Remember, iptables
rules are read from the top down, so you always want the DENY ALL rule to be the last one on the list. If this rule falls anywhere else in the list, nothing below it will process. All other rules should be inserted with the (-I
) option, like this:
$ sudo iptables -I INPUT -s 192.168.1.0/24 -p tcp --dport 22 -j ACCEPT
The insert option adds the rule to the top of the list, and so the new rule will not be affected by DENY ALL. The particular rule above allows every system on the 192.168.1.0/24 network to connect to the protected system via SSH. Don't forget to add this rule, because the DROP rule locks you completely out of your system by denying all TCP traffic to it. I'm not going to tell you who, but I know someone who recently locked himself out of the system he was using for an article covering iptables
by forgetting the SSH rule. Fortunately, the system in question is a virtual machine and the console is easy to access. Imagine what would happen if someone submitted the DENY ALL rule without the SSH rule on a remotely hosted system and the console wasn't so easy to access.
Note: You should add the SSH rule first and then add the DENY ALL rule.
Deleting entries
Deleting iptables
entries is where the --line-numbers
option becomes essential. From a previous listing, you can see that my so-called DENY ALL rule is the second rule in the list (as it should be). To delete that rule, find the line number of the rule you wish to delete. For example:
$ sudo iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 192.168.1.0/24 anywhere tcp dpt:ssh
2 DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Issue the following command to remove the second rule:
$ sudo iptables -D INPUT 2
You must specify the list (INPUT, OUTPUT, or FORWARD) and the line number of the rule in that list. There is no response from the delete command.
Saving entries
You'll probably want your configured iptables to survive reboots, so be sure to issue the following command to save your valuable entries, otherwise, you'll have to import your rules after every reboot or script the import.
$ sudo iptables-save > /etc/sysconfig/iptables
Standard entries
For a truly locked-down system, you need a rule that allows you to SSH from a specific host or network, and a DENY ALL rule for both INPUT and OUTPUT. All other rules would be inserted as needed to allow specific traffic into and out of the system.
Other than those minimal rules, there are no other "standard" rules that apply to every system. If you have a web server, you'd have to write an INPUT rule to allow ports 80 and 443. If it's internet-facing, you'd have to open it up to all hosts. If the web server is internal, then you could only allow web access from your internal corporate networks.
Wrapping up
This article is a short introduction to one of the most necessary and useful sysadmin tools: iptables
. Iptables is easy to use and requires almost no maintenance. It requires no daemon restarts and it is available for all Linux systems. One of the first things you should do when bringing a new Linux system online is to set up these standard rules. You don't need any security issues springing up in the earliest days of deployment (or ever, really) and iptables
is a quick security fix if there ever was one.
Want more on networking topics? Check out the Linux networking cheat sheet.
Ken Hess
Ken has used Red Hat Linux since 1996 and has written ebooks, whitepapers, actual books, thousands of exam review questions, and hundreds of articles on open source and other topics. Ken also has 20+ years of experience as an enterprise sysadmin with Unix, Linux, Windows, and Virtualization. More about me