コンテナ内で Linux ブリッジを設定するにはどうすればいいですか?

コンテナ内で Linux ブリッジを設定するにはどうすればいいですか?

私はコンテナ内で作業しており、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 コマンドが機能しません。何が間違っているのでしょうか? 使用するインターフェイスはタップ インターフェイスが正しいのでしょうか? 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 パケットを送受信することはできません。( pingIP プロトコルの ICMP を使用します。)

2つ目:タップインターフェースはそうは機能しません。タップインターフェースはパケットをブリッジに「反射」しませんping。代わりに、タップインターフェースはブリッジに接続されることを期待します。プログラムたとえば、OpenVPN やその他の VPN ソフトウェアなどです。

したがって、たとえば、ホスト ネットワークにブリッジされた OpenVPN (単一のサブネットを共有) を設定しようとする場合、このアプローチは機能します。ただし、Linux ブリッジがどのように機能するかを確認したいだけの場合は、vethインターフェイスを使用する方がよいでしょう。

そして、外部LANへのL2接続だけが必要な場合は、ブリッジを間違った場所に作成していることになります。このようなことは通常、ホスト容器に入っていません。


ネットワークインターフェースには2つの端があると考えてください。ホスト端はOSに表示され、すべてのソフトウェアによって使用されます。もう一方の端は実際のネットワークに接続されます(例:物理的なイーサネットポート)。パケットが一方の端から入ってくると、他の終了。(もちろんブリッジには 2 つだけではなく複数のポートを設定できますが、同じ一般原則が適用されます。)

インターフェースをブリッジすると、ブリッジがホストそのインターフェースの側では、からネットワーク。ただし、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 ───┘

したがって、あなたの状況では、タップ インターフェイスは役に立ちません。反対側にプログラムが接続されていないため、タップ インターフェイスを介して送信しようとするすべてのパケットは破棄されます。(確認すると、ip linkおそらくNO-CARRIERフラグが表示されます。)

代わりに、たとえば、vethインターフェース(コンテナでよく使用されるものと同じ種類)を使用できます。インターフェースは常に、互いに接続されたペアで作成されます。したがって、pingパケットを 経由で送信するように指示するとveth0、パケットはループバックして のホスト側を通過しveth1、ブリッジはパケットを受信して​​、必要に応じて eth0 経由で転送できます。

      ┌── [eth0 ──› NIC] ──› network
br0 ──┤
      └── [veth1 ‹───› veth0] ‹── ping -I veth0

関連情報