我正在容器內工作,試圖演示 Linux 橋接和第 2 層連接。
我啟動了一個新容器:
host$ docker run -it --rm --name c1 --privileged networking sh
在容器上,我使用以下內容建立橋接介面和點擊接口
c1$ ip link add br0 type bridge
c1$ ip link set eth0 master br0
c1$ ip tuntap add tap0 mode tap
c1$ ip link set tap0 master br0
c1$ ip link set tap0 up
c1$ ip link set br0 up
c1$ ping -I tap0 172.17.0.2
最後一個 ping 指令不起作用。我究竟做錯了什麼 ? Tap 介面是否正確使用?如何使用 linux 橋接器顯示容器上的第 2 層連接?
根據 @grawity 的回答,我嘗試了以下操作:
ip link add dev veth1 type veth peer name veth2
ip link set dev veth1 up
ip link add br0 type bridge
ip link set veth1 master br0
ip link set eth0 master br0
ip link set br0 up
ip link set veth1 up
ip link set veth2 up
ip addr add 10.0.0.3/24 dev veth1
ip addr add 10.0.0.4/24 dev veth2
ip addr add 10.0.0.2/24 dev br0
/ # brctl show
bridge name bridge id STP enabled interfaces
br0 8000.0242ac110002 no veth1
eth0
對所有介面執行 ping 操作均有效
/ # ping -c1 10.0.0.2
PING 10.0.0.2 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.068 ms
--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.068/0.068/0.068 ms
/ # ping -c1 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=0.072 ms
--- 10.0.0.3 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.072/0.072/0.072 ms
/ # ping -c1 10.0.0.4
PING 10.0.0.4 (10.0.0.4): 56 data bytes
64 bytes from 10.0.0.4: seq=0 ttl=64 time=0.095 ms
--- 10.0.0.4 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.095/0.095/0.095 ms
從 veth2 到 eth0 的 ping 和 arping 均不起作用。
ping -I veth2 -c1 172.17.0.2
ip連結輸出
10: veth2@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000\ link/ether f2:8e:e4:f7:fc:7c brd ff:ff:ff:ff:ff:ff
11: veth1@veth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP mode DEFAULT group default qlen 1000\ link/ether 1a:3a:26:02:8a:a1 brd ff:ff:ff:ff:ff:ff
12: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000\ link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
21: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP mode DEFAULT group default \ link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
和 ip 輸出
/ # ip -o a
1: lo inet 127.0.0.1/8 scope host lo\ valid_lft forever preferred_lft forever
1: lo inet6 ::1/128 scope host \ valid_lft forever preferred_lft forever
10: veth2 inet 10.0.0.4/24 scope global veth2\ valid_lft forever preferred_lft forever
10: veth2 inet6 fe80::f08e:e4ff:fef7:fc7c/64 scope link \ valid_lft forever preferred_lft forever
11: veth1 inet 10.0.0.3/24 scope global veth1\ valid_lft forever preferred_lft forever
11: veth1 inet6 fe80::183a:26ff:fe02:8aa1/64 scope link \ valid_lft forever preferred_lft forever
12: br0 inet 10.0.0.2/24 scope global br0\ valid_lft forever preferred_lft forever
12: br0 inet6 fe80::42:acff:fe11:2/64 scope link \ valid_lft forever preferred_lft forever
21: eth0 inet 172.17.0.2/16 scope global eth0\ valid_lft forever preferred_lft forever
21: eth0 inet6 fe80::42:acff:fe11:2/64 scope link \ valid_lft forever preferred_lft forever
tcpdump 有以下內容
09:29:31.253321 ARP, Request who-has 6e2b9b27d81b (Broadcast) tell 10.0.0.4, length 28
09:29:31.253509 ARP, Request who-has 172.17.0.1 tell 6e2b9b27d81b, length 28
09:29:31.253541 ARP, Reply 172.17.0.1 is-at 02:42:be:d6:a7:81 (oui Unknown), length 28
09:29:31.253541 ARP, Reply 172.17.0.1 is-at 02:42:be:d6:a7:81 (oui Unknown), length 28
09:29:36.263281 ARP, Request who-has 172.17.0.1 tell 6e2b9b27d81b, length 28
09:29:36.263313 ARP, Reply 172.17.0.1 is-at 02:42:be:d6:a7:81 (oui Unknown), length 28
09:29:36.263313 ARP, Reply 172.17.0.1 is-at 02:42:be:d6:a7:81 (oui Unknown), length 28
09:29:36.268142 ARP, Request who-has 6e2b9b27d81b (Broadcast) tell 10.0.0.4, length 28
09:29:41.284187 ARP, Request who-has 6e2b9b27d81b (Broadcast) tell 10.0.0.4, length 28
09:29:41.284196 ARP, Request who-has 6e2b9b27d81b (Broadcast) tell 10.0.0.4, length 28
我缺什麼?什麼是6e2b9b27d81b
?
答案1
第一:您的介面沒有配置IP位址,因此如果沒有位址,您就無法真正透過它傳送和接收IP封包。 (ping
使用 ICMP,一種 IP 協定。)
其次:這不是 Tap 介面的工作方式 - 它們不會將ping
資料包「反射」回網橋;相反,他們希望連接到程式,例如 OpenVPN 或其他 VPN 軟體。
因此,如果您嘗試設定橋接到主機網路(共用單一子網路)的 OpenVPN,那麼您的方法將會起作用。但如果您只是想了解 Linux 橋接器的工作原理,那麼介面方面的運氣會更好veth
。
如果您想要的只是與外部 LAN 的 L2 連接,那麼您就在錯誤的位置創建了網橋 – 這些事情通常是在主持人,不在容器中。
將網路介面視為具有兩端:「主機」端顯示在作業系統中並由所有軟體使用;「主機」端顯示在作業系統中並由所有軟體使用。另一端連接到實際網路(例如實體乙太網路連接埠)。如果資料包從一端進入,它們會通過其他結尾。 (網橋當然可以有多個端口,而不僅僅是兩個,但適用相同的一般原則。)
當您橋接介面時,橋接器將接管主持人該介面的一側,因此它只能看到來自的資料包從網路。但如果您使用ping -I eth0
或ping -I tap0
,您將繞過網橋並將所有內容傳送到實際網路。
ping ──› [eth0 ──› NIC] ──› network
ping ──› [tap0 ──› VPN software] ──› ???
┌─› [eth0 ──› NIC] ──› network
ping ──› br0 ──┤
└─› [tap0 ──› VPN software] ──› ???
∧
ping -I tap0 ───┘
因此,在您的情況下,tap 介面是無用的 - 您嘗試透過它發送的所有資料包都會被丟棄,因為另一端沒有附加程式。 (如果你檢查一下,ip link
你可能會看到它帶有NO-CARRIER
標誌。)
相反,您可以使用例如veth
介面(與容器經常使用的介面相同)——它們總是成對創建並相互連接。因此,如果您告訴ping
透過 發送封包veth0
,它們將環回並通過 的主機端veth1
,橋接器可以在其中接收它們並在必要時透過 eth0 轉發。
┌── [eth0 ──› NIC] ──› network
br0 ──┤
└── [veth1 ‹───› veth0] ‹── ping -I veth0