Deep Dive Linux Network Namespace

Pahrial Ms
9 min readApr 9, 2023

--

Photo by David Knox on Unsplash

Namespace membuat seolah-olah suatu container memiliki filesystem, proses, dan network nya sendiri atau terisolasi dari proses yang lain, namun dari sisi host proses didalam container masih terafiliasi dengan proses di host dengan pid yang unik. Begitu pula dengan network namespace, container seolah-olah memiliki network nya sendiri, beserta dengan interface, ip address, dan routing.

Mari kita lihat bagaimana sebenarnya network namespace bekerja, membuat container memiliki serangkaian ip address, dan bisa berkomunikasi dengan antar namespace dan komunikasi keluar namespace.

Membuat Network Namespace di Linux

Dalam catatan ini saya akan membuat dua network namespace dengan nama yellow and green :

# ip netns add yellow
# ip netns add green
# ip netns
green
yellow

Apabila kita lihat network namespace (ns) yang baru saya buat, hanya akan memiliki interfae loopback :

# ip -n yellow addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# ip -n green addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Kita bisa gunakan perintah ip netns exec green ip address atau bisa disingkat dengan ip -n green address.

Buat interface untuk setiap ns kemudian hubungkan dengan peer agar antar ns dapat saling berkomunikasi. Saya beri nama veth-yellow untuk interface ns yellow dan veth-green untu ns green.

# ip link add veth-yellow type veth peer name veth-green

Pasang interface yang telah dibuat ke masing-masing ns dengan perintah berikut :

# ip link set veth-yellow netns yellow
# ip link set veth-green netns green

# ip -n yellow addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
11: veth-yellow@if10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 16:84:7a:55:03:ec brd ff:ff:ff:ff:ff:ff link-netnsid 1
# ip -n green addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: veth-green@if11: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether ae:0e:a4:6e:8a:b7 brd ff:ff:ff:ff:ff:ff link-netnsid 0

Terlihat diatas, ketika saya cek kembali ns memiliki dua interface saat ini.

Tambahkan ip ke setiap interface veth kemudian aktifkan interfacenya, disini saya gunakan network 192.168.17.0/24 :

# ip -n yellow add add 192.168.17.1/24 dev veth-yellow
# ip -n green add add 192.168.17.2/24 dev veth-green
# ip -n yellow link set up veth-yellow
# ip -n green link set up veth-green

# ip -n yellow addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
11: veth-yellow@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 16:84:7a:55:03:ec brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 192.168.17.1/24 scope global veth-yellow
valid_lft forever preferred_lft forever
inet6 fe80::1484:7aff:fe55:3ec/64 scope link
valid_lft forever preferred_lft forever

# ip -n green addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: veth-green@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ae:0e:a4:6e:8a:b7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.17.2/24 scope global veth-green
valid_lft forever preferred_lft forever
inet6 fe80::ac0e:a4ff:fe6e:8ab7/64 scope link
valid_lft forever preferred_lft forever

Sampai disini kita sudah bisa lakukan test ping antar ns terhadap ip-ip yang telah kita set :

# ip netns exec yellow ping -c 2 192.168.17.2
PING 192.168.17.2 (192.168.17.2) 56(84) bytes of data.
64 bytes from 192.168.17.2: icmp_seq=1 ttl=64 time=0.060 ms
64 bytes from 192.168.17.2: icmp_seq=2 ttl=64 time=0.052 ms

--- 192.168.17.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1011ms
rtt min/avg/max/mdev = 0.052/0.056/0.060/0.004 ms

# ip netns exec green ping -c 2 192.168.17.1
PING 192.168.17.1 (192.168.17.1) 56(84) bytes of data.
64 bytes from 192.168.17.1: icmp_seq=1 ttl=64 time=0.021 ms
64 bytes from 192.168.17.1: icmp_seq=2 ttl=64 time=0.044 ms

--- 192.168.17.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1015ms
rtt min/avg/max/mdev = 0.021/0.032/0.044/0.012 ms

Dan jika kita lihat table arp yang dimiliki masing-masing ns hanya akan memiliki satu list dari masing-masing mac address neighbors nya, dimana ns yellow memiliki arp ke ns green dan begitu pula sebaliknya :

# ip netns exec yellow arp
Address HWtype HWaddress Flags Mask Iface
192.168.17.2 ether ae:0e:a4:6e:8a:b7 C veth-yellow

# ip netns exec green arp
Address HWtype HWaddress Flags Mask Iface
192.168.17.1 ether 16:84:7a:55:03:ec C veth-green

Kemudian bagaimana jika kita memiliki banyak ns atau container, bagaimana cara kita menghubungkannya ? sama seperti pada kondisi nyata, kita cukup menambahkan switch, nanti kita akan hubungkan setiap ns ke switch agar antar ns yang banyak tersebut dapat saling terkoneksi :

Inter Koneksi Antar NS dengan Linux Bridge

Kita juga bisa gunakan Open Vswitch untuk menyelesaikan tugas ini, tetapi disini saya gunakan linux bridge untuk membuat switch/bridge .

# ip link add v-net-1 type bridge
# ip link set v-net-1 up

Sama seperti sebelumnya, tambahkan ip address dan bring up interface ns dan bridge, ya bedanya kita buat interface yang di peering ke interface bridgenya. Sebelum itu jangan lupa hapus interface peer yang kita buat diawal (menghapus satu interface akan otomatis menghapus interface peernya) :

# ip -n yellow link del veth-yellow
# ip link add veth-yellow type veth peer name veth-yellow-br
# ip link add veth-green type veth peer name veth-green-br
# ip link set veth-yellow netns yellow
# ip link set veth-green netns green
# ip link set veth-yellow-br master v-net-1
# ip link set veth-green-br master v-net-1

# ip -n yellow addr add 192.168.17.1/24 dev veth-yellow
# ip -n green addr add 192.168.17.2/24 dev veth-green

# ip link set veth-yellow-br up
# ip link set veth-green-br up
# ip link set v-net-1 up

# ip -n yellow link set veth-yellow up
# ip -n green link set veth-green up
# ip -n yellow addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
14: veth-yellow@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 92:b5:f3:de:a6:80 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.17.1/24 scope global veth-yellow
valid_lft forever preferred_lft forever
inet6 fe80::90b5:f3ff:fede:a680/64 scope link
valid_lft forever preferred_lft forever

# ip -n green addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
16: veth-green@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 3a:8e:d5:34:02:6d brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 192.168.17.2/24 scope global veth-green
valid_lft forever preferred_lft forever
inet6 fe80::388e:d5ff:fe34:26d/64 scope link
valid_lft forever preferred_lft forever

Jika lakukan test ping dari ns yellow ke green hasilnya akan success, begitu juga jika dilakukan ping sebaliknya:

# ip netns exec yellow ping -c2 192.168.17.2
PING 192.168.17.2 (192.168.17.2) 56(84) bytes of data.
64 bytes from 192.168.17.2: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 192.168.17.2: icmp_seq=2 ttl=64 time=0.050 ms

--- 192.168.17.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.032/0.041/0.050/0.009 ms

Tetapi jika kita jalankan test ping dari host ke ns yellow dan green, hasilnya network unreacheable :

# ping -c 1 192.168.17.1
PING 192.168.17.1 (192.168.17.1) 56(84) bytes of data.

--- 192.168.17.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

Mengapa gagal ping ? karena kita belum tambahkan ip ke interface bridge di hostnya, ya kita bisa tambahkan ip ke interface bridge nya, karena interface bridge tersebut merupakan interface yang dimiliki oleh host tersebut, yang memungkinkan untuk terhubung ke ns, tambahkan ip kemudian test ping kembali :

# ip addr add 192.168.17.5/24 dev v-net-1

# ping -c 1 192.168.17.1
PING 192.168.17.1 (192.168.17.1) 56(84) bytes of data.
64 bytes from 192.168.17.1: icmp_seq=1 ttl=64 time=0.125 ms

--- 192.168.17.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.125/0.125/0.125/0.000 ms

# ping -c 1 192.168.17.2
PING 192.168.17.2 (192.168.17.2) 56(84) bytes of data.
64 bytes from 192.168.17.2: icmp_seq=1 ttl=64 time=0.058 ms

--- 192.168.17.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.058/0.058/0.058/0.000 ms

Terlihat setelah ditambahkan ip address pada bridge, host dapat terhubung ke ns.

Selanjutnya bagaiman jika container ingin terhubung ke host lain ?, mari coba kita test ping dari ns yellow ke ip 172.16.50.11 milik host lain :

# ip netns exec yellow ping -c 2 172.16.50.11
connect: Network is unreachable

Hasilnya ping “Network is unreachable”, mengapa ? karena kita belum tambahkan routing ke network 172.16.50.0/24 ke dalam ns yellow dan juga nat, mari kita cek table routing ns yellow:

# ip -n yellow route
192.168.17.0/24 dev veth-yellow proto kernel scope link src 192.168.17.1

Terlihat hanya ada routing ke network ns nya sendiri, Oleh karena itu kita harus tambahkan routing ke network tersebut melalui gateway 192.168.17.5 yang merupakan ip dari interface bridge v-net-1, karena seperti yang kita tahu untuk bisa mengirimkan paket keluar dibutuhkan gerbang atau gateway agar paketnya bisa diteruskan ketujuan.

Selain routing, kita perlu tambahkan nat dengan menggunakan iptables, mengapa ? agar balasan atas paket yang dikirimkan oleh ns yellow dapat diterima lagi, karena host lain tersebut tidak mengetahui berapa ip dan siapa yang mengirimkan paket ping tersebut kepada dirinya, dibutuhkan lah nat untuk mentraslasikan ip ns yellow ke ip eth0 dan sebaliknya, sehingga paket balasan dapat diterima oleh ns. Sebenarnya jika tidak menggunakan nat kita juga bisa menambahkan routing ke network ns yellow di sisi host lain tapi kita tidak gunakan cara tersebut.

Mari tambahkan routing dan konfigurasi nat dengan iptables :

# ip -n yellow route add 172.16.50.0/24 via 192.168.17.5
# ip -n yellow route
172.16.50.0/24 via 192.168.17.5 dev veth-yellow
192.168.17.0/24 dev veth-yellow proto kernel scope link src 192.168.17.1

# iptables -t nat -A POSTROUTING -s 192.168.17.0/24 -j MASQUERADE
# echo 1 > /proc/sys/net/ipv4/ip_forward

Test ping lagi dari ns yellow ke host lain :

# ip netns exec yellow ping -c 2 172.16.50.11
PING 172.16.50.11 (172.16.50.11) 56(84) bytes of data.
64 bytes from 172.16.50.11: icmp_seq=1 ttl=63 time=0.180 ms
64 bytes from 172.16.50.11: icmp_seq=2 ttl=63 time=0.194 ms

--- 172.16.50.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1006ms
rtt min/avg/max/mdev = 0.180/0.187/0.194/0.007 ms

Terlihat saat ini ns yellow sudah dapat terhubung ke host lain setelah kita tambahkan nat dan routing.

Selanjutnya bagaimana jika container atau ns yellow ingin mengakses internet ? sebelum mari kita coba test ping ke internet :

# ip netns exec yellow ping -c 2 8.8.8.8
connect: Network is unreachable

Ternyata “Network is unreachle” mengapa ? ya lagi-lagi karena kita belum tambahkan default routing (0.0.0.0/0 mewakili semua ip internet) ke ns yellow, mari kita tambahkan dan test ping kembali :

# ip -n yellow route add default via 192.168.17.5
# ip -n yellow route
default via 192.168.17.5 dev veth-yellow
172.16.50.0/24 via 192.168.17.5 dev veth-yellow
192.168.17.0/24 dev veth-yellow proto kernel scope link src 192.168.17.1

# ip netns exec yellow ping -c 2 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=5.18 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=5.21 ms

--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 5.181/5.197/5.213/0.016 ms

Terlihat saat ini ns yellow sudah dapat terhubung ke internet.

Terakhir, bagaimana jika casenya kita balik, kita ingin mengakses container/ns dari host lain supaya kita bisa mengakses misalnya service yang ada dalam container ?, untuk membuatnya seperti itu kita perlu tambahkan iptables dengan DNAT dengan mempetakan port yang diexpose oleh container, agar traffik yang berasal dari luar host bisa diteruskan ke dalam container :

# iptables -t nat -I PREROUTING -p tcp --dport 8080 -j DNAT --to 192.168.17.1:80

Summary

Dalam catatan ini Network namespace dan container memiliki arti yang sama, karena jika kita lihat docker, ia akan membuat container didalam network namespace yang ia buat lebih dahulu.

Network namespace layaknya namespace seolah memiliki serangkain konfigurasi yang independen dan terisolasi. Untuk menghubungkan antar network namespace dibutuhkan interface dengan konfigurasi ip address yang benar. Agar ns dapat terhubung ke external network diperlukan routing dan juga nat iptables dan dnat iptables agar ns dapat diakses dari external network.

Dengan memahami cara kerja namespace, akan lebih mudah memahmi docker dan software management container lainnya, karena namespace adalah basic dasar dari container yang perlu diketahui.

--

--

No responses yet