如何找到所有已在 Linux 中配置的介面,包括容器的介面?
我知道你可以通過做來顯示界面
ip a show
。那隻顯示主機可以看到的介面,但容器配置的虛擬介面不會出現在這個列表中。我也嘗試過使用ip netns
,它們也沒有出現。我應該重新編譯另一個版本iproute2
嗎?在/proc/net/fb_trie
中,您可以看到本地/廣播地址,我假設,作為轉發數據庫的用途。我在哪裡可以找到這些資訊或列出所有介面(包括容器)的命令?
要對此進行測試,請啟動一個容器。就我而言,它是 snap 上的 lxc 容器。做一個
ip a
或ip l
。它將顯示主機的視圖,但不顯示容器配置的界面。我正在通過grepping ,因為容器只是 cgrouped 程序,但除了和 arp 條目procfs
之外我沒有得到任何東西。fib_trie
我認為這可能是由於 netns 命名空間混淆,但ip netns
也沒有顯示任何內容。您可以使用
conntrack -L
顯示所有已建立的傳入和傳出連接,因為 lxd 需要連接跟踪數據包的轉發,但我想列出系統上配置的所有 IP 地址,就像我能做到的那樣告訴使用netstat
orlsof
。
一個介面,在給定的時間,屬於一個網路命名空間並且只屬於一個。init(初始)網路命名空間,除了繼承被破壞的網路命名空間的物理介面外,對其他網路命名空間沒有特殊的能力:它不能直接看到它們的介面。只要你還在 init 的 pid 和 mount 命名空間中,你仍然可以通過使用不同的可用資訊找到網路命名空間,
/proc
並最終通過輸入這些網路命名空間來顯示它們的介面。我將在 shell 中提供範例。
- 列舉網路命名空間
為此,您必須知道這些名稱空間是如何存在的:只要資源保持它們。這裡的資源可以是程序(實際上是程序的執行緒)、掛載點或打開的文件描述符(fd)。這些資源都被引用
/proc/
並指向偽文件系統中nsfs
列舉所有命名空間的抽象偽文件。這個文件唯一有意義的資訊是它的inode,代表網路命名空間,但是inode不能單獨操作,它必須是文件。這就是為什麼稍後我們不能只保留 inode值stat -c %i /proc/some/file
(由nsenter
- 程序(實際上是執行緒)
最常見的情況:對於普通容器。每個執行緒的網路命名空間都可以通過引用獲知
/proc/pid/ns/net
:僅stat
它們並列舉所有唯一的命名空間。這是在找不到臨時程序2>/dev/null
時隱藏。stat
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
可以通過[`lsns`](https://manpages.debian.org/util-linux/lsns.8)處理命名空間的專用命令更快地完成,但似乎只處理程序(不是掛載點,也不是打開 fd,如後面所示):
ns -n -u -t net -o NS,PATH
必須重新格式化以備後用`lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done`) 掛載點 些主要由`ip netns add`通過安裝它們來創建永久網路命名空間的命令使用,從而避免它們在沒有程序或 fd 資源保持它們時消失,然後還允許例如在網路命名空間中執行路由器、防火牆或網橋而不任何關聯的過程。 載的命名空間(處理掛載和可能的 pid 命名空間可能更複雜,但我們只對網路命名空間感興趣)看起來像 中的任何其他掛載點`/proc/mounts`,文件系統類型為`nsfs`。在 shell 中沒有簡單的方法來區分網路命名空間和其他類型的命名空間,但是由於來自同一文件系統(此處)的兩個偽文件`nsfs`不會共享相同的 inode,只需將它們全部選中並稍後在界面中忽略錯誤嘗試使用非網路命名空間引用作為網路命名空間時的步驟。抱歉,下面我不會正確處理帶有特殊字元(包括空格)的掛載點,因為它們已經在`/proc/mounts`'s 的輸出中轉義(在任何其他語言中都會更容易),所以我不會費心使用 null終止的行。
k '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do at -c '%20i %n' "$mount" ne
打開文件描述符 些可能比掛載點更罕見,除了在命名空間創建時臨時,但可能由一些處理多個命名空間的專門應用程序持有和使用,包括可能的一些容器化技術。 無法設計出比在 every 中搜尋所有可用 fd 更好的方法`/proc/pid/fd/`,使用 stat 來驗證它指向一個`nsfs`命名空間,並且現在再次不在乎它是否真的是一個網路命名空間。我確信有一個更優化的循環,但這個循環至少不會到處亂跑,也不會假設任何最大程序限制。
nd /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do nd $procpid/fd -mindepth 1 | while read -r procfd; do [ "$(stat -f -c %T $procfd)" = nsfs ]; then at -L -c '%20i %n' $procfd ne ne 2>/dev/null `現在從以前的結果中刪除所有重複的網路命名空間引用。例如,通過在 3 個先前結果的組合輸出上使用此過濾器(尤其是來自打開的文件描述符部分):
sort -k 1n | uniq -w 20
* **在每個命名空間中列舉介面** 現在我們有了對所有現有網路命名空間的引用(以及一些我們將忽略的非網路命名空間),只需使用引用輸入它們中的每一個並顯示介面。 將先前命令的輸出作為此循環的輸入以列舉介面(並根據 OP 的問題,選擇顯示它們的地址),同時忽略由非網路命名空間引起的錯誤,如前所述:
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
初始化網路的 inode 可以列印 pid 1 作為參考:
echo -n ‘INIT NETWORK: ’ ; stat -L -c %i /proc/1/ns/net
使用正在執行的 LXC 容器的範例(真實但經過編輯)輸出,使用`ip netns add ...`未連接的網橋介面創建的空“已安裝”網路名稱空間,具有其他介面的網路名稱空間,由*不在*此網路名稱空間中但保持打開`dummy0`的程序保持活動狀態fd 就可以了,創建:
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 &
*和*一個正在執行的 Firefox,它將它的每個“Web 內容”執行緒隔離在一個未連接的網路命名空間(所有那些關閉的`lo`介面)中:
lo 未知 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 關閉 dummy0 未知 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 關閉 vethSOEPSH@if9 UP fe80::fc8e:ff:fe85:476f/64 網路結束 4026531992
向下 網路結束 4026532418
向下 網路結束 4026532518
向下 網路結束 4026532618
向下 網路結束 4026532718
lo 未知 127.0.0.1/8 ::1/128 eth0@if10 UP 10.0.3.66/24 fe80::216:3eff:fe6a:c1e9/64 網路結束 4026532822
向下 bridge0 未知 fe80::b884:44ff:feaf:dca3/64 網路結束 4026532923
向下 dummy0 DOWN 10.11.12.13/24 網路結束 4026533021
初始化網路:4026531992