iptables base ruleset

I remember very well how lost I encountered iptables for the first few times. It was so bad that I gave up completely… many times over! Every attempt had major starting troubles.

If only I had a holding hand or helpful reference like this one below. Or perhaps I just need to make this long winded journey, where I am a bit older and wiser to digest such complicated issues.

I've been using iptables for a few years now, and it just flows. Admittedly, I don't push the boundaries. I don't have IP6, NAT, or any complicated setup. I try to keep my ruleset very simple, in accordance with my principles.

Rule #0: KISS
Keep it Short and Simple.

Rule #1: Deny everything. Allow specifically.
Close all doors, and open only those required when required.

A starter base is always helpful for everyone. This is mine.

-F
-X
-Z

-P INPUT   DROP
-P OUTPUT  DROP
-P FORWARD DROP

-A INPUT  -m state --state INVALID -j DROP
-A OUTPUT -m state --state INVALID -j DROP

-A INPUT -p tcp ! --syn -m state --state NEW -j DROP
-A INPUT -p tcp --tcp-flags ALL ALL -j DROP
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
-A INPUT -f -j DROP

-A INPUT  -i lo -s 127.0.0.1/8 -j ACCEPT
-A OUTPUT -o lo -d 127.0.0.1/8 -j ACCEPT

-A INPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,NEW     -j ACCEPT

-A INPUT   -j LOG --log-level notice --log-prefix "ipt: "
-A INPUT   -j DROP
-A OUTPUT  -j LOG --log-level notice --log-prefix "ipt: "
-A OUTPUT  -j DROP
-A FORWARD -j LOG --log-level notice --log-prefix "ipt: "
-A FORWARD -j DROP

The outgoing rules would be a lot more locked down in practice. I would remove NEW, and only allow specific ports.

While building my base ruleset, I found a few resources very useful. Links in the index at the bottom. One of them is a Wilders Forums thread[1]. The other is from an archived StackExchange blog[2], relevant parts copied here just in case that disappears.

Base Rulesets in IPTables[2]

"Is there a recommended set of firewall rules that can be used as a standard config?"

I have a bunch of systems, so what rules should they all have no matter what services they provide.

-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp --icmp-type any -j ACCEPT
# Force SYN checks
-A INPUT -p tcp ! --syn -m state --state NEW -j DROP
# Drop all fragments
-A INPUT -f -j DROP
# Drop XMAS packets
-A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# Drop NULL packets
-A INPUT -p tcp --tcp-flags ALL NONE -j DROP
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Enough services use loopback that, except in very restrictive environments, attempting to firewall them will almost definitely be more work than is useful.

ESTABLISHED keyword allows return traffic for outgoing connections.
RELATED keyword takes care of things like FTP that use multiple ports and may trigger multiple flows that are not part of the same connection, but are none-the-less dependent on each other.

In a perfect world these would be at the top for performance reasons. Since rules are processed in order we really want the fewest number of rules processed as possible, however in order to get the full benefit from the above rule set, we want to run as many packets as possible by them.

The allow all on ICMP is probably the most controversial part of this set. While there are reconnaissance concerns with ICMP, the network infrastructure is designed with the assumption that ICMP is passed.[3]

Let's look at each of the wonky rules in order.

Forcing SYN Checks
This is a bit of a low-hanging fruit kind of rule. If these conditions match, then we’re looking at a packet that we just downright shouldn't be interested in. This could indicate a situation where the connection has been pruned from the conntrack state table, or perhaps a malicious replay event. Either way, there isn’t any typical benefit to allowing this traffic, so let’s explicitly block it.

Fragments Be Damned
By default, standard iptables rules are only applied to the packet marked as the first fragment. Meaning, any packet marked as a fragment with an offset of 2 or greater is passed through, the assumption being that if we receive an invalid packet then reassembly will fail and the packets will get dropped anyway. In my experience, fragmentation is a small enough problem that I don’t want to deal with risk and block it anyway.

Christmas in July
'Christmas Tree Packets' are one of those reconnaissance techniques used by most network scanners. The idea is that for whatever protocol we use, whether TCP/UDP/ICMP/etc, every flag is set and every option is enabled. The notion is that just like a old style indicator board the packet is "lit up like a Christmas tree". By using a packet like this we can look at the behavior of the responses and make some guesses about what operating system and version the remote host is running.
By design some flags are incompatible with each-other and as a result any Christmas Tree Packet is at best a protocol anomaly, and at worst a precursor to malicious activity. In either case, there is normally no compelling reason to accept such packets, so we should drop them just to be safe.

Nothing to See Here
When we see a packet where none of the flags or options are set we use the term Null Packet. Just like with the above Christmas Tree Packet, one should not see this on a normal, well behaved network. Also, just as above, they can be used for reconnaissance purposes to try and determine the OS of the remote host.

If you got a bit lost up there, it might be worth refreshing some concepts.

TCP connections[1]

ICMP types[1]


[1] [Tutorial] Expert Linux
[2]
Base Rulesets in IPTables
[3] Security risk of PING?
[4] TCP connections
[5] ICMP types
Firewalling

No comments:

Post a Comment

most viewed