IpTables — Netfilter. (Yet another fine tutorial.)


IpTables :

Target : Self.

The Basic iptables tutorial 1 — from the  UCHW. 2 Has been very helpful in the past, to me, in getting up to speed with IpT. 3

Now, that I’m somewhat “ older, ” I may be “ ready, ” to take the plunge — into the deeper waters of netfilter’s innerworkings. 😉 😀 Nuh, not really, I’m just kidding ! Netfilter — Iptables, has a very steep learing curve ! In other words : Don’t blame me, if something goes wrong. I’m posting “ as is, ” 4 I’ll also assume, you’re sitting in front of your computer, and are not logged in remotely !

##  A helpful hint :
##  In case you get stuck ?
##  Flush all rules, from the default chains.
sudo iptables -F
##  Flush all rules, from any userdefined chains.
sudo iptables -X

So, while I promised — a few days ago — to write up a more thorough description on how to use IpTables, I remember, to have written up 5 something similar, in the past. But to be fair, how I thought back then, and now, are way too much apart for me to make use of it. 😉 Let me start afresh, and point you to some recommended reading, while I conjure up a basic configuration for you to use, if you so would choose ‽ But remember : It’s always better though, to figure things out for yourself !

Hence the Recommended reading :

Nuff said ! Let’s get to work.

Important!

Netfilter evaluates all rules from top to bottom, i.e : the first one who matches wins. Therefore, if you have explicit needs to allow some, or such traffic, then you need to put those before any rules that match a DROP, or REJECT target. ← Just saying. 😉

The traversing of tables.

The traversing of tables.

Or to be more exact, from the man-page :

IpTables — Netfilter :
It is used to set up, maintain, and inspect the tables of IPv4 packet filter rules in the Linux kernel. Several different tables may be defined. Each table contains a number of built-in chains and may also contain user-defined chains.
Chain :
Each chain is a list of rules which can match a set of packets. Each rule specifies what to do with a packet that matches. This is called a ‘ target, ’ which may be a jump to a user-defined chain in the same table.
Target :
A firewall rule specifies criteria for a packet and a target. If the packet does not match, the next rule in the chain is the examined; if it does match, then the next rule is specified by the value of the target, which can be the name of a user-defined chain or one of the special values **ACCEPT**, **DROP**, **QUEUE** or **RETURN**.
ACCEPT
It means to let the packet through.
DROP
It means to drop the packet on the floor.
QUEUE
It means to pass the packet to userspace. (How the packet can be received by a userspace process differs by the particular queue handler. 2.4.x and 2.6.x kernels up to 2.6.13 include the ip_queue queue handler. Kernels 2.6.14 and later additionally include the nfnetlink_queue queue handler. Packets with a target of QUEUE will be sent to queue number ‘0’ in this case. Please also see the NFQUEUE target as described later in this man page.)
RETURN
It means stop traversing this chain and resume at the next rule in the previous (calling) chain. If the end of a built-in chain is reached or a rule in a built-in chain with target RETURN is matched, the target specified by the chain policy determines the fate of the packet.
How jumps work.

How jumps work.

Now in order to help visualize the rules I‘ve used : I’ve neatly written them down, as if they were css (or as a set of functions, depending on pov.) rules applied to some webpage. 😉 Right after this illustration I’ll post my final rules, mostly based on the UCHW’s version. The method I use for configuration upon startup is : This one.

*filter()
{
/*  When one issues a :*/
/*  sudo bash -c "iptables-save > /etc/iptables.rules"*/
/*  Then the head of the file will contain the following line.*/
/*  Generated by iptables-save v1.4.12 on Sun Dec 14 08:50:34 2014*/

/*  The “ filter ” table — it contains at least 3 **built in** chains,*/
/*  namely : INPUT, OUTPUT, and FORWARD.*/
POLICY()
{
/*  Here we set their **default** policy.*/
/*  Which can be one of the following : ACCEPT, DROP, or REJECT.*/
/*  I, personally, prefer to use the “ blacklist ” approach.*/
/*  I.e : Nothing in, or out, until I say so. : )*/
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
}
INPUT()
{
/*  The “ INPUT ” chain — 1<sup>st</sup> of the **default** chains.*/

/*  Accept — each, and every packet/protocol — on your local loopback.*/
/*  I.e. : Allow your computer, to talk to itself.*/
1.  -A INPUT -i lo -j ACCEPT
/*  This will allow — any initiated tcp connection (3-way handshake), see OUTPUT chain — to return unhindered.*/
2.  -A INPUT -p tcp -m tcp -m state --state ESTABLISHED -j ACCEPT
/*  Same as above, only now it refers to responsiveness to send out udp packets.*/
3.  -A INPUT -p udp -m udp -m state --state ESTABLISHED -j ACCEPT
/*  My machine will allow connections to be reset by the outside world, but only within reason.*/
4.  -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/sec --limit-burst 2 -j ACCEPT
/*  icmp is a useful protocol, and should be enabled/accepted.*/
/*  *Don’t break the Internet.**/
5.  -A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
6.  -A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
/*  This will mitigate the ping-flood attack.*/
7.  -A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j ACCEPT
8.  -A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
/*  Reject everything else, not defined.*/
/*  The chain’s policy will take care of everything I might have forgotten.*/
/*  Which, till this day, is absolute ZERO dropped packets. ; )*/
9.  -A INPUT -p tcp -m tcp -j REJECT --reject-with tcp-reset
10. -A INPUT -p udp -m udp -j REJECT --reject-with icmp-host-prohibited
11. -A INPUT -j REJECT --reject-with icmp-host-prohibited
/*  End of the line club. Libations for all ! : D*/
}
OUTPUT()
{
/*  The “ OUTPUT ” chain — 2<sup>nd</sup> of the **default** chains.*/

/*  Accept — each, and every packet/protocol — on your local loopback.*/
/*  I.e. : Allow your computer, to talk to itself.*/
1.  -A OUTPUT -o lo -j ACCEPT
/*  They explain all this — in far better detail — than I ever can. : D*/
/*  http://www.iptables.info/en/connection-state.html#STATEMACHINE*/

/*  All users : Initiate new connections.*/
2.  -A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "Initiate new connections." -j ACCEPT
3.  -A OUTPUT -p tcp -m tcp -m state --state ESTABLISHED -m comment --comment "Established connections." -j ACCEPT
/*  I can’t think of any proper use for this one, afaik only ftp creates additional connections.*/
/*  Neither have I seen my box create any.*/
/*  Oh, I’ve monitored mine, for a **very** long time. ; )*/
/*  -A OUTPUT -p tcp -m tcp -m state --state RELATED -m comment --comment "Related connections." -j ACCEPT*/
4.  -A OUTPUT -p udp -m udp -j ACCEPT
/*  icmp is a useful protocol, and should be enabled/accepted.*/
/*  *Don’t break the Internet.**/
5.  -A OUTPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
6.  -A OUTPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
7.  -A OUTPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j ACCEPT
8.  -A OUTPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
9.  -A OUTPUT -p icmp -j REJECT --reject-with icmp-host-prohibited
/*  Reject everything, everyone else.*/
10. -A OUTPUT -j REJECT --reject-with icmp-host-prohibited
/*  End of the line club. Libations for all !*/
/*  Default POLICY takes effect here.*/
}
FORWARD()
{
/*  The “ FORWARD ” chain — 3<sup>rd</sup> of the **default** chains.*/

/*  Forward the Foundation.*/

/*  I’m not a router. Nothing to see here, just walk along.*/
1.  -A FORWARD -m state --state INVALID -j REJECT --reject-with icmp-host-prohibited
2.  -A FORWARD -j REJECT --reject-with icmp-host-prohibited
/*  End of the line club. Libations for all !*/
/*  Default POLICY takes effect here.*/
}
COMMIT()
}
/* Completed on Sun Dec 14 08:50:34 2014*/

↑ Remember, this is for illustration purposes only!

Also the more astute will notice, that I haven’t defined any interface, such as : -i eth0, in the INPUT chain, or -o eth0, in the OUTPUT chain. Neither have I defined a source ip : e.g. -s 192.168.X.X, in the OUTPUT chain. Simply, because I don’t know yours ! 😀 It’s highly probable though, but to avoid any confusion(s), or frustration(s). I’ve opted to omit those. 😉 I use a fixed-ip 6, and thus I can restrict my firewall to an even tighter rule-set. I’ll publish mine to my cloudup, for you to view. ← May it be of use to you ?

Here’s the real deal :

The following can be pasted into any text-editor, of your choice. And … saved as — anything you want, as long as it’s useful to you — e.g. : iptables.rules.

##  When one issues a :
##  sudo bash -c "iptables-save > /etc/iptables.rules"
##  Then the head of the file will contain the following line.
#  Generated by iptables-save v1.4.12 on Sun Dec 14 08:50:34 2014
#
##  The “ filter ” table — it contains at least 3 **built in** chains,
##  namely : INPUT, OUTPUT, and FORWARD.
*filter
#
##  Here we set their **default** policy.
##  Which can be one of the following : ACCEPT, DROP, or REJECT.
##  I, personally, prefer to use the “ blacklist ” approach.
##  I.e : Nothing in, or out, until I say so. : )
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
##  The “ INPUT ” chain — 1<sup>st</sup> of the **default** chains.

##  Accept — each, and every packet/protocol — on your local loopback.
##  I.e. : Allow your computer, to talk to itself.
-A INPUT -i lo -j ACCEPT
##  This will allow — any initiated tcp connection (3-way handshake), see OUTPUT chain — to return unhindered.
-A INPUT -p tcp -m tcp -m state --state ESTABLISHED -j ACCEPT
##  Same as above, only now it refers to responsiveness to send out udp packets.
-A INPUT -p udp -m udp -m state --state ESTABLISHED -j ACCEPT
##  My machine will allow connections to be reset by the outside world, but only within reason.
-A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/sec --limit-burst 2 -j ACCEPT
##  icmp is a useful protocol, and should be enabled/accepted.
##  *Don’t break the Internet.*
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
##  This will mitigate the ping-flood attack.
-A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
##  Reject everything else, not defined.
##  The chain’s policy will take care of everything I might have forgotten.
##  Which, till this day, is absolute ZERO dropped packets. ; )
-A INPUT -p tcp -m tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -m udp -j REJECT --reject-with icmp-host-prohibited
-A INPUT -j REJECT --reject-with icmp-host-prohibited
##  End of the line club. Libations for all ! : D
#
##  The “ OUTPUT ” chain — 2<sup>nd</sup> of the **default** chains.
#
##  Accept — each, and every packet/protocol — on your local loopback.
##  I.e. : Allow your computer, to talk to itself.
-A OUTPUT -o lo -j ACCEPT
##  They explain all this — in far better detail — than I ever can. : D
##  http://www.iptables.info/en/connection-state.html#STATEMACHINE

##  All users : Initiate new connections.
-A OUTPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "Initiate new connections." -j ACCEPT
-A OUTPUT -p tcp -m tcp -m state --state ESTABLISHED -m comment --comment "Established connections." -j ACCEPT
##  I can’t think of any proper use for this one, afaik only ftp creates additional connections.
##  Neither have I seen my box create any.
##  Oh, I’ve monitored mine, for a **very** long time. ; )
-A OUTPUT -p tcp -m tcp -m state --state RELATED -m comment --comment "Related connections." -j ACCEPT
-A OUTPUT -p udp -m udp -j ACCEPT
##  icmp is a useful protocol, and should be enabled/accepted.
##  *Don’t break the Internet.*
-A OUTPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j ACCEPT
-A OUTPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A OUTPUT -p icmp -j REJECT --reject-with icmp-host-prohibited
##  Reject everything, everyone else. ICMP-only.
-A OUTPUT -j REJECT --reject-with icmp-host-prohibited
##  End of the line club. Libations for all !
##  Default POLICY takes effect here.
#
##  The “ FORWARD ” chain — 3<sup>rd</sup> of the **default** chains.
##  I’m not a router. Nothing to see here, just walk along.
-A FORWARD -m state --state INVALID -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
##  End of the line club. Libations for all !
##  Default POLICY takes effect here.
COMMIT
# Completed on Sun Dec 14 08:50:34 2014

Now, if you like what you see, then issue the following command, to make the desired changes, if that ? :

##  Simply prepending sudo to iptables-restore doesn’t work !
sudo bash -c "iptables-restore < /path/to/your/iptables.rules"

If you want to see what it’s doing, then do the following :

##  -L list
##  -n do NOT resolve any ips.
##  -v be verbose.
##  Neatly number the lines for us.
sudo iptables -L -n -v --line-numbers

My rule-set :
(Split up in 4 parts.)

In addition to sharing my rule-set, I feel like sharing my /etc/sysctl.conf 7 settings as well. YMMV though. 😉

Target : Self.

PS : May this post be a starting point to dig deeper into the innerworkings of IpTables. It’s impossible, and too cumbersome, to state every option, and possibility. Keep in mind, when you installed your linux-based system, it came with an open policy.