Eine Schnittstelle gehört zu einem bestimmten Zeitpunkt zu einem Netzwerknamensraum und nur zu einem. Der init (anfängliche) Netzwerk-Namespace hat außer dem Erben physischer Schnittstellen zerstörter Netzwerk-Namespaces keine besonderen Fähigkeiten gegenüber anderen Netzwerk-Namespaces:Er kann ihre Schnittstellen nicht direkt sehen. Solange Sie sich noch in den PID- und Mount-Namespaces von init befinden, können Sie die Netzwerk-Namespaces immer noch finden, indem Sie verschiedene Informationen verwenden, die von /proc
verfügbar sind und zeigen schließlich ihre Schnittstellen an, indem Sie diese Netzwerk-Namespaces eingeben.
Ich werde Beispiele in der Shell bereitstellen.
-
Zählen Sie die Netzwerk-Namespaces auf
Dazu müssen Sie wissen, wie diese Namespaces existieren:solange eine Ressource sie aufrechterhält. Eine Ressource kann hier ein Prozess (eigentlich ein Thread eines Prozesses), ein Einhängepunkt oder ein offener Dateideskriptor (fd) sein. Diese Ressourcen werden alle in
/proc/
referenziert und auf eine abstrakte Pseudodatei imnsfs
zeigen Pseudo-Dateisystem, das alle Namespaces auflistet. Die einzige aussagekräftige Information dieser Datei ist ihr Inode, der den Netzwerknamensraum darstellt, aber der Inode kann nicht allein manipuliert werden, es muss die Datei sein. Deshalb können wir später nicht einfach nur den Inode-Wert behalten (gegeben durchstat -c %i /proc/some/file
):Wir behalten den Inode, um Duplikate und entfernen zu können einen Dateinamen, um noch eine brauchbare Referenz fürnsenter
zu haben später.-
Prozess (eigentlich Thread)
Der häufigste Fall:für übliche Container. Der Netzwerknamensraum jedes Threads kann über die Referenz
/proc/pid/ns/net
bekannt sein :nurstat
sie und listen alle eindeutigen Namespaces auf. Die2>/dev/null
ist zu verstecken, wennstat
kann keine ephemeren Prozesse mehr finden.find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do stat -L -c '%20i %n' $procpid/ns/net done 2>/dev/null
Mit dem spezialisierten
lsns
geht das schneller Befehl, der sich mit Namespaces befasst, aber scheinbar nur Prozesse behandelt (keine Einhängepunkte oder open fd, wie später zu sehen ist):lsns -n -u -t net -o NS,PATH
(was später in
lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done
umformatiert werden müsste ) -
Einhängepunkt
Diese werden hauptsächlich von
ip netns add
verwendet Befehl, der permanente Netzwerk-Namespaces erstellt, indem er sie einhängt, wodurch verhindert wird, dass sie verschwinden, wenn es keinen Prozess oder keine fd-Ressource gibt, die sie aufrechterhält, und es dann beispielsweise auch ermöglicht, einen Router, eine Firewall oder eine Bridge in einem Netzwerk-Namespace ohne einen verknüpften Prozess auszuführen.Gemountete Namespaces (die Handhabung von Mount- und vielleicht PID-Namespaces ist wahrscheinlich komplexer, aber wir interessieren uns sowieso nur für Netzwerk-Namespaces) erscheinen wie jeder andere Mount-Punkt in
/proc/mounts
, mit dem Dateisystemtypnsfs
. In der Shell gibt es keine einfache Möglichkeit, einen Netzwerk-Namespace von einem anderen Namespace-Typ zu unterscheiden, aber da zwei Pseudodateien aus demselben Dateisystem (hiernsfs
) nicht denselben Inode verwenden, wählen Sie einfach alle aus und ignorieren Sie Fehler später im Schnittstellenschritt, wenn Sie versuchen, eine Nicht-Netzwerk-Namespace-Referenz als Netzwerk-Namespace zu verwenden. Tut mir leid, unten werde ich Einhängepunkte mit Sonderzeichen, einschließlich Leerzeichen, nicht korrekt handhaben, da sie bereits in/proc/mounts
maskiert sind 's Ausgabe (in jeder anderen Sprache wäre es einfacher), also werde ich mich auch nicht darum kümmern, nullterminierte Zeilen zu verwenden.awk '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do stat -c '%20i %n' "$mount" done
-
Dateideskriptor öffnen
Diese sind wahrscheinlich noch seltener als Einhängepunkte, außer vorübergehend bei der Namespace-Erstellung, können aber von einer spezialisierten Anwendung gehalten und verwendet werden, die mehrere Namespaces handhabt, einschließlich möglicherweise einiger Containerisierungstechnologie.
Ich könnte mir keine bessere Methode ausdenken, als alle fd zu durchsuchen, die in jedem
/proc/pid/fd/
verfügbar sind , verwenden Sie stat, um zu überprüfen, ob es aufnsfs
zeigt Namespace und kümmert sich jetzt wieder nicht darum, ob es sich wirklich um einen Netzwerk-Namespace handelt. Ich bin mir sicher, dass es eine optimiertere Schleife gibt, aber diese wird zumindest nicht überall herumwandern oder eine maximale Prozessgrenze annehmen.find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do find $procpid/fd -mindepth 1 | while read -r procfd; do if [ "$(stat -f -c %T $procfd)" = nsfs ]; then stat -L -c '%20i %n' $procfd fi done done 2>/dev/null
Entfernen Sie nun alle doppelten Netzwerk-Namespace-Referenzen aus den vorherigen Ergebnissen. ZB durch Verwendung dieses Filters auf die kombinierte Ausgabe der 3 vorherigen Ergebnisse (insbesondere aus dem offenen Dateideskriptorteil):
sort -k 1n | uniq -w 20
-
-
Zählen Sie in jedem Namensraum die Schnittstellen auf
Jetzt haben wir die Verweise auf alle existierenden Netzwerk-Namensräume (und auch einige Nicht-Netzwerk-Namensräume, die wir einfach ignorieren werden), geben Sie einfach jeden von ihnen unter Verwendung der Referenz ein und zeigen Sie die Schnittstellen an.
Verwenden Sie die Ausgabe der vorherigen Befehle als Eingabe für diese Schleife, um Schnittstellen aufzulisten (und wählen Sie gemäß der Frage von OP, ihre Adressen anzuzeigen), während Sie Fehler ignorieren, die durch Nicht-Netzwerk-Namespaces verursacht werden, wie zuvor erläutert:
while read -r inode reference; do if nsenter --net="$reference" ip -br address show 2>/dev/null; then printf 'end of network %d\n\n' $inode fi done
Der Inode des Init-Netzwerks kann mit PID 1 als Referenz ausgegeben werden:
echo -n 'INIT NETWORK: ' ; stat -L -c %i /proc/1/ns/net
Beispielausgabe (echt, aber redigiert) mit einem laufenden LXC-Container, einem leeren "gemounteten" Netzwerk-Namespace, der mit ip netns add ...
erstellt wurde mit einer unverbundenen Bridge-Schnittstelle, einem Netzwerk-Namensraum mit einem anderen dummy0
Schnittstelle, die von einem nicht Prozess am Leben erhalten wird in diesem Netzwerk-Namespace, aber ein offenes fd darauf, erstellt mit:
unshare --net sh -c 'ip link add dummy0 type dummy; ip address add dev dummy0 10.11.12.13/24; sleep 3' & sleep 1; sleep 999 < /proc/$!/ns/net &
und ein laufender Firefox, der jeden seiner "Web Content"-Threads in einem unverbundenen Netzwerk-Namespace isoliert (alle diese unten lo
Schnittstellen):
lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 192.0.2.2/24 2001:db8:0:1:bc5c:95c7:4ea6:f94f/64 fe80::b4f0:7aff:fe76:76a8/64 wlan0 DOWN dummy0 UNKNOWN 198.51.100.2/24 fe80::108a:83ff:fe05:e0da/64 lxcbr0 UP 10.0.3.1/24 2001:db8:0:4::1/64 fe80::216:3eff:fe00:0/64 virbr0 DOWN 192.168.122.1/24 virbr0-nic DOWN [email protected] UP fe80::fc8e:ff:fe85:476f/64 end of network 4026531992 lo DOWN end of network 4026532418 lo DOWN end of network 4026532518 lo DOWN end of network 4026532618 lo DOWN end of network 4026532718 lo UNKNOWN 127.0.0.1/8 ::1/128 [email protected] UP 10.0.3.66/24 fe80::216:3eff:fe6a:c1e9/64 end of network 4026532822 lo DOWN bridge0 UNKNOWN fe80::b884:44ff:feaf:dca3/64 end of network 4026532923 lo DOWN dummy0 DOWN 10.11.12.13/24 end of network 4026533021 INIT NETWORK: 4026531992