All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.