MaxKellermann/ferm

Incorrect behaviour when default domain is used

KimBrodowski opened this issue · 0 comments

Hello,

I have the following rules.conf:

table filter chain INPUT proto tcp daddr 4.6.4.6 jump REJECT;
domain ip6 table filter chain INPUT proto TCP daddr fe80::1 jump REJECT;
domain ip table filter chain INPUT proto tcp daddr 4.4.4.4 jump REJECT;

According to the documentation the first line implies domain ip because when no domain is specified the IPv4 domain is used:

BASIC KEYWORDS
   Location keywords
       domain [ip|ip6]
               Set the domain. "ip" is default and means "IPv4" (iptables). "ip6" is for IPv6 support, using "ip6tables".

When generating the rules for inspection I receive the following expected output:

kim.mein-iserv.de ~ # ferm --noexec --lines rules.conf 
# Generated by ferm 2.3 on Fri Jan 18 13:37:34 2019
*mangle
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*raw
:OUTPUT ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*filter
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT --protocol TCP --destination fe80::1 --jump REJECT
COMMIT
*nat
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
# Generated by ferm 2.3 on Fri Jan 18 13:37:34 2019
*filter
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT --protocol tcp --destination 4.6.4.6 --jump REJECT
-A INPUT --protocol tcp --destination 4.4.4.4 --jump REJECT
COMMIT
*nat
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*raw
:OUTPUT ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*mangle
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT

O.K. so far, so good! Let's assume for some reason we need to handle IPv4 and IPv6 separately, e.g. because we want to save the rules to a file and import them later using iptables-restore. This is made up of course but I do actually have a reason to do this in my toolchain that can't be easily avoided.

For IPv4 everything appears to be just fine:

kim.mein-iserv.de ~ # ferm --domain ip --noexec --lines rules.conf
# Generated by ferm 2.3 on Fri Jan 18 13:41:23 2019
*nat
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*mangle
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*filter
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT --protocol tcp --destination 4.6.4.6 --jump REJECT
-A INPUT --protocol tcp --destination 4.4.4.4 --jump REJECT
COMMIT
*raw
:OUTPUT ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT

And now let's check IPv6 output:

kim.mein-iserv.de ~ # ferm --domain ip6 --noexec --lines rules.conf
# Generated by ferm 2.3 on Fri Jan 18 13:42:21 2019
*nat
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*filter
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT --protocol tcp --destination 4.6.4.6 --jump REJECT
-A INPUT --protocol TCP --destination fe80::1 --jump REJECT
COMMIT
*raw
:OUTPUT ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT
*mangle
:FORWARD ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
COMMIT

An IPv4 address sneaked into our rules! That breaks our ruleset.

You might think at this point that --domain has somehow set the default domain and this might sound like reasonable behaviour at first glance, however this makes parsing mixed rulesets a giant pain. The documentation doesn't mention default behaviour overrides either:

       --domain {ip|ip6}
                   Handle only the specified domain. ferm output may be empty if the domain is not configured in the input file.

It actually sounds a lot like unexpected behaviour. This is my reason for filing this bug.

Thank you for looking into this.

Best regards,
Kim-Alexander Brodowski