Antarmuka, pada waktu tertentu, milik satu ruang nama jaringan dan hanya satu. Namespace jaringan init (awal), kecuali untuk mewarisi antarmuka fisik dari namespace jaringan yang dihancurkan tidak memiliki kemampuan khusus dibandingkan namespace jaringan lain:ia tidak dapat melihat langsung antarmuka mereka. Selama Anda masih dalam pid init dan me-mount ruang nama, Anda masih dapat menemukan ruang nama jaringan dengan menggunakan berbagai informasi yang tersedia dari /proc
dan akhirnya tampilkan antarmuka mereka dengan memasukkan ruang nama jaringan tersebut.
Saya akan memberikan contoh di shell.
-
menghitung ruang nama jaringan
Untuk ini, Anda harus tahu bagaimana ruang nama itu ada:selama sumber daya mempertahankannya. Sumber daya di sini dapat berupa proses (sebenarnya utas proses), titik pemasangan, atau deskriptor file terbuka (fd). Sumber daya tersebut semuanya dirujuk dalam
/proc/
dan arahkan ke file pseudo abstrak dinsfs
pseudo-filesystem menghitung semua ruang nama. Satu-satunya informasi yang berarti dari file ini adalah inode-nya, yang mewakili ruang nama jaringan, tetapi inode tidak dapat dimanipulasi sendiri, harus berupa file. Itu sebabnya nanti kita tidak bisa hanya menyimpan nilai inode saja (diberikan olehstat -c %i /proc/some/file
):kami akan menyimpan inode untuk dapat menghapus duplikat dan nama file agar tetap memiliki referensi yang dapat digunakan untuknsenter
nanti.-
proses (sebenarnya utas)
Kasus paling umum:untuk wadah biasa. Namespace jaringan setiap utas dapat diketahui melalui referensi
/proc/pid/ns/net
:cukupstat
mereka dan menghitung semua ruang nama yang unik.2>/dev/null
adalah menyembunyikan kapanstat
tidak dapat menemukan proses sesaat lagi.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
Ini dapat dilakukan lebih cepat dengan
lsns
khusus perintah yang berurusan dengan ruang nama, tetapi tampaknya hanya menangani proses (bukan mount point atau buka fd seperti yang terlihat nanti):lsns -n -u -t net -o NS,PATH
(yang harus diformat ulang untuk nanti sebagai
lsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done
) -
titik pemasangan
Itu sebagian besar digunakan oleh
ip netns add
perintah yang membuat ruang nama jaringan permanen dengan memasangnya, sehingga menghindarinya menghilang ketika tidak ada proses atau sumber daya fd yang mempertahankannya, kemudian juga memungkinkan misalnya untuk menjalankan router, firewall, atau jembatan di ruang nama jaringan tanpa proses yang ditautkan.Ruang nama yang dipasang (menangani mount dan mungkin ruang nama pid mungkin lebih rumit tetapi kami hanya tertarik pada ruang nama jaringan) muncul seperti titik pemasangan lainnya di
/proc/mounts
, dengan tipe sistem filensfs
. Tidak ada cara mudah di shell untuk membedakan namespace jaringan dari tipe namespace lain, tetapi karena dua file pseudo dari sistem file yang sama (di sininsfs
) tidak akan berbagi inode yang sama, cukup pilih semuanya dan abaikan kesalahan nanti di langkah antarmuka saat mencoba menggunakan referensi namespace non-jaringan sebagai namespace jaringan. Maaf, di bawah ini saya tidak akan menangani dengan benar titik pemasangan dengan karakter khusus di dalamnya, termasuk spasi, karena sudah di-escape di/proc/mounts
output (akan lebih mudah dalam bahasa lain), jadi saya tidak akan repot-repot menggunakan baris yang diakhiri null.awk '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do stat -c '%20i %n' "$mount" done
-
buka deskriptor file
Itu bahkan mungkin lebih jarang daripada titik pemasangan kecuali untuk sementara saat pembuatan namespace, tetapi mungkin dipegang dan digunakan oleh beberapa aplikasi khusus yang menangani beberapa ruang nama, termasuk mungkin beberapa teknologi penampung.
Saya tidak bisa menemukan metode yang lebih baik daripada mencari semua fd yang tersedia di setiap
/proc/pid/fd/
, menggunakan stat untuk memverifikasi bahwa itu mengarah kensfs
namespace dan sekali lagi tidak peduli sekarang apakah itu benar-benar namespace jaringan. Saya yakin ada loop yang lebih dioptimalkan, tetapi yang ini setidaknya tidak akan berkeliaran di mana-mana atau menerima batas proses maksimum apa pun.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
Sekarang hapus semua referensi namespace jaringan duplikat dari hasil sebelumnya. Misalnya dengan menggunakan filter ini pada keluaran gabungan dari 3 hasil sebelumnya (terutama dari bagian deskriptor file terbuka):
sort -k 1n | uniq -w 20
-
-
di setiap ruang nama sebutkan antarmuka
Sekarang kita memiliki referensi ke semua ruang nama jaringan yang ada (dan juga beberapa ruang nama non-jaringan yang akan kita abaikan saja), cukup masukkan masing-masing menggunakan referensi dan tampilkan antarmuka.
Ambil keluaran perintah sebelumnya sebagai input ke loop ini untuk menghitung antarmuka (dan sesuai pertanyaan OP, pilih untuk menampilkan alamatnya), sambil mengabaikan kesalahan yang disebabkan oleh ruang nama non-jaringan seperti yang dijelaskan sebelumnya:
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 jaringan init dapat dicetak dengan pid 1 sebagai referensi:
echo -n 'INIT NETWORK: ' ; stat -L -c %i /proc/1/ns/net
Contoh keluaran (nyata tetapi disunting) dengan wadah LXC yang sedang berjalan, namepace jaringan "terpasang" kosong yang dibuat dengan ip netns add ...
memiliki antarmuka jembatan yang tidak terhubung, ruang nama jaringan dengan dummy0
lainnya antarmuka, tetap hidup dengan proses bukan di ruang nama jaringan ini tetapi tetap membuka fd di atasnya, dibuat dengan:
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 &
dan Firefox yang sedang berjalan yang mengisolasi setiap utas "Konten Web" di ruang nama jaringan yang tidak terhubung (semuanya turun lo
antarmuka):
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