Linux Netfilter discussions
 help / color / mirror / Atom feed
From: trentbuck@gmail.com (Trent W. Buck)
To: netfilter@vger.kernel.org
Subject: Re: Is viewing a "candidate" ruleset in 'nft list ruleset' format possible?
Date: Thu, 30 Apr 2020 18:05:40 +1000	[thread overview]
Message-ID: <87lfmdpfe3.fsf@goll.lan> (raw)
In-Reply-To: 87ees5wt76.fsf@goll.lan

[-- Attachment #1: Type: text/plain, Size: 1533 bytes --]

trentbuck@gmail.com (Trent W. Buck) writes:

> Duncan Roe <duncan_roe@optusnet.com.au> writes:
>
>> On Wed, Apr 22, 2020 at 12:34:26PM -0400, Martin Gignac wrote:
>>> > You can simply put "list ruleset" at the bottom of the foo.nft file.
>>> > However in my experience this routinely gives outright wrong rulesets
>>> > (as at nftables 0.9.1), so I don't trust it.
>>
>> "list ruleset" at the bottom of an nft script is completely accurate.
>> The command "nft list ruleset" discards portions of rules that are implicit, in the
>> interests of brevity.
>
> Sorry, I don't have a testable example.
> If I run into this again, I'll try to keep proper records so I can file
> a proper bug report!

Hooray, I got one (attached).

You can see "list ruleset" inside /etc/nftables.conf ends with

    table inet my_filter {
    }

where running "nft list ruleset" immediately afterwards, it shows all
the chains and rules that are actually there:

    table inet my_filter {
            chain my_input {
                    type filter hook input priority filter; policy drop;
                    jump my_prologue comment "deal with boring conntrack/loopback/ICMP/ICMPv6"
                    tcp dport 22 accept
                    jump my_epilogue
            }
    [...]
    }

It happens reliably if I run "nft delete table inet my_filter" before "/etc/nftables.conf",
but NOT if I run  "/etc/nftables.conf" before "/etc/nftables.conf".

To me this feels like "list ruleset" is sometimes running before the block
immediately before it.


[-- Attachment #2: transcript showing "list ruleset" inside foo.nft giving weird output --]
[-- Type: text/plain, Size: 11808 bytes --]

root@zippy:~# nft delete table inet my_filter
root@zippy:~# /etc/nftables.conf
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
		iifname "virbr1" meta l4proto udp udp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto tcp tcp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto udp udp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto tcp tcp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto udp udp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto tcp tcp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto udp udp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto tcp tcp dport 67 counter packets 0 bytes 0 accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
		iifname "virbr1" oifname "virbr1" counter packets 0 bytes 0 accept
		oifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		oifname "virbr0" ip daddr 192.168.122.0/24 ct state related,established counter packets 0 bytes 0 accept
		iifname "virbr0" ip saddr 192.168.122.0/24 counter packets 0 bytes 0 accept
		iifname "virbr0" oifname "virbr0" counter packets 0 bytes 0 accept
		oifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
		oifname "virbr1" meta l4proto udp udp dport 68 counter packets 0 bytes 0 accept
		oifname "virbr0" meta l4proto udp udp dport 68 counter packets 0 bytes 0 accept
	}
}
table ip6 filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
	}
}
table bridge filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
	}
}
table ip mangle {
	chain PREROUTING {
		type filter hook prerouting priority mangle; policy accept;
	}

	chain INPUT {
		type filter hook input priority mangle; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority mangle; policy accept;
	}

	chain OUTPUT {
		type route hook output priority mangle; policy accept;
	}

	chain POSTROUTING {
		type filter hook postrouting priority mangle; policy accept;
		oifname "virbr1" meta l4proto udp udp dport 68 counter packets 0 bytes 0 # CHECKSUM fill
		oifname "virbr0" meta l4proto udp udp dport 68 counter packets 0 bytes 0 # CHECKSUM fill
	}
}
table ip nat {
	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
	}

	chain INPUT {
		type nat hook input priority 100; policy accept;
	}

	chain POSTROUTING {
		type nat hook postrouting priority srcnat; policy accept;
		ip saddr 192.168.122.0/24 ip daddr 224.0.0.0/24 counter packets 0 bytes 0 return
		ip saddr 192.168.122.0/24 ip daddr 255.255.255.255 counter packets 0 bytes 0 return
		meta l4proto tcp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade to :1024-65535 
		meta l4proto udp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade to :1024-65535 
		ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade 
	}

	chain OUTPUT {
		type nat hook output priority -100; policy accept;
	}
}
table ip sshguard {
	set attackers {
		type ipv4_addr
		flags interval
	}

	chain blacklist {
		type filter hook input priority filter - 10; policy accept;
		ip saddr @attackers drop
	}
}
table ip6 sshguard {
	set attackers {
		type ipv6_addr
		flags interval
	}

	chain blacklist {
		type filter hook input priority filter - 10; policy accept;
		ip6 saddr @attackers drop
	}
}
table inet my_filter {
}
root@zippy:~# nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
		iifname "virbr1" meta l4proto udp udp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto tcp tcp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto udp udp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr1" meta l4proto tcp tcp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto udp udp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto tcp tcp dport 53 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto udp udp dport 67 counter packets 0 bytes 0 accept
		iifname "virbr0" meta l4proto tcp tcp dport 67 counter packets 0 bytes 0 accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
		iifname "virbr1" oifname "virbr1" counter packets 0 bytes 0 accept
		oifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		oifname "virbr0" ip daddr 192.168.122.0/24 ct state related,established counter packets 0 bytes 0 accept
		iifname "virbr0" ip saddr 192.168.122.0/24 counter packets 0 bytes 0 accept
		iifname "virbr0" oifname "virbr0" counter packets 0 bytes 0 accept
		oifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
		iifname "virbr0" counter packets 0 bytes 0 reject
		iifname "virbr1" counter packets 0 bytes 0 reject
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
		oifname "virbr1" meta l4proto udp udp dport 68 counter packets 0 bytes 0 accept
		oifname "virbr0" meta l4proto udp udp dport 68 counter packets 0 bytes 0 accept
	}
}
table ip6 filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
	}
}
table bridge filter {
	chain INPUT {
		type filter hook input priority filter; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority filter; policy accept;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy accept;
	}
}
table ip mangle {
	chain PREROUTING {
		type filter hook prerouting priority mangle; policy accept;
	}

	chain INPUT {
		type filter hook input priority mangle; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority mangle; policy accept;
	}

	chain OUTPUT {
		type route hook output priority mangle; policy accept;
	}

	chain POSTROUTING {
		type filter hook postrouting priority mangle; policy accept;
		oifname "virbr1" meta l4proto udp udp dport 68 counter packets 0 bytes 0 # CHECKSUM fill
		oifname "virbr0" meta l4proto udp udp dport 68 counter packets 0 bytes 0 # CHECKSUM fill
	}
}
table ip nat {
	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
	}

	chain INPUT {
		type nat hook input priority 100; policy accept;
	}

	chain POSTROUTING {
		type nat hook postrouting priority srcnat; policy accept;
		ip saddr 192.168.122.0/24 ip daddr 224.0.0.0/24 counter packets 0 bytes 0 return
		ip saddr 192.168.122.0/24 ip daddr 255.255.255.255 counter packets 0 bytes 0 return
		meta l4proto tcp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade to :1024-65535 
		meta l4proto udp ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade to :1024-65535 
		ip saddr 192.168.122.0/24 ip daddr != 192.168.122.0/24 counter packets 0 bytes 0 masquerade 
	}

	chain OUTPUT {
		type nat hook output priority -100; policy accept;
	}
}
table ip sshguard {
	set attackers {
		type ipv4_addr
		flags interval
	}

	chain blacklist {
		type filter hook input priority filter - 10; policy accept;
		ip saddr @attackers drop
	}
}
table ip6 sshguard {
	set attackers {
		type ipv6_addr
		flags interval
	}

	chain blacklist {
		type filter hook input priority filter - 10; policy accept;
		ip6 saddr @attackers drop
	}
}
table inet my_filter {
	chain my_input {
		type filter hook input priority filter; policy drop;
		jump my_prologue comment "deal with boring conntrack/loopback/ICMP/ICMPv6"
		tcp dport 22 accept
		jump my_epilogue
	}

	chain my_forward {
		type filter hook forward priority filter; policy drop;
		jump my_prologue comment "deal with boring conntrack/loopback/ICMP/ICMPv6"
		jump my_epilogue
	}

	chain my_prologue {
		ct state vmap { invalid : drop, established : accept, related : accept }
		ct status dnat accept
		meta iiftype loopback accept
		icmp type echo-request accept
		icmpv6 type { echo-request, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
	}

	chain my_epilogue {
	}
}
root@zippy:~# cat /etc/nftables.conf
#!/usr/sbin/nft --file

## NOTE: we add+delete each table (not "flush ruleset"), because
##       otherwise we would wipe out sshguard & libvirtd tables.
#flush ruleset
add table inet my_filter        # idempotent
delete table inet my_filter     # not idempotent


table inet my_filter {
    chain my_input {
        type filter hook input priority filter
        policy drop
        jump my_prologue  comment "deal with boring conntrack/loopback/ICMP/ICMPv6"

        # YOUR RULES HERE.
        # NOTE: service names resolve via nss (/etc/hosts) only in nft 0.9.1+!
        tcp dport ssh  accept
        jump my_epilogue
    }
    chain my_forward {
        type filter hook forward priority filter
        policy drop
        jump my_prologue  comment "deal with boring conntrack/loopback/ICMP/ICMPv6"
        # YOUR RULES HERE.
        jump my_epilogue
    }
    # We want output to be "allow all", so we don't even create a chain.
    #chain my_output {
    #    type filter hook output priority filter
    #    policy accept
    #}

    chain my_prologue {
        ct state vmap { established: accept, related: accept, invalid: drop }
        ct status dnat  accept
        iiftype loopback  accept
        icmp type echo-request  accept
        icmpv6 type {
            echo-request,
            nd-neighbor-solicit,
            nd-router-advert,
            nd-neighbor-advert }  accept
    }
    chain my_epilogue {
    }
}

# This is here to aid debugging.
# Note that its output WILL NOT MATCH a later "nft list ruleset".
list ruleset
root@zippy:~# dpkg-query -W nftables
nftables	0.9.3-2~bpo10+1
root@zippy:~# nft --version
nftables v0.9.3 (Topsy)
root@zippy:~# uname -a
Linux zippy 5.4.0-0.bpo.4-amd64 #1 SMP Debian 5.4.19-1~bpo10+1 (2020-03-09) x86_64 GNU/Linux
root@zippy:~# 

  reply	other threads:[~2020-04-30  8:05 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-19  2:12 Is viewing a "candidate" ruleset in 'nft list ruleset' format possible? Martin Gignac
2020-04-22  4:51 ` Trent W. Buck
2020-04-22 16:34   ` Martin Gignac
2020-04-23  2:06     ` Duncan Roe
2020-04-23 12:10       ` Martin Gignac
2020-04-30  3:25       ` Trent W. Buck
2020-04-30  8:05         ` Trent W. Buck [this message]
2020-04-30  3:10     ` Trent W. Buck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87lfmdpfe3.fsf@goll.lan \
    --to=trentbuck@gmail.com \
    --cc=netfilter@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox