Ansichten eines Informatikers

Design by ignorance

Hadmut
16.7.2024 15:04

Update zu Linux-Paketfilter nftables: Broken by design.

Ich hatte doch neulich beschrieben, dass es da einen groben Designfehler in dem neuen Paketfilter „nftables“ von Linux gibt. Nachdem mir inzwischen doch die Gnade erteilt wurde, überhaupt bug reports einreichen zu dürfen, und ich das auch getan hatte, hatte ein anderer Nutzer, dem ebenfalls aufgefallen war, dass das nicht taugt, noch einen technisch interessanten Kommentar hinzugefügt.

Bei Regelsätzen in der IT (nicht nur bei Firewalls, sondern generell bei vielen Dingen, in denen man regelbasiert Attribute setzt, auch bei Softwarekonfigurationen wie etwa ssh-config oder sonstigen Regelsätzen wie in Mail- und Proxyregeln) gibt es zwei Ansätze: first match und last match. Manchmal gilt die erste Regel, die passt, egal was danach kommt. Und manchmal gilt die letzte Regel, die passt, egal was davor kam.

Beides hat so seine Daseinsberechtigung. Manchmal fängt man mit den feinsten Regeln an und macht die Regeln immer grober, dann setzt man first match ein, und das kommt der intuitiven Denkweise mancher Leute näher. Und manchmal will man erst mal das Grundsätzliche hinschreiben und dann die Ausnahmen davon aufzählen, dann wählt man last match, also die umgekehrte Reihenfolge. Das wird meist dann bevorzugt, wenn die Aktionen oder Resultate selbst kumulativ wirken sollen. Letztlich ist beides gleich mächtig, und man muss sich beim Schreiben von irgendwelchen Regeln immer erst mal vergewissern (und weil nicht immer so klar dokumentiert, manchmal auch einfach ausprobieren), ob irgendeine Software ihre Regelsätze first match oder last match anwendet. Es gibt auch noch andere Methoden, wonach die spezifischere, also kleinteiligere Regel Vorrang vor der groberen hat, egal in welcher Reihenfolge sie da stehen. Die Juristen haben so etwas, dass das spezifischere Gesetz Vorrang vor dem allgemeineren hat, nennt sich der lex-specialis-Grundsatz, aber auch den lex-posterior-Grundsatz, wonach das jüngere Gesetz, also das später erlassene, Vorrang hat. (Die haben noch einen anderen Fachbegriff für den Vorrang des Spezielleren vor dem Allgemeineren, der fällt mir aber gerade partout nicht ein, obwohl ich ihn schon selbst verwendet habe.)

Bei Firewallregeln ist mir, soweit ich mich erinnern kann, bisher immer nur first match untergekommen, der Kommentar dort beschreibt aber, dass pf von OpenBSD nach dem last match Prinzip arbeite.

Und besagter Kommentator schreibt auch – und das völlig zutreffend – dass die nftables deshalb fehlerhaft seien, weil sie beide Methoden mischen: Bei drop/reject zähle first match, bei accept aber würde nach last match gearbeitet, wobei ein Paket dann, wenn es auf ein reject trifft, von last match nach first match springt.

Das ist der zentrale Fehler, dass sie nicht klar first match oder last match machen, sondern beides wild durcheinander mischen. Das kann nicht funktionieren.

Ich hatte das zwar nicht so explizit mit diesen Begriffen ausformuliert (hätte ich sollen), genau dazu in meinem Bug Report aber schon erwähnt, wie man das in solchen Fällen, dass hintereinander mehrere Regelsätze abgearbeitet werden müssen, dadurch löst, dass man neben accept/reject noch eine weitere Aktion hinzufügt, mit „proceed“ oder „continue“ oder ähnlicher Bezeichnung verwendet, und damit explizit sagen kann, dass das Ergebnis noch unentschied ist, und mit dem nächsten Regelsatz fortzufahren ist, also quasi neben „Ja“ und „Nein“ noch ein „Weiß nicht“ eingeführt wird, das dann dazu führt, dass mit dem nächsten Regelsatz weitergemacht wird. Das ist eigentlich gängige Praxis in solchen Fällen. Beispielsweise heißt das in den Regelsätzen von Postfix, einem Mail-Relay, über die Annahme oder Ablehnung einer E-Mail entschieden wird, dann „DUNNO“ (für don’t know, neben „OK“ und „REJECT“), womit dann mit dem nächsten Regelsatz weitergemacht wird. Das ist eigentlich ein bekanntes und bewährtes Prinzip um genau dieses Problem zu lösen, was aber den Netfilter-Leuten, die nftables geschrieben haben, offenbar nicht geläufig war – fehlende Sachkunde.

Dazu schreibt mir da nun einer von denen:

Hi,

Please note that iptables works exactly the same way, you just don’t have the flexibility to add arbitrary base chains.

Take security table for instance: A drop rule in its INPUT chain can’t be overridden from filter table, no matter what. Vice-versa: An accept rule in security table’s INPUT chain will not see any packet if filter table’s INPUT chain dropped them already.

All this is hard to change: Nobody would expect a packet to no longer appear in filter’s INPUT chain after mangle’s PREROUTING chain had an ACCEPT verdict for it.

You’re free to design the basic ruleset layout of base and non-base chains in nftables. But you also have to define (and enforce) the rules of how different actors add their ruleset snippets to it. A simpler way may be to use a coordinating daemon such as firewalld.

The “major design flaw” is expecting nftables to implement coordination between concurrent users because its design supports them in the first place. We’ve discussed this misunderstanding pretty extensively at netfilter workshops in the past and haven’t even found a feasible way to please users falling for this, let alone compatibility to existing rulesets.

The substantial problem with the suggested “proceed” verdict is that one has to change the “accept” one which is not compatible. The alternative of implementing a “really accept” is flawed in that it will only lead to requests for support of overriding it and thus back to square one.

We may continue discussing why things are the way they are, but please don’t expect this to change.

Cheers, Phil

Die Antwort ergibt keinen Sinn, weil das Problem unter iptables ja gar nicht auftrat, eben weil es dort nur eine Haupt-Chain gab, und strikt first match galt. Der redet völlig am Problem vorbei und scheint es nicht einmal zu verstehen.

The “major design flaw” is expecting nftables to implement coordination between concurrent users because its design supports them in the first place. We’ve discussed this misunderstanding pretty extensively at netfilter workshops in the past and haven’t even found a feasible way to please users falling for this, let alone compatibility to existing rulesets.

The substantial problem with the suggested “proceed” verdict is that one has to change the “accept” one which is not compatible. The alternative of implementing a “really accept” is flawed in that it will only lead to requests for support of overriding it and thus back to square one.

Das ist bullshit. Denn es ging ja nicht darum, dass man von nftables erwartete, „concurrent users“ zu koordinieren, sondern im Gegenteil, es so zu bauen, dass man sich nicht koordinieren muss. Beim jetzigen Stand bin ich gezwungen, in meinen Firewall-Regeln die LXD-Regeln in meinen Firewall-Regeln zu wiederholen, damit sie wirken können, und wenn man Regeln doppelt eintragen muss, damit sie wirken, kann etwas nicht stimmen.

Und der Brüller ist dann dieser Satz:

We may continue discussing why things are the way they are, but please don’t expect this to change.

Obwohl er zugibt, dass sie vom Problem überfordert sind und keine Lösung dafür gefunden haben (obwohl eine bewährte Lösung ja existiert und seit Jahrzehnten bekannt und gängige Praxis ist, die sie nur nicht kannten, oder die sie überforderte), habe man das hinzunehmen, wie es ist. Also ob einem das bei einem Ding, das nicht funktioniert, helfen würde, darüber zu diskutieren, warum es so kaputt entworfen hat.

Das ist der neue Zeitgeist, der sich da breit gemacht hat, dieses „code of conduct“-Denken: Jeder Honk darf mitbauen, egal ob Ahnung oder nicht, und man hat das dann zu akzeptieren, egal ob es funktioniert oder nicht.

Ich wollte da gerade noch einen bösen Kommentar daruntersetzen, nämlich dass es nicht hilft, mit ihnen rumzudiskutieren, warum sie das so gemacht haben (und die Frage, wo man das nachlesen könnte), sondern sie mal darstellen sollten, wie das zu verwenden wäre, und wie man ihrer Ansicht nach die Regeln zu bauen hätte, habe aber schon keine Schreibrechte mehr auf diesen Bug, kann keinen Kommentar mehr darunter fügen, bekommen nur eine Fehlermeldung.

Entweder hat man mir den Account gesperrt, oder es liegt daran, dass man den Bug auf „RESOLVED WONTFIX“ gesetzt hat.

Es zeigt sehr gut, wie Open Source-Software durch dieses Woke-Denken und den code of conduct-Ansatz systematisch zerstört wird: Man braucht keinen Angriff, keine nachweisbare Attacke. Es reicht, überall Leute reinzusetzen, die das Ding nicht verstanden haben, und die trotzdem akzeptiert werden müssen. Das Ergebnis ist kaputt.