Geschichte der programmatischen Schnittstellen zu iptables, ipchains und ipfw
Ich musste in iptablesletzter Zeit ein bisschen mit den Regeln von Go herumspielen , und ich bemerkte, dass sowohl die Wrapper-Bibliotheken von Docker als auch von Coreosexec() auf den iptablesBefehl und den Bildschirm die Standardausgabe kratzten . Das schien mir überraschend.
In Python-Land gibt es Python-Iptables :
Die Interoperabilität mit iptables wird erreicht, indem die iptables C-Bibliotheken (libiptc, libxtables und die iptables-Erweiterungen) verwendet werden, die iptables-Binärdatei nicht aufgerufen und ihre Ausgabe analysiert wird.
Ich denke, eine Python-Bibliothek darf zur Laufzeit C-Bibliotheken laden, und Go kann nicht [bearbeiten: Ich liege falsch], aber Go kann nicht statisch mit diesen Bibliotheken verknüpft werden? Weil die Go-Bibliothek libxtables.ausw. von irgendwoher bekommen müsste ? (Ich bin dpkg -Ldie relevanten -devPakete in Debian, und ich sehe nur .sos.)
Wie auch immer, laut Netfilter FAQ :
4.5 Gibt es eine C / C ++ - API zum Hinzufügen / Entfernen von Regeln?
Die Antwort lautet leider: Nein.
Jetzt könnten Sie denken, aber was ist mit libiptc? Wie bereits mehrfach auf der Mailingliste (n) darauf hingewiesen wurde libiptc nie als öffentliche Schnittstelle verwendet werden soll. Wir garantieren keine stabile Schnittstelle und es ist geplant, sie in der nächsten Inkarnation des Linux-Pakets zu entfernen
Wir sind uns bewusst, dass es einen grundlegenden Mangel für eine solche API gibt, und wir arbeiten daran, diese Situation zu verbessern. Bis dahin wird empfohlen, entweder system () zu verwenden oder eine Pipe in stdin von iptables-restore zu öffnen. Letzteres bietet Ihnen eine bessere Leistung. Filtern. libiptc ist viel zu niedrig, um überhaupt vernünftig verwendet zu werden.
Ok, vielleicht sollten Sie diese C-Bibliotheken nicht als stabil behandeln. Dann dachte ich: "Warum nicht einfach direkt mit /procoder was auch immer reden ?" Es stellt sich heraus, dass iptablesmeistens nicht /procmit dem Kernel gesprochen wird (nur um Tabellennamen zu lesen?), Und die Hauptschnittstelle befindet sich tatsächlich getsockopt()und setsockopt()auf einem ungebundenen Socket.
Dies war eine weitere Überraschung! (Aber vielleicht scheint es eine lustige Art zu sein, mit dem Kernel zu kommunizieren, nur weil ich mit dieser Art von Code nicht vertraut bin.)
Ich habe ein bisschen Archäologie von iptablesbis ipchainsnach gemacht ipfwund eine ipfw-Manpage von 1997 gefunden, auf der ich mich ein bisschen besser fühlte:
BUGS
The setsockopt(2) interface is a crock. This should be
put under /proc/sys/net/ipv4 and the world would be a bet-
ter place.
Sie finden an anderer Stelle, dass "Das Dienstprogramm ipfw zum ersten Mal in FreeBSD 2.0 angezeigt wurde" und
HISTORY
Initially this utility was written for BSDI by:
Daniel Boulet <[email protected]>
The FreeBSD version is written completely by:
Ugen J.S.Antsilevich <[email protected]>
while synopsis partially compatible with old one.
Hier ist die FreeBSD 2.0-Version ipfwvon 1994 . Es verwendet immer noch setsockopt(), aber es scheint zu verwenden , kvm_read()statt getsockopt().
Meine Fragen
- Bitte korrigieren Sie alles, was ich oben falsch gesagt habe :)
- Warum haben sie sich überhaupt entschieden
{get,set}sockopt()? Ist es ungewöhnlich oder nur neu für mich? - Warum wurde es nicht irgendwann geändert? Wie zu etwas unter,
/procwie die Manpage von 1997 andeutet. - Warum haben sie sich nie eine stabile / öffentliche C-Schnittstelle ausgedacht
iptables?
Meine Anschlussfragen
"Nicht ganz, die Hauptschnittstelle ist die NETLINK_NETFILTER-Familie von netlink."
Danke für diesen Hinweis!
Ich schaue auf https://git.netfilter.org/iptables/treeund libipqscheint nur einen Netlink-Socket zu verwenden, es sei denn, ich vermisse etwas.
$ ick "socket\("
include/libiptc/libiptc.h
158:int iptc_get_raw_socket(void);
include/libiptc/libip6tc.h
152:int ip6tc_get_raw_socket(void);
utils/nfsynproxy.c
129: fd = socket(AF_INET, SOCK_STREAM, 0);
libiptc/libiptc.c
1312: sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
extensions/libxt_set.h
14: int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
libipq/libipq.c
223: h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
225: h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);
libxtables/xtables.c
881: sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);
Die libipqSachen Aussehen „normal“ zu mir: eine Steckdose machen, binden sie mit einem sockaddr, sendto(), recvfrom()etc.
Auch xtables-monitorscheint einige zu verwenden mnl_socket_*Wrapper , die netlink Sachen tun.
Aber ich kann es nicht herausfinden libiptcund xtables- keine Erwähnung von Netlink, und sie binden nicht einmal den Socket.
https://git.netfilter.org/iptables/tree/libxtables/xtables.c#n881
https://git.netfilter.org/iptables/tree/libiptc/libiptc.c#n1312
Es gibt andere Beispiele, die Netlink nicht verwenden (scheinen?), Wie diesen Code aus Mozillas rr-Debugger: https://github.com/mozilla/rr/blob/master/src/test/netfilter.c
Und netlink ist ab dem Jahr 2000 (2.2) nur für Linux verfügbar, während dieses {get,set}sockopt()Zeug (zumindest) ipfwälter ist und im BSD-Land.
Ich bin mir nicht mehr sicher, was meine Frage ist :) Wie kommunizieren die Nicht-Netlink-Sockets irgendwie mit dem richtigen bind()kernelseitigen Ding ohne gerade und ohne Sockaddr?
Antworten
Ich denke, eine Python-Bibliothek darf zur Laufzeit C-Bibliotheken laden, und Go kann nicht
Go kann gemeinsam genutzte C-Bibliotheken verwenden.
Es stellt sich heraus, dass
iptablesmeistens nicht/procmit dem Kernel gesprochen wird (nur um Tabellennamen zu lesen?), Und die Hauptschnittstelle ist tatsächlichgetsockopt()undsetsockopt().
Warum haben sie sich überhaupt entschieden
{get,set}sockopt()? Ist es ungewöhnlich oder nur neu für mich?
(Diese Antwort bereits erwähnt, nicht richtig, dass die wichtigste Schnittstelle ist netlink‚s NETLINK_NETFILTERFamilie.)
Sie haben Recht, iptablesverwenden Aufrufe getsockoptan ungebundenen Sockets des entsprechenden Typs, um mit dem Kernel zu interagieren, wodurch der netfilterCode des Kernels aufgerufen wird . Ich vermute, das hat historische Gründe ...
Übrigens, getsockoptund setsockoptarbeiten Sie an Sockets in einer Vielzahl von Zuständen, einschließlich ungebunden, und sie müssen, weil sie verwendet werden, um Optionen vor dem Verbinden festzulegen. Die netfilter-via- sockoptVerbindung ist effektiv ein Seitenkanal.
Warum wurde es nicht irgendwann geändert? Wie zu etwas unter,
/procwie die Manpage von 1997 andeutet.
Es gibt wahrscheinlich eine Reihe von Gründen, aber es besteht kein Zweifel an der Abwärtskompatibilität - unter Linux sollten Benutzer-Space-Schnittstellen niemals kaputt gehen. Während also eine neue Schnittstelle bereitgestellt werden könnte, würde die vorhandene erhalten bleiben, was den Anreiz verringert, sie zu verbessern oder bereits funktionierende Programme neu zu schreiben.
Solange das iptablesBefehlszeilentool mit nicht allzu viel Aufwand verwendet werden kann und die Bereitstellung einer besseren Benutzeroberfläche viel mehr Aufwand erfordert, wäre eine Änderung schwierig. Eine ordnungsgemäß gewartete libiptcBibliothek im Stil wäre ebenfalls eine Möglichkeit gewesen, aber für die iptablesEntwickler gab es nie einen großen Anreiz , dies zu tun.
Warum haben sie sich nie eine stabile / öffentliche C-Schnittstelle ausgedacht
iptables?
Weil „sie“ nie dazu gekommen sind. Jetzt iptableszugunsten schrittweise aus wird nftables, die eine Reihe von Bibliotheken umfasst den Zugriff auf verschiedenen Abstraktionsebenen bereitstellt ( libnftables, libnftnl, libnfnetlink). Diese Verwendung netlink, die als Sockets-basierte Schnittstelle zum Übertragen von Informationen zwischen dem Kernel und dem Benutzerbereich konzipiert wurde, eignet sich natürlich für Tools wie nftables(und iptables). In der netlinkDokumentation sind die anderen verfügbaren Familien aufgeführt. Diese decken eine ganze Reihe von Kernel-gehosteten Funktionen ab. netlink.
Sie könnten finden https://github.com/vishvananda/netlinknützlich, um iptablesvon Go aus loszufahren. (Dafür braucht es eine Menge Arbeit, aber es ist besser, als bei Null anzufangen.)