I like editing the iptables file manually, but there's something that confuses me a bit.
From how I have understood iptables from the manual, it traverses the rules from top to bottom, and if no match is possible it will be logged and denied by the default rules in the bottom.
All good.
But what does these mean:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
<accept ssh, ssl, etc>
<log all, deny all>
The chains in the top has default policy "accept" – is this only a way of saying that we accept the packets into the filter
table, for later matching? For me, after reading the manual, it feels as if it would accept everything and then not read the rules, because that's how rules work by default – if anything matches it will stop reading rules and then do what the policy sais. Any documentation of this behaviour? I cannot find anything specific enough.
I have also seen this, after the *filter
table:
*filter
:RH-Firewall-1-INPUT - [0:0]
Which gives the ability to add your own chains and route other chains to this chain:
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
But here the "ACCEPT" or "DROP" is not specified at all for this chain, but instead there's a dash (-).
Which makes me even more confused – how does it work?
Best Answer
The policy on a built-in chain determines what happens to packets that make it through all the rules in the chain without matching a single one with a dispositive target. In your example above, packets that make it all the way through the
FORWARD
chain without matching any rule with a dispositive target will beACCEPT
ed, because the chain's policy isACCEPT
.User-defined chains cannot have a policy. Packets that pass all the way through a user-defined chain without matching a rule with a dispositive target return to the chain from which they were sent to the user-defined chain (the "calling chain") at the rule after the one that sent them there.
A dispositive target is one which disposes of a packet; examples include
DROP
,ACCEPT
, andMASQUERADE
; non-dispositive targets includeLOG
, and the null target (it's quite legal to have a rule that has no target). When a packet matches a rule with a dispositive target, the packet is considered disposed of, and no further rule processing occurs. When a packet matches a rule without a dispositive target, packet processing continues at the next rule.An important corollary of this logic on target-matching and disposition is that first-dispositive-match wins. Too often we see questions on SF where people have a chain that says, eg,
which contains a single rule to block access to a web server (
tcp dpt:80
). They wish to allow a single external IP address, say1.2.3.4
, to access this web server, so they add a rule withand they end up with a chain like this
As you can see, the packet counts on that last rule are zero - and they will always be zero. No packet can match that last rule without having matched the one before it, and the one before it is dispositive (
DROP
), so no packet will ever reach that last rule.The way to deal with this correctly is to ensure that your exceptions come before your rules, like this:
Now, the exceptional acceptances are handled first, then other web server packets that don't come from the exceptional server are handled and dropped, and finally the chain policy takes care of all other packets and accepts them.