Gast-DNS unter libvirt reparieren, die eine markbasierte VPN-Firewall blockiert
Eine markbasierte VPN-Firewall verwirft Gast-DNS, bevor irgendeine Filterkette sie sieht. Eine Regel mit mangle-Priorität markiert die Abfrage und ihre Antwort, ohne dein LAN zu öffnen.
Gäste im Standard-libvirt-Netz lösen Namen perfekt auf, bis das WireGuard-Interface hochkommt, und dann bleibt jede Auflösung an derselben Stelle hängen. dnsmasq lauscht weiterhin auf 192.168.122.1:53, der Gast hat diese Adresse weiterhin als Resolver, und die Abfrage kommt weiterhin an. Geändert hat sich, dass die eigene Upstream-Abfrage des Hosts oder die Antwort darauf jetzt von einer Regel verworfen wird, die ausgewertet wird, bevor irgendeine Filterkette zum Zug kommt, die man bearbeiten würde. Der Ausweg ist eine Markierung, die früh genug gesetzt wird, auf einer Verbindung, die die Antwort erbt.
Gäste verlieren DNS, sobald der Tunnel hochkommt
Bestätige die Form, bevor du etwas änderst. Bringe den Tunnel herunter, führe dig @192.168.122.1 example.com von einem Gast aus und sieh zu, wie es antwortet. Bringe den Tunnel hoch, wiederhole es und sieh zu, wie es in einen Timeout läuft. Dieses Ergebnispaar schließt ein defektes libvirt-Netz, eine falsche Resolver-Adresse und einen toten dnsmasq in einem Schritt aus.
Sieh dann auf die Host-Seite. Wenn dnsmasq die Abfrage und ihre Upstream-Weiterleitung protokolliert, ist das Paket angekommen und der Fehler liegt am Ausgang. Wenn dnsmasq gar nichts protokolliert, wird die Gast-Abfrage am Eingang verworfen, und die Ausnahme gehört an einen anderen Hook als den, den dieser Artikel markiert.
Warum eine Accept-Regel in einer späteren Kette nie greift
Eine markbasierte VPN-Firewall entscheidet anhand der Paketmarke oder der Verbindungsmarke, nicht anhand deiner Quelladresse. Alles, was ohne die erwartete Marke am physischen Interface ankommt, wird abgelehnt, und diese Ablehnung geschieht in dem Regelsatz, der den Markentest besitzt. Eine ip saddr 192.168.122.0/24 accept-Zeile, die einer späteren Kette hinzugefügt wird, wird für dieses Paket schlicht nie herangezogen, weshalb die naheliegende Regel korrekt aussieht und nichts ändert.
Sie so weit zu öffnen, bis etwas funktioniert, ist die zweite Falle. Das gesamte libvirt-Subnetz im Eingangspfad des Hosts zu akzeptieren, öffnet jeden Host-Dienst für Gäste, während der tatsächliche Bedarf ein einziger Port ist.
Der Mechanismus, der eine enge Ausnahme ermöglicht, ist die Verbindungsverfolgung. Wenn du ct mark auf ein Paket setzt, wird der Wert im conntrack-Eintrag gespeichert und nicht nur im Paket, sodass jedes Paket dieser Verbindung ihn danach trägt, einschließlich der Antwort vom Host zurück zum Gast. Das ist der ganze Trick: Markiere die Anfrage einmal, und der Rückweg ist bereits markiert.
Markiere die Abfrage, bevor die VPN-Tabelle sie sieht
Lege die Ausnahme in eine eigene Tabelle, damit ein späterer Leser sie findet, ohne die VPN-Regeln zu parsen:
table inet allowedLocal {
chain guest_dns {
type filter hook input priority mangle; policy accept;
ip saddr 192.168.122.0/24 meta l4proto { tcp, udp } \
th dport 53 ct mark set 0x00000f41
}
}
priority mangle ist negativ, was diese Kette vor die gewöhnlichen Filterketten setzt, die das VPN-Paket bei Priorität null installiert. Die Hook-Reihenfolge macht die Regel wirksam; dieselbe Regel in einer Kette, die nach der VPN-Kette sortiert, ist Dekoration.
Die Markennummer selbst ist nicht portabel. Nimm den Wert, den die installierten VPN-Regeln für ihren eigenen Verkehr akzeptieren, lies ihn aus dem laufenden Regelsatz und verwende ihn. Eine falsche Marke erzeugt eine Regel, die sauber lädt, jede Abfrage trifft und nichts zulässt.
Halte das Loch so breit wie Port 53
So wie es dasteht, erlaubt dies DNS vom libvirt-Subnetz zum Host über TCP oder UDP Port 53 und sonst nichts. Es lässt Gäste nicht ins Internet außerhalb des Tunnels und lässt den Host keine Verbindungen zu Gästen öffnen. Wenn ein Gast später einen anderen Host-Dienst braucht, füge eine separate Regel hinzu, die diesen Zielport nennt, statt diese hier zu lockern.
Sei ehrlich darüber, was du eintauschst. Ein Gast, der einen Resolver erreichen kann, kann auch beliebige Daten über DNS-Abfragen tunneln, und diese Ausnahme ist eine bewusste Lücke in der VPN-Grenze und keine Aussage, dass das lokale Netz vertrauenswürdig ist. Die Quelle auf 192.168.122.0/24 zu beschränken hält die Lücke von jedem anderen lokalen Subnetz fern, und Abfragen von dieser Quelle zu zählen ist billig, wenn die Bedrohung für dich zählt.
Lass sie einen Neustart überleben und beweise beide Hälften
Eine an einer Shell-Eingabeaufforderung getippte Regel verschwindet beim nächsten Start, und eine Regel, die geladen wird, nachdem das VPN-Interface bereits Verkehr durchlässt, verliert das Rennen bei der ersten Verbindung. Lege die Tabelle in die persistente nftables-Konfiguration des Hosts oder in eine Unit, die vor dem VPN-Dienst geordnet ist, und prüfe die Reihenfolge, statt sie anzunehmen.
Die Verifikation braucht drei getrennte Antworten. Bestätige, dass die Kette geladen und zuerst geordnet ist, bestätige, dass der conntrack-Eintrag die Marke in beiden Richtungen zeigt, und bestätige, dass eine Gast-Auflösung eine Adresse zurückgibt. Bestätige dann die andere Hälfte: gewöhnlicher Gast-Webverkehr zu einem öffentlichen Host schlägt weiterhin fehl, solange der Tunnel unten ist oder blockiert. Wenn DNS funktioniert und alles andere leckt, ist deine Regel breiter als die oben.
Wenn Auflösungen trotz gesetzter Marke weiterhin fehlschlagen, widerstehe dem Drang, die Quelle zu erweitern. Prüfe, wohin dnsmasq weiterleitet, ob der Gast-Resolver auf 192.168.122.1 oder auf eine öffentliche Adresse zeigt, die jemand eingetippt hat, und ob die Abfrage den Host überhaupt erreicht. Markieren lässt das Paket durch und sonst nichts, also bleiben ein schlechtes Upstream oder ein defektes virtuelles Netz defekt, egal wie viele Regeln du hinzufügst.