On Mon, Feb 24, 2025 at 04:25:58PM -0500, Laine Stump wrote:
> On 2/21/25 7:02 PM, robinleepow...@gmail.com wrote:
> > So I, like many other people, have hit problems with nftables ordering, as
> > has been discussed on this mailing list MANY TIMES.
> >
> > This whole thing seemed ridiculous so I asked the nftables people about
> > what one is *supposed* to do in this situation. It turns out that the
> > standard solution is for libvirt's nftables rules to set a packet mark
> > (there's a collision possibility here but it's a 32 bit integer if you pick
> > one at random it shouldn't be a problem) and then the user adds a rule to
> > exclude packets with that mark from any reject rules they might have, or
> > explicitly accept marked packets in their own chains, or whatever.
>
> Was the discussion on a public forum somewhere? I'd like to look at exactly
> what they said.
Yep! Sorry, thought I linked to it, oops.
https://lore.kernel.org/netfilter/132daf73-668f-4321-8945-c809db227...@redhat.com/T/#t
> > It's not *as nice* as the iptables situation, but having documentation that
> > says "if you're using nftables make sure that packets with mark 79892 are
> > accepted in all your chains" is quite straightforward compared to the
> > current situation of "LOL good luck". (I'm not blaming anyone there!, the
> > current situation is impossible for libvirt to navigate and it's not
> > anyone's fault.)
>
> It does still require that the other utilities know this secret number, and
> agree to "anti-reject" it as we've requested, though. Also doesn't this
> require that libvirt's table is processed first, before the other utilities'
> tables? Otherwise, if the other tables are traversed before libvirt has a
> chance to mark the packet with the special number, they won't get the
> signal, so they'll reject the traffic. So I we would have set our table as a
> higher priority, but then what if someone else sets their table with an
> *even higher* priority? e.g. firewalld has "priority filter + 10" for its
> forwarding rules, so could make ours "priority filter + 20", but what if,
> e.g. docker decided to make theirs "priority filter +50"?). (yes, that's all
> a rhetorical question. I guess in the end everything like this that we do
> will chip away a bit more at the list of people who encounter problems; it
> will never reach 0, but it will at least get closer :-))
Yep, those are all real concerns. :sigh:
> Aside from that, libvirt's nftables rules are default accept, and it has no
> rules looking at traffic that is destined for the host, only for forwarded
> traffic that is going *through* the host, mainly with the intent of
> rejecting stuff it doesn't like. So are you/they suggesting that this
> forwarded traffic be marked with the special "libvirt code"? Or that we
> should also add back rules that match input DNS/DHCP/TFTP on the
> libvirt-created bridges, and have them both accept and mark those packets?
I think it'd have to be the latter to actually work.
> > If y'all don't like that, what's working excellently for me is adding
> > `iifname "virbr*" accept` to my rule chain. FWIW.
>
> Just keep in mind that "iifname" has to fetch the name of the interface and
> do a string comparison for each packet, while "iif" just does a quick
> comparison of ifindex, which I think is already saved away in the skb (of
> course wildcards aren't possible in that case, but if you have just a couple
> of libvirt networks it's still more efficient to have a rule using "iif" for
> each interface.
The reason I have to use iifname is that at the time my rules are
loaded, the virbr interfaces *don't exist*. Like I actually have no
choice; it won't work the other way, unless I'm badly missing
something.
> > It was very hard to navigate through this situation because there's no
> > documentation that this problem even exists.
>
> Yeah, that's my fault. When I added the nftables backend, I forgot to update
> https://libvirt.org/firewall.html (which is in docs/firewall.rst in the
> libvirt sources). (also at the time I wrote the code, I I keep remembering
> that I should do that, but only when I'm in the middle of something else and
> somehow I haven't managed to even write it down on a list.
No attack intended; FOSS work is hard. :)
> > My suggestion is to describe the situation at
> > https://libvirt.org/firewall.html and suggest the virbr* fix, and down the
> > road maybe look at this mark thing.
>
> That's a kind of a broad solution though - libvirt's rules only reject
> specific traffic between libvirt-created bridges (and incoming traffic from
> outside a bridge's direct connects in the case of forward mode='nat'),
> Anywhere they allow traffic, they allow *all* of it. The real problematic
> stuff is traffic between the guests and the host (the rules we've had for
> iptables that are absent in nftables are those to allow inbound DNS, DHCP,
> and TFTP that are arriving on a virbr* interface, and destined for the
> host). If you allow *all* traffic for virbr*, then you're leaving the host
> wide open to all traffic from any guests (since libvirt's own rules are
> default accept). I think the suggestion needs to be more than just "allow
> all incoming on virbr*".
That's fair; I suppose we could post something equivalent to the old
iptables rules?
> > I'd like to help. I'm happy to write up issues for this, and I'm happy to
> > write the updates to the firewall docs; just tell me what you'd like me to
> > do.
>
> firewall.rst should really be a shortened intro that links to the current
> firewall.html for iptables (maybe renaming it "iptables.rst/html"?), and to
> a new nftables.rst/html for information about nftables (including an
> explanation of the "many tables, all must resolve to 'accept' problem.)
>
> Since I've never gotten around to it in spite of wanting it done, I'd
> certainly be happy to review an update done by anyone else :-)
Acknowledged. :)