Using iptables the right way

I often come across tutorials on the Internet which attempt to show people how to use iptables. The intention behind these tutorials may be good, the problem is that sadly most of them are written by people believing to know all there is to know on this particular subject, when in reality they give advices that ultimately misguide more people. In this short tutorial I am going to explain what is the right way to use iptables, in the hope that someday, someone will find this post and use it rather than end up misguided by another poorly thought tutorial.

1. Stop using iptables -L

Iptables -L is a liar. When you want to examine your rules to find what may be wrong, don’t use it.

See for yourself, iptables -L VS. iptables-save.

Notice how iptables -L report the rules for the multiport up to 26200 and the UDP port to be from and to anywhere ?

Iptables -L is a pretty output that is there since a very long time, but should never be used for these reasons:

  • It lies about incoming / outgoing interfaces.
  • It takes time to display on some machine because it display the pretty name for a port if it is known rather than the port number.
  • It also try to resolve all the FQDN associated with the IPs, if any.

Even the classic iptables -L -v option is confusing, compared to the simple and clear output of iptables-save.

2. Use iptables-save and iptables-restore

One of the worst things you can do is trying to get help for your nice firewall you’ve made in bash scripting, posting on whatever pastebin you prefer and asking people for help debugging why some things work and some don’t, or why some work half the time. The reasons why not to do this can vary, but here is a couple:

  • You ask for help debugging a shell script, not a firewall.
  • The iptables command is not atomic.

Let me expand on that last statement. If you have a script such as this one for example:

#!/bin/bash
/usr/bin/iptables -P INPUT DROP
/usr/bin/iptables -P FORWARD DROP
/usr/bin/iptables -A INPUT -i lo -j ACCEPT
...

That script is going to be executed, line by line, in a non-atomic way. There will be a short period where your firewall will be imcomplete, each time a rule is applied up until it is all done. During that time the wrong packet could get into your network, or the right one could get stuck and not go out. Editing rules with the iptables command is also resource-intensive. Every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole. The more your firewall becomes complex, the more time it will take. You could get locked out of your own remote server for this exact reason.

This is why using iptables-save syntax is better for writing your rule set file, and why you should use iptables-restore to load/reload it. Iptables-restore is atomic, contrary to a shell script. It loads your entire rule set, and replace the current set in a single shot with it, thus not leaving the possibility of wrong packets coming in or good packets not leaving the system while it loads the rules.

  • Notes:
    • if you want, you can use either iptables-apply or iptables-failsafe, which can be found here to reload your rule set. They both have a timeout mechanism to avoid locking you out if you have made a mistake in your rules by rolling back to the previous working set if you did not answer to the prompt before the timeout.
    • it is worth noting that iptables-save, by default, output the current ruleset to stdout. Hence if you want to create the file from which iptables-restore will load your rules from, you should use it like this: iptables-save > iptables.rules.

3. DON’T use iptables -F

I often read this answer to a simple question such as “How do I delete all of my rules ?” “Use iptables -F, works for me.”

Plain wrong. Imagine you have a machine where the input and forward policy are both set to drop, and you realize you made a big mistake in your 10 last rules. So because you feel lazy about deleting them, you prefer starting over, and run iptables -F. You have just gotten yourself two big problems:

  • That machine is a remote one.
  • You flushed all the chains, but did not restore their policy to the default.

In clear, your machine does not accept any packets, nor does it forward any like it was previously doing because it was acting as the outside link for some containers you have running up on there. You deleted the rules, without changing the policy.

So no, don’t use iptables -F, ever.

I had this with a frontend on centos, firewalld. The machine was a server from Scaleway, running centos 6. At the time I didn’t know a thing about iptables, so I went with their frontend. Set the policy to deny for input and so on and… Got myself both locked out and without a working machine, because the disk was a network block device (nbd). Flushing was automatically done by firewalld when I reloaded it, which destroyed the active connection to keep the OS running.
That’s when I decided to learn iptables and never try to use any frontend again.

4. Don’t set OUTPUT policy to DROP unless you know what you are doing

The header pretty much says it all. Setting the OUTPUT policy to drop traffic is a bad idea, and you could end up in a world of trouble if you try it.

  • You would need to add all the IPs of the repositories mirrors of your distribution, relying on domain names in iptables is unsupported and a very bad practice.
  • What if these IPs change ?
  • How do you plan on getting DNS to resolve in the first place ?

Needless to say these are only a few of the problems you could encounter if you persist in your idea to block the OUTPUT chain. There are probably way more problems that I have not thought of myself, but these should be enough to make you get the idea that doing this unless you know what you’re doing is a very bad idea. And even if you know what you are doing, is my personal opinion. Just don’t connect the machine to the internet.

Conclusion

These are the major points I found after hanging around in the #Netfilter irc channel on freenode, and that I try to change. I got inspired by this gist which is in itself a ton of very good resources on various topics including netfilter, iptables, iproute. I recommend you take a look at the resources it offers and consider them carefully.

I hope this post was helpful to you in any case.

Till next time.

There are no comments

Join the conversation

Your email address will not be published. Required fields are marked *