Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
netfence — Wie Envoy xDS, aber für eBPF-Filter | Kitploit
Tools/GitHubGitHub/danthegoodman1/netfence
Cloud-Infrastruktur-SicherheitContainer-SicherheitIDS/IPS-UmgehungNetzwerksicherheitCloud-SicherheitDevSecOpsFehlkonfigurationDNS-Analyse
GitHubdanthegoodman1/netfence

netfence

Wie Envoy xDS, aber für eBPF-Filter

Repository anzeigen
1014vor 1 MonatVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Netfence

Wie Envoy xDS, aber für eBPF-Filter.

Netfence läuft als Dienstprogramm auf Ihren VM/Container-Hosts und injiziert automatisch eBPF-Filterprogramme in Cgroups und Netzwerkschnittstellen, mit einem integrierten DNS-Server, der erlaubte Domänen auflöst und die IP-Erlaubnisliste befüllt.

Netfence-Daemons können allein über ihre lokale Unix-Socket-API gesteuert werden oder sich mit einer zentralen Steuerungsebene verbinden, die Sie über gRPC implementieren, um Erlaubnislisten/Sperrlisten mit Ihrem Backend zu synchronisieren.

Ihre Steuerungsebene schiebt Netzwerkregeln wie ALLOW *.pypi.org oder ALLOW 10.0.0.0/16 an angehängte Schnittstellen/Cgroups. Wenn eine VM/ein Container DNS abfragt, löst Netfence dies auf, fügt die IPs zum eBPF-Filter hinzu und verwirft den Verkehr zu unbekannten IPs, bevor er den Host verlässt, mit einem Overhead auf dem warmen Pfad, der in aktuellen Benchmarks praktisch nicht von einem normalen Socket-Connect zu unterscheiden ist.

Features

  • eBPF-Filter an Netzwerkschnittstellen (TC) oder Cgroups anhängen
  • Richtlinienmodi: deaktiviert, Erlaubnisliste, Sperrliste, alles blockieren
  • IPv4- und IPv6-CIDR-Unterstützung mit optionalen TTLs
  • Pro-Anhang UDP/TCP-DNS-Server mit Domänen-Erlaubnisliste/Sperrliste und geordneten Upstream-Überschreibungen
  • Domänenregeln unterstützen Subdomains mit spezifitätsbasiertem Matching (spezifischere Regeln gewinnen)
  • Aufgelöste Domänen befüllen automatisch den IP-Filter
  • Metadaten zu Daemons und Anhängen zur Zuordnung zu VM-ID, Mandant usw.
  • Unterstützung für das Weiterleiten von DNS-Abfragen an die Steuerungsebene, um DNS-Entscheidungen pro Anhang zu treffen

Sicherheitshinweis: Standard-Ausnahmen

Im Erlaubnislistenmodus ist IPv4-Link-Local (169.254.0.0/16) standardmäßig nicht mehr automatisch erlaubt – der Cloud-Metadatendienst (169.254.169.254) ist also blockiert, sofern nicht explizit erlaubt. Dies ist beabsichtigt: Der Metadatendienst ist ein Ziel für Credential-Diebstahl, und sandboxed Workloads müssen ihn nicht implizit erreichen können. Localhost (127.0.0.0/8, ::1) und IPv6-Nachbarschaftserkennung (fe80::/10, ff02::/16) bleiben standardmäßig erlaubt, damit grundlegende Konnektivität und NDP funktionieren. Um den Metadatendienst für einen Workload zuzulassen, erlauben Sie 169.254.169.254/32 (eine Überschreibung pro Anhang über die Steuerungsebene ist als geplante Erweiterung vorgesehen).

IPv4-Broadcast (255.255.255.255) und Multicast (224.0.0.0/4) haben keine Ausnahme und unterliegen der Richtlinie. Daher wird im TC-Erlaubnislistenmodus Verkehr wie DHCP-Erneuerungs-Broadcasts blockiert, sofern nicht explizit erlaubt. Ausnahme-Prüfungen laufen vor der Sperrliste, daher kann ein ausgenommener Bereich nur blockiert werden, indem seine Ausnahme deaktiviert wird – und da IPv4-Link-Local jetzt standardmäßig deaktiviert ist, kann der Sperrlistenmodus auch den Metadatendienst blockieren.

Unterschiede zu anderen Optionen

Einige wesentliche Vorteile dieser Lösung, die andere Optionen normalerweise nicht bieten:

  • Sofortiges Trennen bestehender Verbindungen, wenn Regeln geändert werden, um eine IP zu verbieten (nur bei Schnittstellen-Anhang)
  • Unterstützung aller Netzwerkprotokolle und direkte IP-Netzwerkverbindungen. Beispielsweise erlaubt das großartige httpjail keine direkten Verbindungen zu IPs oder direkte TCP/UDP-Verbindungen wie zu Datenbanken.
  • Dynamische DNS-Auflösung und Filterung vor der Auflösung (damit es keine Exfiltration von secretdata.someattacker.com gibt)

Meines Wissens nach bietet keine andere Lösung alle diese Funktionen zusammen.

Bekannte Einschränkung: Cgroup-Anhänge filtern auf der Socket-Ebene (connect/sendmsg-Hooks), daher kann ein Prozess mit CAP_NET_RAW Rohpakete erstellen, die diese umgehen. Verwenden Sie einen TC-Anhang (Schnittstelle), der auf der Geräteebene filtert, für Workloads, die CAP_NET_RAW halten könnten.

Allerdings hat dies etwas mehr Overhead als so etwas wie httpjail.

Leistungsübersicht

Diese Zahlen wurden im privilegierten Docker-Linux-Gate auf linux/arm64 mit make bench-docker gemessen. Die Werte sind Mediane von fünf Stichproben.

Warmer Socket-Pfad

Der Warm-Socket-Benchmark verwendet verbundene UDP-Sockets, um die Kosten des EBPF-Hooks cgroup/connect4 von der TCP-Handshake-Latenz zu isolieren. In diesem Pfad hat DNS die Domäne bereits aufgelöst, die IP liegt noch innerhalb der TTL, und die IP/CIDR ist bereits in der eBPF-Karte vorhanden.

PathMedian latency
Normale Socket-Verbindung, kein eBPF~2.647 us
Warme Erlaubnisliste, geschützter LPM-Treffer~2.691 us
Warme Erlaubnisliste, DNS-Exact-Host-Treffer~2.741 us
Erlaubnislisten-Fehltreffer, lokale Sperre~1.652 us

Die gemessene Streuung zwischen den normalen, geschützten LPM- und DNS-Exact-Host-Verbindungspfaden liegt innerhalb der Stichprobenvarianz.

Es gibt derzeit keinen Pfad 'Kernel-Fehltreffer fragt Elternprozess'. Ein Fehlschlag der Cgroup-Erlaubnisliste wird lokal durch eBPF entschieden und sofort blockiert.

DNS-Abfragepfad

Diese Zahlen messen den DNS-Serverpfad, nicht den gewärmten Socket-Verbindungspfad.

PathMedian latency
Proxy-Abfrage kalt, prozessinterne Richtlinienfunktion~31.336 us
Proxy-Abfrage warm~27.964 us
Erlaubnislisten-Abfrage kalt mit lokalem Upstream~53.510 us
Erlaubnislisten-Abfrage warm mit lokalem Upstream~53.432 us

Kalte Zeilen synchronisieren durch die reale Anhangs-Mutationsbarriere und leeren den Benchmark-Besitzgraphen und den gefälschten Exact-Map-Snapshot zwischen den Abfragen. Der Timer läuft kontinuierlich, um die UDP-Scheduler-Lokalität zu erhalten, während ns/op die separat gemeldete fixture-reset-ns/op-Wandzeit abzieht (einschließlich eines eventuellen Nachlaufs des vorherigen Handlers, nachdem der Client sein Paket erhalten hat) und somit die aktuelle Client-Exchange misst. raw-total-ns/op meldet beide zusammen. Der Reset bewahrt die konfigurierten Richtliniendomänen und den Backing-Speicher, und der Benchmark behauptet einen physischen Exact-Map-Add pro Abfrage. Warme Zeilen initialisieren den Besitz einmal und behaupten einen physischen Add über den gesamten Lauf.

Die folgenden internen Besitz-Mikrobenchmarks sind Skalierungsdiagnostiken, keine End-to-End-DNS-Abfragepfad-Akzeptanzzeilen. Der gecachte Helfer wird nur für Tests und Benchmarks beibehalten; er kapselt jeweils einen Datensatz und wiederholt die Domänenvalidierung. Sowohl er als auch normaler Resolver-Traversal durchlaufen die Anhangs-Mutationsbarriere, während normaler Resolver-Traversal jede vollständige Antwort als eine Transaktion akzeptiert.

Entwurf

Architektur```

+------------------+ +-------------------------+ | Your Control |<------->| Daemon (per host) | | Plane (gRPC) | stream | | +------------------+ | +-------------------+ | | | DNS Server | | | | (per-attachment) | | | +-------------------+ | +-------------------------+ | +------+------+ | | TC Filter Cgroup Filter (veth, eth) (containers)

root@kitploit:~
Jeder Anhang erhält eine eindeutige DNS-Adresse (Port), die vom Daemon bereitgestellt wird. Container/VMs müssen so konfiguriert sein, dass sie ihre zugewiesene DNS-Adresse verwenden; das Filtern des normalen DNS-Verkehrs von Workloads leitet diesen nicht transparent um.

### DNS-Resolver-Topologie und -Verhalten

`dns.listen_addr` muss eine konkrete IPv4- oder IPv6-Adresse identifizieren, die jeder angeschlossene Workload erreichen kann. Wildcard-Adressen werden abgelehnt, da sie nicht als Resolver-Endpunkte angekündigt werden können. Ein konfigurierter Hostname wird einmal beim Start des Daemons aufgelöst, und die resultierende konkrete IP wird für Bindung, Ankündigung, Persistenz und Filter-Bootstrap verwendet. Der Standardwert `127.0.0.1` ist nur geeignet, wenn der Workload den Netzwerk-Namespace des Daemons teilt; ein Container oder VM in einem anderen Namespace benötigt normalerweise stattdessen eine erreichbare Host-/Bridge-Adresse.```yaml
dns:
  listen_addr: 10.0.0.1
  port_min: 11000
  port_max: 11500
  # Daemon-global fallback when DnsConfig.upstream_servers is empty.
  upstream: 1.1.1.1:53
  # Hard daemon ceilings for each attachment's bounded DNS exact ownership.
  # Zero/unset uses these defaults (max_ips_per_family instead derives from
  # filter.max_dns_rule_entries).
  max_ips_per_family: 4096
  max_ips_per_response: 64
  max_ips_per_policy_domain: 1024
  max_tracked_domains: 1024
  max_ownership_edges: 8192
  # Rolling physical-admission/LRU mutation budget and slow-planning work
  # allowance. The window is daemon-global and immutable until restart;
  # DnsConfig.max_churn_units may only lower the daemon ceiling.
  max_churn_units: 8192
  churn_window: 1m

Attach returns the concrete dns_address; konfiguriere diese genaue Adresse als Resolver der Workload. Netfence installiert einen geschützten, nicht ablaufenden /32- oder /128-Allow-Eintrag für die Listener-IP, sodass der Allowlist-Modus ohne eine Kontrollebenen-DNS-IP-Regel bootstrappen kann. Die aktuellen Filter erzwingen IP-Präfixe, nicht Zielports, sodass dieser geschützte Eintrag jeden Port auf der Listener-IP erlaubt (nicht nur ihren DNS-Port); dies ist besonders wichtig für Threat-Modelle mit Cgroup-Anbindung. Verwende eine dedizierte Listener-IP, wenn diese breitere Erreichbarkeit nicht akzeptabel ist.

Der zugewiesene Endpunkt bedient sowohl UDP als auch TCP. UDP-Antworten werden auf das 512-Byte-Limit eines Legacy-Clients oder seine beworbene EDNS-Größe gekürzt und tragen TC, wenn nötig, sodass die Workload denselben Endpunkt über TCP wiederholen kann. Bei der Upstream-Auflösung wird eine gekürzte UDP-Antwort zunächst über TCP gegenüber demselben Upstream wiederholt. Ein Transportfehler, SERVFAIL oder REFUSED wechselt dann zum nächsten konfigurierten Upstream in der Reihenfolge.

DnsConfig.upstream_servers überschreibt den Daemon-globalen dns.upstream für eine Anbindung. Einträge verwenden die Syntax host:port (IPv6-Literale in Klammern), werden kanonikalisiert und in der Reihenfolge des ersten Auftretens dedupliziert und sind auf acht eindeutige Server begrenzt. Eine leere Liste wählt den globalen Fallback.

In Filtermodi entfernt Netfence die Parameter ipv4hint und ipv6hint aus HTTPS/SVCB-Antworten, einschließlich ihrer entsprechenden mandatory-Referenzen, da angezeigte Adressen nicht unabhängig die Filterzulassung bestanden haben. Der deaktivierte Modus gibt Upstream-Antworten unverändert weiter.

DNS-Abfragezähler schließen sich gegenseitig aus: dns_queries_allowed zählt erfolgreich beantwortete, richtlinien-zugelassene Abfragen (einschließlich NXDOMAIN), dns_queries_blocked zählt Richtlinien-REFUSED-Antworten, und dns_queries_errors zählt Resolver-, Proxy-, Filterzulassungs-, Antwort-Schreib- und andere Fehlerpfade. Eine Abfrage erhöht genau einen Bucket.

Jede adressentragende Antwort in einem DNS-Filtermodus wird der exakten IPv4/IPv6-HASH-Stufe der Anbindung als eine Transaktion zugeführt, bevor eine A/AAAA-Adresse aus ihren Antwort-, Autoritäts- oder Zusatzabschnitten zurückgegeben wird. Wenn die vollständige Antwort nicht dargestellt werden kann, gibt der Resolver SERVFAIL ohne Adresse zurück und bewahrt den zuvor zugelassenen Arbeitssatz. PROXY-Entscheidungen, die Adressen zurückgeben, müssen add_to_filter setzen; andernfalls schlagen sie ebenfalls als SERVFAIL fehl. Der deaktivierte DNS-Modus ist die explizite Durchlass- Ausnahme.

Exakte Einträge tragen TTL-Kanten von der normalisierten Abfrage zum übereinstimmenden Richtlinien-Besitzer. Das Entfernen oder Verweigern einer Domain entfernt schnell ihre letzten reinen DNS-exakten Adressen, während eine gemeinsam genutzte Adresse einen anderen live-Abfrage-Besitzer überlebt und eine überlappende Kontrollebenen-CIDR unabhängig in der geschützten LPM-Stufe fortbesteht. DNS-DENYLIST-Standard-Zulassungs- und explizite Zulassungsantworten werden ebenfalls verfolgt, selbst während Paket-DENYLIST exakte Zulassungen ignoriert, sodass ein späterer Paketmodus-Wechsel zu ALLOWLIST bereits zurückgegebene gecachte Adressen ohne erneute Abfrage nutzen kann.

Der gesamte normale/live-Userspace-Besitzstatus wird durch die fünf Besitzer-Einstellungen oben begrenzt. Wiederhergestellte synthetische provisorische Kanten sind von diesen logischen Grenzen ausgenommen, sodass sie vor der Rekonziliation nicht vergessen werden können, bleiben aber durch die physischen IPv4/IPv6-exakten Maps begrenzt. Konfigurierte Richtlinien-Domains und live-Abfrage-Domains teilen sich max_tracked_domains, und jeder (Abfrage, übereinstimmender Besitzer, IP)-TTL-Eintrag verbraucht einen max_ownership_edges-Slot.

Bei Druck projiziert die Zulassung zuerst abgelaufene TTL-Kanten weg. Sie beansprucht dann vollständige logische Abfrage/Besitzer-Kanten mit dem geringsten physischen Kollateral zurück, gefolgt von deterministischem, vom Resolver beobachtetem LRU (kanonische IP bricht Gleichstände). Eine physische Räumung entfernt den gesamten DNS-exakten Schlüssel und alle seine DNS- Besitzer. Die eingehende physische IP und die exakte eingehende (IP, Abfrage, Besitzer)-Kante sind für die Antworttransaktion geschützt. Wiederhergestellter provisorischer Besitz schützt seinen physischen Schlüssel bis zur autoritativen Rekonziliation, aber nicht verwandte normale DNS-Metadaten, die diesen Schlüssel teilen, können dennoch zurückgefordert werden. Autoritative Kontrollebenen-/System-Zulassungen und jede Verweigerung bleiben in separaten LPM-Stufen und sind niemals Kandidaten für die DNS-Rückforderung.

Das rollierende Churn-Budget pro Anbindung berechnet eine Einheit für einen neuen physischen exakten Schlüssel und eine für jeden geräumten live-physischen DNS-Schlüssel; ein vollständiger Alt/Neu-Ersatz kostet daher zwei. Aktualisierungen, logische Rückforderung, Ablauf und Richtlinienentfernung kosten null. Ereignisse bleiben aktiv, solange ihr Alter kleiner als dns.churn_window ist, und laufen an der genauen Grenze ab. DnsConfig.max_churn_units darf nur die Daemon-Obergrenze senken; Null übernimmt sie. Das Fenster kann nicht von der Kontrollebene geändert werden, und das Ändern der Daemon-Obergrenze/des Fensters erfordert einen Neustart. Das Senken und spätere Anheben einer Anbindungsgrenze vergisst nicht noch aktive Historie.

Ein separates rollierendes Arbeitsbuch begrenzt aufwändige Besitzgraph-Planung. Schnelle Aktualisierungen und gewöhnliche Zulassungen berühren es nie. Bevor ein Druckpfad den Graphen klont oder analysiert, berechnet Netfence stabile Arbeitseinheiten, die von aktuellen physischen Schlüsseln, Besitzkanten, verfolgten Domains und Antwortgröße relativ zu ihren unveränderlichen Daemon/Map-Obergrenzen abgeleitet sind. Dieser Versuchsaufwand wird beibehalten, selbst wenn der Plan sich als unmöglich erweist oder eine spätere Exakt-Map-Transaktion fehlschlägt, wodurch der Null-Mutations-Wiederholungspfad für CPU-/Allokationsdruck geschlossen wird, ohne die transaktionale physische Churn-Abrechnung oben zu ändern. Bei den Standard-Obergrenzen lässt die Zulassung acht maximalequivalente Graph-Durchläufe pro Fenster zu; das Senken von DnsConfig.max_churn_units behält mindestens einen. Das Senken und spätere Anheben der Grenze skaliert nie neu oder vergisst aktive Arbeitshistorie.

Wenn kein geeigneter DNS-Zustand eine Grenze erfüllen kann oder eine der beiden rollierenden Zulassungen erschöpft ist, bewahrt Netfence den zugelassenen Arbeitssatz und gibt SERVFAIL zurück, ohne die nicht zugelassene Adresse zurückzugeben. Kapazitätsfehler erhöhen map_full_drops; physische Churn- und Planungsarbeits-Drosselungen tun dies nicht. Heartbeats zeigen Exakt-Map-Aktuell-, Kapazitäts- und Prozessgenerations-Höchstwerte plus kumulative DNS-LRU-Räumungen, alle Zulassungsfehler und einen aggregierten Budget-Drosselungszähler, der beide rollierenden Wächter abdeckt. Kapazitäts-, physische Budget- und Arbeitsbudget-Druck/Wiederherstellungslogs sind unabhängig ratenbegrenzt. Betreiber können auf TTL-/Fenster-Wiederherstellung warten, Antwort-/Domain-Churn oder wiederholte Kapazitätsdruckversuche reduzieren oder DnsConfig.max_churn_units bis zur Daemon-dns.max_churn_units-Obergrenze erhöhen. Das Anheben der Daemon-Obergrenze erfordert einen Neustart; das Erhöhen von filter.max_dns_rule_entries erfordert ebenfalls das Neuerstellen der Anbindung, da gepinnte Maps nicht vor Ort vergrößert werden können.

Geschützte CIDR-Kapazität und Fail-Closed-Wiederherstellung

Autoritative Kontrollebenen-CIDRs und Daemon-Systemregeln verwenden vier unabhängige, nicht räumbare LPM-Maps: Allow/Deny × IPv4/IPv6. Jede Map hat filter.max_rule_entries Slots. Der DNS-Listener-/32- oder /128-Bootstrap ist ein System-Allow und wird gegen die entsprechende geschützte Allow-Map gezählt. DNS-Exakt-Host-Einträge bleiben in ihren separaten Maps und können diese Slots nicht verbrauchen. Keine geschützte Regel wird jemals LRU-geräumt: explizite Allows, Systemregeln und jede Deny bleiben bis zu einer autorisierten Entfernung oder einem vollständigen Ersatz.

Ein vollständiges SubscribedAck oder BulkUpdate wird kanonikalisiert, und seine endgültige Belegung wird für alle vier Maps vor der Mutation geprüft. Die Kapazität basiert auf dem endgültigen Zustand, sodass das Ersetzen von Schlüsseln in einer vollen Map gültig ist; ein zu großer Zustand wird zurückgewiesen, ohne Regeln zu räumen oder teilweise zu akzeptieren. Überlebende werden nicht entfernt und neu hinzugefügt. Wenn ein späterer Map-Syscall fehlschlägt, stellt Netfence das exakte Vier-Map-Inventar vor dem Aufruf wieder her und verifiziert es. Der bewiesene Modus nach dem Rollback ist der alte Modus oder BLOCK_ALL (normalerweise BLOCK_ALL), sodass der Daemon die Anbindung weiterhin im Fail-Closed-Zustand hält, bis ein vollständiger autoritativer Wiederholungsversuch erfolgreich ist.

Der Sicherheitszustand der geschützten Richtlinie wird mit der Anbindung persistiert und in Heartbeats exportiert. BLOCK_ALL allein ist ein normaler, gesunder konfigurierter Modus: policy_degraded ist false, wenn policy_degraded_reason leer ist. Eine riskante geschützte Mutation, die startet, während BLOCK_ALL gesund ist, journalliert zuerst protected_policy_mutation_in_progress. Dies ist ein transientes Absturzjournal, nicht eine stabile Fehlerdiagnose: die Live-Operation kann ihre beabsichtigte Art vor dem endgültigen Journal-Clear-Speichern veröffentlichen, und der erfolgreiche Abschluss löscht das Journal selbst. Wenn der Start es nach einem Absturz findet, erzwingt und beweist der Start zuerst BLOCK_ALL und persistiert dann protected_policy_mutation_interrupted. Stabile degradierte Grundcodes sind:

  • protected_policy_mutation_interrupted
  • authoritative_protected_policy_failed
  • incremental_deny_install_failed
  • incremental_allow_removal_failed
  • incremental_mode_change_failed

Dies sind stabile Klassifikationen, niemals roher Syscall/Store-Text. Das laufende Journal ist eine interne persistierte Absturzgrenze; Heartbeat-Statistiken serialisieren mit der besitzenden Mutation und beobachten daher entweder ihren erfolgreichen Clear oder eine stabile Fehlerumwandlung, nicht das Live-Zwischenjournal. Stabile degradierte/unterbrochene Gründe halten die Paketdurchsetzung im bewiesenen BLOCK_ALL und lehnen inkrementelle CIDR- und Paketmodus-Befehle ab. Unabhängige DNS-Konfigurationsänderungen und DNS-TTL-Abläufe können unter diesem bewiesenen Halten fortgesetzt werden, können aber den stabilen Grund nicht löschen oder die Paketrichtlinie reaktivieren. Die Wiederherstellung von einem stabilen Grund erfordert einen vollständigen LPM-und DNS-Soll-Zustand: wende BulkUpdate über die Kontrollebene oder die lokale API an (oder beantworte das Subscribed einer wiederhergestellten Anbindung mit SubscribedAck). Netfence bereitet den vollständigen geschützten Zustand vor, wendet den autoritativen DNS-Zustand an, aktiviert den angeforderten Modus und löscht den dauerhaften Grund erst, nachdem jeder Schritt erfolgreich war. Bevorzuge eine eindeutige command_id auf einem BulkUpdate der Kontrollebene zur Wiederherstellung und erfordere ein erfolgreiches CommandResult; die lokale API lehnt command_id ab, da ihr unäres RPC-Ergebnis bereits Erfolg oder Fehlschlag meldet.

Heartbeats zeigen aktuelle physische Einträge, harte Kapazität und Daemon-Generations-Höchstwerte unabhängig für alle vier geschützten Maps. Der Bootstrap ist enthalten; übernommene gepinnte Einträge initialisieren den Höchstwert der neuen Generation. map_full_drops ist kumulativ und enthält geschützte Kapazitätsablehnungen. Wenn eine Belegungsablesung fehlschlägt, behält der Daemon die letzte bewiesene Momentaufnahme und gibt höchstens einmal alle 30 Sekunden eine Warnung aus, anstatt neue Zählwerte zu erfinden. Zur Wiederherstellung von Druck reduziere die vollständigen gewünschten Regeln unter jeder Pro-Map-Kapazität und wiederhole das vollständige Update. Das Erhöhen von filter.max_rule_entries ist nur zur Ladezeit möglich und erfordert das Neuerstellen einer bestehenden gepinnten Anbindung. Wenn der Daemon BLOCK_ALL nicht beweisen oder seinen Sicherheitsmarker dauerhaft aufzeichnen kann, stoppt er die Mutationszulassung; repariere den Map/Store-Fehler und starte neu, anstatt anzunehmen, dass die Durchsetzung wieder geöffnet ist.

Pro Host

Führe den Daemon aus, welcher:

  • Eine lokale gRPC-API (DaemonService) für Anbindungen, Richtlinien und Inspektion bereitstellt
  • Optional über einen bidirektionalen Stream (ControlPlane.Connect) eine Verbindung zu deiner Kontrollebene herstellt
  • eBPF-Programme lädt und verwaltet

Starte den Daemon:```bash

Start with default config

netfenced start

Start with custom config file

netfenced start --config /etc/netfence/config.yaml

root@kitploit:~
**Daemon-Status überprüfen:**```bash
netfenced status

Mit keinem control_plane.url wird ein neuer Attachment im deaktivierten Paket-/DNS-Modus ausgeführt und kann sofort über die lokale API oder CLI konfiguriert werden. Für den unter „Per Attachment“ dokumentierten eigenständigen Workflow ist kein Control-Plane-Prozess erforderlich.

Lokale Unix-Socket-Vertrauensgrenze

Die lokale gRPC-API hat keine Authentifizierung pro RPC. Der Dateisystemzugriff auf ihren Unix-Socket ist die Autorisierungsgrenze, und jeder Prozess, der eine Verbindung herstellen kann, ist ein vollständig vertrauenswürdiger Host-Netzwerk-Administrator: Er kann Host-eBPF-Programme anhängen oder trennen, Paket- und DNS-Richtlinien ersetzen sowie Workload-Datenverkehr öffnen oder schließen. Halten Sie die Socket-Gruppenmitgliedschaft eng und schützen Sie das übergeordnete Verzeichnis des Sockets.```yaml

Defaults to /var/run/netfence.sock.

socket: /run/netfence/netfence.sock

Unix group name or numeric GID. Empty/unset uses the daemon's effective GID.

socket_group: netfence-admin

root@kitploit:~
`NETFENCE_SOCKET` und `NETFENCE_SOCKET_GROUP` sind die entsprechenden Umgebungsvariablen. Beim Start bindet der Daemon den Socket in einem privaten Staging-Verzeichnis, setzt seine Gruppe und den Modus `0660`, während er unerreichbar ist, und veröffentlicht ihn dann atomar. Der Daemon entfernt jeden bereits vorhandenen Unix-Socket am konfigurierten Ziel – er unterscheidet nicht zwischen einem veralteten Socket und einem, der einem anderen laufenden Daemon gehört –, daher muss genau ein Daemon einen Socket-Pfad besitzen. Er weigert sich, ein Nicht-Socket-Ziel zu entfernen. Unter Linux verhindert das "no-replace rename" das Überschreiben eines neuen Pfads, der nach dieser Entfernung erstellt wurde; beim Herunterfahren wird der veröffentlichte Pfad nur entfernt, solange er noch den Inode des eigenen Sockets des Daemons identifiziert. Eine ungültige Gruppe, ein Besitz-/Modusfehler oder ein Nicht-Socket-Ziel führt zu einem Startfehler, ohne einen permissiven Endpunkt zu veröffentlichen.

### Sicherheit des Control-Plane-Transports (TLS / mTLS / Bearer-Token)

Der Control-Plane-Kanal ist die wertvollste Angriffsfläche im System (wer ihn kontrolliert, kann `ALLOW`-Regeln an jede Workload pushen), daher **schlägt der Daemon geschlossen fehl**: wenn `control_plane.url` gesetzt ist, muss die Konfiguration explizit einen Transport wählen – entweder einen `control_plane.tls`-Block oder `control_plane.insecure: true`. Eine URL ohne beides wird beim Start abgelehnt; es gibt keine implizite Klartext-Voreinstellung. (Dies ist eine bewusste Verhaltensänderung: ältere Versionen haben die Control-Plane unverschlüsselt angewählt.)```yaml
control_plane:
  url: cp.internal:443
  tls:
    # CA bundle used to verify the control-plane server certificate.
    # Path to a PEM file or inline PEM; omit to use the system root pool.
    ca: /etc/netfence/cp-ca.pem
    # Client certificate + key (path or inline PEM). Setting BOTH enables
    # mTLS: the daemon presents this cert to the control plane. Setting only
    # one is a config error.
    cert: /etc/netfence/daemon.pem
    key: /etc/netfence/daemon.key
    # Optional hostname override for server certificate verification (SNI),
    # e.g. when dialing by IP.
    server_name: cp.internal
  # Optional bearer token, sent as `authorization: Bearer <token>` metadata
  # on every control-plane RPC. Refused on a plaintext channel unless
  # `insecure: true` was explicitly set (so a misconfiguration can't leak it).
  auth_token: "..."

TLS nur mit Systemstammzertifikaten (öffentliches CA-ausgestelltes Serverzertifikat, kein mTLS) ist nur ein leerer Block:```yaml control_plane: url: cp.example.com:443 tls: {}

root@kitploit:~
Plaintext für lokale Entwicklung ist ein explizites Opt-in (sich gegenseitig ausschließend mit `tls`):```yaml
control_plane:
  url: localhost:9000
  insecure: true

Zertifikate und Schlüssel werden einmalig beim Start geladen, sodass ein falscher Pfad/ein ungültiges PEM mit einer klaren Fehlermeldung fehlschlägt, anstatt bei jeder erneuten Verbindung aufzutauchen.

Lebensdauer der Steuerungsebene (Keepalive) und Wiederherstellungs-Backoff

Der Daemon sendet HTTP/2-Keepalive-Pings auf der Control-Plane-Verbindung, sodass ein stiller Verbindungsabbruch (Kabelziehen, verlorene NAT-Zuordnung, Blackhole-Route) erkannt und in etwa keepalive_time + keepalive_timeout abgerissen wird – anstatt Minuten lang im Zustand CONNECTED zu verharren, bis das TCP-Retransmission-Timeout des Kernels abläuft, während jede proxierte DNS-Anfrage ihre vollständige Timeout-Zeit verbraucht. Wiederherstellungsversuche werden durch einen exponentiellen Backoff mit Jitter getaktet (beginnt bei 1s, verdoppelt sich, ±20% Jitter, begrenzt auf reconnect_backoff_max); der Backoff wird nur auf den Startwert zurückgesetzt, nachdem eine Verbindung 30s lang gesund geblieben ist, sodass eine Steuerungsebene, die Verbindungen akzeptiert und sofort verwirft, den Backoff weiter erhöht, anstatt ständig auf den Startwert zurückgesetzt zu werden.```yaml control_plane:

Send a keepalive ping after this much inactivity… (default 30s; gRPC

clamps the effective interval to a 10s minimum client-side)

keepalive_time: 30s

…and declare the peer dead if no ack arrives within this (default 10s).

keepalive_timeout: 10s

Cap on the jittered exponential reconnect backoff (default 30s).

reconnect_backoff_max: 30s

root@kitploit:~
Null- oder nicht gesetzte Werte bedeuten die Standardwerte – sie deaktivieren **nicht** Keepalive oder den Backoff. Ihre Kontrollebene muss diesen Ping-Rhythmus in ihrer gRPC-Keepalive-Durchsetzungsrichtlinie erlauben (siehe unten), sonst wird sie den Daemon mit `ENHANCE_YOUR_CALM (too_many_pings)` ablehnen.

### Neustarts, Abstürze und Upgrades des Daemons (angehefteter BPF-Zustand)

Der Daemon heftet die BPF-Links und Regelzuordnungen jedes Attachments an bpffs an (`filter.bpf_pin_dir`, standardmäßig `/sys/fs/bpf/netfence`, ein Verzeichnis pro Attachment-ID). Da der angeheftete Zustand vom Kernel gehalten wird – nicht vom Daemon-Prozess – **läuft die Durchsetzung weiter, während der Daemon nicht läuft**: Ein Absturz (`kill -9`), ein ordentlicher Stopp oder ein Upgrade hinterlässt die zuletzt bekannte Richtlinie (Modus + alle Regeln) in Kraft, und der nächste Daemon-Start übernimmt den angehefteten Zustand unverändert. Die Wiederherstellung fügt keine Live-Maps erneut an oder überschreibt sie, sodass es kein Fenster gibt, in dem eine zugelassene Arbeitslast blockiert oder ein blockiertes Ziel zugelassen wird, und es gibt keine doppelten Attachments.

Das Stoppverhalten ist explizit konfiguriert (`filter.detach_on_stop`):```yaml
filter:
  # false (default): stopping the daemon KEEPS ENFORCING — filters stay
  # attached via their bpffs pins and are re-adopted on the next start
  # (fail-closed across restarts/upgrades).
  # true: stopping the daemon detaches filters and removes their pins —
  # traffic is unfiltered while the daemon is down (explicit fail-open).
  detach_on_stop: false
  # bpffs directory for pinned state. Must be on a bpffs mount; the daemon
  # mounts bpffs at /sys/fs/bpf if needed (privileged). An explicit "" turns
  # pinning off entirely (BPF state then dies with the process).
  bpf_pin_dir: /sys/fs/bpf/netfence
  # Capacity of each authoritative/system LPM map (allowed/denied per family).
  # Protected entries are non-evictable; the DNS listener bootstrap consumes
  # one slot in its address family. Changing pinned-map capacity requires
  # recreating the attachment.
  max_rule_entries: 4096
  # Independent capacity of each DNS-derived exact-host HASH map (IPv4/IPv6).
  # These entries can never consume or evict authoritative/deny capacity.
  max_dns_rule_entries: 4096

Ein explizites Detach (RPC/CLI) oder das Entfernen eines live kohärent eigenen Ziels zerstört den gepinnten Status zusammen mit dem Attachment. Beim Neustart autorisiert das Fehlen eines Ziels kein Raten: zukünftige, nicht festgeschriebene, gemischte oder anderweitig nicht verifizierbare persistierte Pins werden erhalten, und der Startvorgang bricht zur Überprüfung ab.

Pin-Verzeichnisse sind ein versioniertes Persistenzformat. Der Schema-Marker wird zuletzt gepinnt, erst nachdem jede erforderliche Map und jeder Link vorhanden ist. Ein Upgrade eines zuvor exakten Tier-Attachments pinnt die beiden neuen leeren exakten Maps mit einem In-Progress-Marker, ersetzt atomar das Programm jedes Links unter Wiederverwendung der live autoritativen Maps, überprüft die Programm/Map-Identität und committet den Marker zuletzt. Ein Absturz oder eine mehrdeutige Aktualisierung hinterlässt den Marker nicht committet; der nächste Start aktualisiert jeden Link mit denselben Maps erneut. Alte und neue Programm-Generationen erzwingen während dieses begrenzten Mischzustands dieselbe autoritative LPM-Richtlinie, sodass eine Migration niemals einen brauchbaren Filter entpinnt oder neu erstellt. Unbekannte, unvollständige oder nicht verifizierbare Pin-Sets werden erhalten und brechen den Startvorgang zur Überprüfung ab, anstatt geraten zu werden.

Anmerkungen zum neu übernommenen Zustand:

  • Jedes erfolgreich wiederhergestellte Attachment wird für die autoritative Abgleichung markiert. Bei jeder Steuerungsebenen-Verbindung sendet der Daemon zuerst die SyncRequest, dann eine vollständige Subscribed-Deklaration für jedes wiederhergestellte Attachment, das noch einer Abgleichung bedarf. Antworte mit einer frischen SubscribedAck: Deren Modus, CIDRs, TTLs und DNS-Konfiguration sind der vollständige Soll-Zustand. Der Daemon wendet ein Delta an (unveränderte CIDRs werden nie entfernt) und löscht den Wiederherstellungsmarker erst, nachdem das gesamte Ack angewendet wurde. Ein Timeout, ein Verbindungsabbruch oder ein Validierungsfehler lassen die Durchsetzung unverändert. Ein Filter-/Map-/DNS-/Store-Anwendungsfehler kann ein partielles Delta hinterlassen, aber der Abgleich verwendet kein vollständiges Map-Clear oder Entfernen/Neu-Hinzufügen von unveränderten Überlebenden; der Wiederherstellungsmarker bleibt gesetzt, und der Daemon wiederholt nach einer späteren Verbindung.
  • Die TTL-Fristen der Regeln selbst werden nicht persistiert. Neu übernommene Regeln werden vorläufig als permanent behandelt, bis die frische SubscribedAck eintrifft; dieses autoritative Ack ersetzt ihre Lebensdauern exakt, einschließlich der Verkürzung einer Frist oder der Rückwandlung einer vorläufig permanenten Regel in eine Regel mit endlicher TTL. Wiederhergestellte exakte DNS-Schlüssel werden inventarisiert und durch begrenzte vorläufige Besitzer dargestellt (die tatsächlichen gepinnten Map-Kapazitäten sind die Grenze); die erste autoritative DNS-Konfiguration verwirft jede synthetische Behauptung, entfernt Schlüssel, die besitzerlos geblieben sind, und bewahrt einen Schlüssel nur, wenn er separat einen normalen live Besitzer hat. Ein nicht-kanonisches/kollidierendes Inventar bricht die Wiederherstellung ab, ohne Besitzmetadaten zu erraten oder teilweise zu veröffentlichen.
  • Es gibt kein persistiertes lokales Soll-Zustandsdokument. Wenn keine Steuerungsebene konfiguriert oder erreichbar ist, treten keine automatischen Regeländerungen auf: Eine übernommene gepinnte Map setzt weiterhin ihre zuletzt bekannten geschützten CIDRs durch, die in der Userspace-Registry als vorläufig dargestellt werden, bis eine vollständige Aktualisierung erfolgt. Eine Wiederherstellung, die keine gültigen Pins übernehmen kann, erstellt das Attachment in seinem persistierten Modus mit leeren Maps neu (Fail-Closed für Allowlist/Block-All). Ein eigenständiger Orchestrator muss nach jedem Daemon-Neustart erneut abspielen, um den vorläufigen Paketzustand zu ersetzen und seinen vollständigen Soll-Zustand und seine TTLs wiederherzustellen.

Pro Attachment

Ihr Orchestrierungssystem ruft die lokale API des Daemons auf.

RPC:``` DaemonService.Attach(interface_name: "veth123", tc_direction: TC_DIRECTION_INGRESS, metadata: {vm_id: "abc"}) // or DaemonService.Attach(cgroup_path: "/sys/fs/cgroup/...", metadata: {container_id: "xyz"})

root@kitploit:~
**CLI:**```bash
# Attach to a host-side veth peer or VM tap (TC) - use ingress direction
netfenced attach --interface veth123 --direction ingress --metadata vm_id=abc

# Attach to a cgroup
netfenced attach --cgroup /sys/fs/cgroup/... --metadata container_id=xyz

# Attach to an uplink inside the workload's own netns (TC) - egress is the default
netfenced attach --interface eth0 --metadata tenant=acme,env=prod

TC-Richtung: Das Feld tc_direction (CLI --direction) wählt aus, an welchen TCX-Hook der Filter angehängt wird. Die richtige Wahl hängt davon ab, auf welcher Seite der Verbindung sich das Interface befindet:

Die Richtung gilt nur für Interface (TC)-Bindungen; sie wird bei Cgroup-Bindungen ignoriert.

  • Der Daemon hängt einen eBPF-Filter an das Ziel an.
  • Wenn control_plane.url konfiguriert ist, sendet der Daemon Subscribed{id, target, type, metadata} und wartet auf SubscribedAck mit der initialen Konfiguration (Modus, CIDRs, DNS-Regeln). Wenn die Kontrollebene nicht innerhalb des Timeouts (Standard 5s, konfigurierbar über control_plane.subscribe_ack_timeout) antwortet, wird die Bindung zurückgesetzt und der Aufruf von Attach schlägt fehl. Validierungs- und andere Pre-Commit-Fehler folgen der gleichen normalen Rollback-Regel.
  • Ohne konfigurierte Kontrollebene wird Attach sofort im deaktivierten Modus ausgeführt; verwenden Sie die folgenden lokalen Policy-Befehle, um es zu konfigurieren.
  • Eine gültige initiale Policy, die einen Fehler einer geschützten Map/Store erreicht, ist die bewusste Ausnahme eines committed Error: Der Daemon behält die Bindung im dauerhaften BLOCK_ALL bei, anstatt sie zerstörend zurückzusetzen. Mit einem begrenzten Timeout gibt Attach einen Fehler zurück, der die beibehaltene Bindungs-ID enthält; der Aufrufer kann diese ID durch Abgleich des Ziels in List finden, und die Kontrollebene muss sie mit einem vollständigen BulkUpdate wiederherstellen.

RPC:``` DaemonService.Detach(id)

root@kitploit:~
**CLI:**```bash
netfenced detach --id <attachment-id>

Anhänge auflisten:```bash netfenced list netfenced list --all # fetch all pages

root@kitploit:~
### Lokale Richtlinie und Inspektion

Jede lokale Mutation ist eine dünne CLI-Codierung des einzelnen
`DaemonService.ApplyCommand(ControlCommand)` RPC. Geben Sie die von `attach` zurückgegebene Anhang-ID an:```bash
# Packet policy and protected CIDRs.
netfenced set-mode <id> allowlist
netfenced allow-cidr <id> 10.0.0.0/8
netfenced allow-cidr <id> 192.0.2.10/32 --ttl 5m
netfenced deny-cidr <id> 10.20.0.0/16
netfenced remove-cidr <id> 10.20.0.0/16 --list deny
# --list accepts allow, deny, or both (the default).

# DNS policy.
netfenced set-dns-mode <id> denylist
netfenced allow-domain <id> example.com --subdomains
netfenced deny-domain <id> blocked.example.com
netfenced remove-domain <id> blocked.example.com

# Deterministic current-policy inspection as protobuf JSON.
netfenced rules <id>

Paket-Modi sind disabled, allowlist, denylist und block-all; DNS-Modi sind disabled, allowlist, denylist und proxy. DNS proxy erfordert eine erreichbare konfigurierte Steuerungsebene. Domain-Matching verwendet das spezifischste passende Suffix; wenn gleich spezifische Allow- und Deny-Regeln beide übereinstimmen, gewinnt Deny. CIDRs und Domains werden kanonisiert. Negative, fehlerhafte oder anderweitig ungültige TTLs, Enums, CIDRs, Domains, Selektoren und verschachtelte Nachrichten werden vor der Mutation abgelehnt, sodass ein ungültiger Befehl eine Nulloperation der Richtlinie ist.

Für einen vollständigen Austausch liest apply-rules die vorhandene BulkUpdate-Protobuf-JSON-Struktur aus einer Datei oder stdin:```bash cat >rules.json <<'JSON' { "mode": "POLICY_MODE_ALLOWLIST", "allowCidrs": [{"cidr": "10.0.0.0/8"}], "dns": { "mode": "DNS_MODE_DENYLIST", "denyDomains": [{"domain": "blocked.example.com", "includeSubdomains": true}] } } JSON netfenced apply-rules --file rules.json

Equivalent stdin form:

netfenced apply-rules --file - < rules.json

root@kitploit:~
`ApplyCommand` akzeptiert nur `SetMode`, `AllowCIDR`, `DenyCIDR`, `RemoveCIDR`,
`BulkUpdate`, `SetDnsMode`, `AllowDomain`, `DenyDomain` und `RemoveDomain`.
Nur-Stream-Sync/Ack-Varianten, unbekannte oder leere Befehle sowie lokale
`command_id`-Werte werden abgelehnt. `BulkUpdate` ist außerdem die einzige lokale Operation,
die eine stabile degradierte Paketrichtlinie wiederherstellen kann; sie muss den vollständigen
gewünschten LPM- und DNS-Zustand enthalten.

Der optionale Selektor `ControlCommand.remove_cidr_list` kann die Erlaubnisliste,
die Verbotsliste oder beide anvisieren, wenn die Befehlsvariante `RemoveCIDR` ist. Der veraltete
nicht spezifizierte Wert und der explizite Wert `BOTH` entfernen beide aus beiden Listen, wodurch
das ursprüngliche Protokollverhalten erhalten bleibt.

Lokale und Kontrollplan-Mutationen teilen sich einen Parser, eine Mutationsbarriere, ein TTL-
Register, einen Fail-Closed-Wiederherstellungspfad und einen Policenbesitzer. Es gibt bewusst keine
Schlichtung der Besitzverhältnisse zwischen lokalem und Kontrollplan: widersprüchliche Operationen auf
einer einzelnen Policenliste werden in ihrer committeten Reihenfolge wirksam, unabhängig von der
Quelle. Insbesondere kann ein späterer vollständiger Kontrollplan-`BulkUpdate` oder
`SubscribedAck` den lokalen Zustand ersetzen.

`GetRules`/`netfenced rules` gibt einen kohärenten, deterministischen Userspace-
Registry-Snapshot zurück. Jedes CIDR meldet Erlaubnis-/Verbotsliste, `policyOwned` (lokal oder Kontrollplan),
`systemOwned` (Daemon), absolute `expiresAt`, wiederhergestelltes `provisional` und den zuletzt committeten
Kernelzustand `installed`. Ein installierter Eintrag ohne Besitzer ist ein fehlgeschlagener Entfernungsversuch,
keine gewünschte Richtlinie. Die DNS-Ausgabe ist die lebende, normalisierte effektive `DnsConfig`. Die Inspektion
zählt bewusst nicht geschützte Kernel-Maps auf und legt auch keine dynamisch aufgelösten DNS-Exact-Host-
Cache-Einträge offen; verwenden Sie Heartbeat-Telemetrie für die Auslastung der geschützten Maps.

## Auf der Kontrollebene (Sie implementieren dies)

Implementieren Sie den `ControlPlane.Connect` RPC - einen bidirektionalen Stream:

Konfigurieren Sie die Keepalive-Durchsetzungsrichtlinie Ihres gRPC-Servers, um den
Ping-Rhythmus des Daemons zu erlauben (`control_plane.keepalive_time`, Standard 30s): setzen Sie
`MinTime` auf oder unter dieses Intervall und `PermitWithoutStream: true`. Die gRPC-
Standardrichtlinie (5 Minuten) behandelt die Pings des Daemons als missbräuchlich und schließt
die Verbindung mit `ENHANCE_YOUR_CALM (too_many_pings)`. In Go:```go
grpc.NewServer(grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
    MinTime:             10 * time.Second,
    PermitWithoutStream: true,
}))

Empfang vom Daemon:

  • SyncRequest bei Verbindung/Wiederverbindung (listet aktuelle Anhänge auf)
  • Subscribed wenn neue Anhänge hinzugefügt werden, und nach SyncRequest für wiederhergestellte Anhänge, die noch frische autoritative Zustände benötigen
  • Unsubscribed wenn Anhänge entfernt werden
  • Heartbeat mit Statistiken
  • CommandResult{command_id, id, success, error} — Ergebnis eines Befehls, den Sie mit einer nicht-leeren command_id gesendet haben (opt-in Korrelations-Nonce auf ControlCommand; Befehle ohne eine erzeugen kein Ergebnis). success ist nur wahr, wenn der Befehl vollständig angewendet wurde – ein teilweise angewendetes BulkUpdate meldet Fehler mit dem aggregierten Fehler. Ergebnisse sind Best-Effort: Behandeln Sie ein fehlendes Ergebnis als unbekannt, nicht als fehlgeschlagen.

Senden an den Daemon:

  • SyncAck nach Empfang von SyncRequest
  • SubscribedAck{mode, cidrs, dns_config} nach Empfang von Subscribed (erforderlich – Daemon wartet darauf)
  • SetMode{mode} – IP-Filterrichtlinienmodus ändern
  • AllowCIDR{cidr, ttl} / DenyCIDR / RemoveCIDR (optional select allow, deny oder both; nicht angegeben behält das Legacy-„both“-Verhalten bei)
  • SetDnsMode{mode} – DNS-Filtermodus ändern
  • AllowDomain{domain} / DenyDomain / RemoveDomain (der spezifischste Treffer gewinnt; verweigern gewinnt bei gleich spezifischem Treffer)
  • BulkUpdate{mode, cidrs, dns_config} – vollständige Zustandssynchronisation

Wenn die Steuerungsebene Subscribed empfängt, muss sie mit einem vollständigen SubscribedAck antworten. Bei einem neuen Anhang wartet der Daemon normalerweise auf dieses Ack, bevor er dem lokalen Aufrufer Erfolg meldet. Bei einem wiederhergestellten Anhang läuft der Handshake im Hintergrund, während die gespeicherte letzte bekannte Richtlinie weiterhin gilt. Verwenden Sie die Metadaten, um die VM/den Mandanten/den Container zu identifizieren, und geben Sie den vollständig gewünschten Modus, CIDRs (einschließlich TTLs) und DNS-Status zurück; eine ausgelassene DNS-Konfiguration bedeutet deaktiviert mit leeren Domain-Listen.

Wiederverbindungen und Idempotenz (erforderlich)

SyncRequest ist der autoritative Abgleichspunkt: Bei jeder (Wieder-)Verbindung ist es das erste Ereignis im Stream und listet den gesamten aktuellen Anhangssatz des Daemons auf. Gleichen Sie Ihre Ansicht damit ab – fügen Sie Anhänge hinzu, die Sie nicht kannten, entfernen Sie diejenigen, die nicht in der Liste sind. Bei Wiederverbindung löscht der Daemon Ereignisse, die gegen die vorherige Verbindung in der Warteschlange waren (die Synchronisation überschreibt sie), sodass Sie keine veralteten Heartbeats, Unsubscribeds für Anhänge, die bereits in der Synchronisation fehlen, oder CommandResults der toten Verbindung, die danach wiedergegeben werden, sehen. Zwei Grenzfälle bleiben absichtlich bestehen, und Ihre Steuerungsebene MUSS sie idempotent behandeln:

  • Ein Subscribed kann auf ein SyncRequest folgen, das bereits dieselbe ID auflistet. Dies passiert, wenn ein Ack eines neuen Anhangs über eine Wiederverbindung hinweg ausstehend war, und bewusst für jeden wiederhergestellten Anhang, bis ein autoritatives Ack vollständig angewendet wird. Behandeln Sie es als Update, antworten Sie mit einem frischen vollständigen SubscribedAck, und verwerfen Sie es niemals als Duplikat. SyncRequest gleicht den Anhangsbestand ab; SubscribedAck gleicht die gewünschte Richtlinie ab.
  • Ein Ereignis, das gleichzeitig mit der (Wieder-)Verbindung erzeugt wird, kann mit der Synchronisationsmomentaufnahme in beide Richtungen konkurrieren. Behandeln Sie ein Unsubscribed für eine unbekannte oder bereits entfernte Anhang-ID als No-Op.

Lebensdauer von Regeln (TTLs)

  • CIDR-Einträge (AllowCIDR/DenyCIDR-Befehle und die CIDR-Listen in SubscribedAck/BulkUpdate) tragen eine optionale TTL. TTL-basierte Regeln werden von einem Daemon-Janitor entfernt, sobald sie ablaufen (Scan-Intervall ttl_janitor_interval, Standard 1s); Regeln ohne TTL sind dauerhaft.
  • Inkrementelle AllowCIDR/DenyCIDR-Neuhinzufügungen verlängern eine CIDR bis zur späteren Frist – sie verkürzen niemals eine – und eine inkrementelle Neuhinzufügung ohne TTL macht sie dauerhaft. Im Gegensatz dazu ersetzt der vollständige Zustand in SubscribedAck/BulkUpdate jede Lebensdauer der Steuerungsebene genau, sodass autoritativer Abgleich eine TTL verkürzen oder dauerhaft in endlich ändern kann, ohne den Live-Map-Eintrag zu entfernen/neu hinzuzufügen. Verwenden Sie RemoveCIDR, um eine inkrementelle Regel vorzeitig zu entfernen.
  • DNS-aufgelöste IPs treten nur in die genaue Ebene mit der TTL des Datensatzes ein, begrenzt durch dns.min_filter_ttl (Standard 60s; null/nicht gesetzt bedeutet den Standard, nicht „keine Untergrenze“). Eine vorgelagerte TTL von Null lebt daher für die Untergrenze; eine ausgelassene PROXY-TTL wird explizit auf 300s standardmäßig gesetzt, bevor die Untergrenze angewendet wird. Eine dauerhafte oder längerlebige CIDR-Regel, die dieselbe Adresse abdeckt, bleibt unabhängig in der geschützten LPM-Ebene installiert, wenn die genaue DNS-Besitzerzeit abläuft.
Tool herunterladen
Internal scalability diagnosticCurrent medianMemory / allocations
Kalte Neuaufnahme eines Schlüssels, leerer Besitzgraph~370.3 ns232 B, 5 allocs/op
Kalte Neuaufnahme eines Schlüssels, 4.095 nicht verwandte Einträge~451.2 ns232 B, 5 allocs/op
Physischer Kapazitätsdruck und LRU-Ersatz~3.820 ms~4.23 MB (4,226,243 B), 4,336 allocs/op
Vorabprüfung des erschöpften physischen Budgets~611.9 ns344 B, 9 allocs/op
Maximaler Kantendruck, 64-Adress-Antwort~6.849 ms~7.66 MB (7,658,774 B), 2,233 allocs/op
Maximaler Graph-Arbeitswächter, erlaubter vollständiger Plan~2.763 ms~4.26 MB (4,264,386 B), 3,074 allocs/op
Maximaler Graph-Arbeitswächter, erschöpfte Vorprojektionsablehnung~10.935 us8.76 KB (8,760 B), 14 allocs/op
Churn-Budget-Operation nahe der numerischen Obergrenze~18.98 ns0 B, 0 allocs/op
Kohärenter Besitz-Statistik-Snapshot~2.094 ns0 B, 0 allocs/op
No-op-Ablaufscan über 4.095 Einträge~74.849 us/scan0 B, 0 allocs/op
netfenced apply-rules
  • DNS-Domain-Regeln, per-Attachment-Upstream-Übersteuerungen und Attachment-DNS-Limits sind Laufzeit-Soll-Zustände, die entweder über die lokale API oder die Steuerungsebene bereitgestellt werden; sie werden nicht persistiert. Ein wiederhergestelltes Attachment, dessen letzter DNS-Modus ALLOWLIST, DENYLIST oder PROXY war, startet seinen Resolver in einer leeren ALLOWLIST-Position und gibt REFUSED zurück, bis eine vollständige BulkUpdate oder SubscribedAck angewendet wird. Ein explizit DISABLED-DNS-Modus leitet weiterhin weiter. Wenn später einer der festgeschriebenen UDP/TCP-Listener unerwartet stirbt, wird das Attachment im IP-BLOCK_ALL-Modus unter Quarantäne gestellt und als Fehler-Unsubscribe gemeldet.
  • Der per-Attachment-DNS-Server ist eine Userspace-Komponente und wird mit dem Daemon beendet; während der Daemon ausgeschaltet ist, funktionieren gepinnte, bereits aufgelöste exakte IPs weiterhin unter der zuletzt bekannten Paketrichtlinie, aber neue Namen können nicht darüber aufgelöst werden. Ihre verlorenen Userspace-Fristen werden vorläufig behandelt, anstatt bis zur autoritativen Abgleichung geraten zu werden.
  • InterfaceRichtige RichtungBegründung
    Uplink (z. B. eth0) oder ein beliebiges Interface im eigenen Netns der Workloadegress (Standard)Die ausgehenden Pakete der Workload werden darüber gesendet; ihre Zieladresse ist das tatsächliche Ziel.
    Hostseitiger Veth-Peer oder VM-Tap (z. B. fcr-*)ingressDie ausgehenden Pakete der Workload treffen auf diesem Interface auf dem Host ein. Egress würde dort stattdessen den Rückverkehr Host→Workload sehen und nach der eigenen Adresse der Workload statt dem tatsächlichen Ziel filtern.
  • Bei subscribe_ack_timeout: 0 kehrt ein neuer Attach zurück, nachdem Subscribed in die Warteschlange gestellt wurde; ein späteres Ack wird dennoch validiert und angewendet. Dieser Nullwert deaktiviert nicht die Wiederherstellungskonvergenz wiederhergestellter Bindungen: Wiederherstellungsversuche warten bis zu 5 s im Hintergrund und wiederholen bei einer späteren Verbindung, falls nötig. Wenn dieses spätere Ack auf Druck der geschützten Map trifft, wird die bereits zurückgegebene Bindung in BLOCK_ALL beibehalten; SubscribedAck sendet weder CommandResult noch ein Fehler-Unsubscribed, und der Daemon fährt die Deklaration vor dem Neustart nicht automatisch erneut. Erkennen Sie policy_degraded plus dessen Grund, Belegung/Kapazität und map_full_drops in Heartbeat, senden Sie dann ein vollständiges BulkUpdate mit command_id, um ein explizites Wiederherstellungsergebnis zu erhalten.
  • Der Daemon überwacht die Entfernung des Ziels und sendet automatisch Unsubscribed.
  • Autoritative/System-Allow-CIDRs und Deny-CIDRs verbleiben in vier geschützten, nicht entfernbaren LPM-Maps, dimensioniert durch filter.max_rule_entries pro Anhang (Standard 4096 jeweils); siehe „Geschützte CIDR-Kapazität und Fail-Closed-Wiederherstellung“ oben. DNS-abgeleitete Hostadressen verwenden separate exakte HASH-Maps, dimensioniert durch filter.max_dns_rule_entries (Standard 4096 pro IP-Familie), sodass sie autoritative oder Deny-Kapazität weder verbrauchen noch verdrängen können. Die vollständige DNS-Antwortannahme validiert/kanonisiert jede Adresse und prüft physische und logische Kapazität vor der Mutation. Ein Kernel-Fehler der exakten DNS-Map stellt ihre exakte Voraufruf-Momentaufnahme wieder her; wenn dieses Rollback nicht nachgewiesen werden kann, unterdrückt der Resolver die Antwort und isoliert den Anhang in dauerhafter IP BLOCK_ALL, bevor er eine weitere Mutation akzeptiert.