2つのブリッジされたvethが互いにpingを送信できないのはなぜですか?

2つのブリッジされたvethが互いにpingを送信できないのはなぜですか?

2 つの veth インターフェイスが 1 つのブリッジに接続され、互いに通信できるネットワーク環境を設定する必要があります。

だからきれいなUbuntuシェルで次のコマンドを実行します。

# Create Two veth and attach them to the bridge
sudo ip link add veth0 type veth peer name veth0p
sudo ip link add veth1 type veth peer name veth1p
sudo brctl addbr br0
sudo brctl addif br0 veth0p
sudo brctl addif br0 veth1p

# Set links up
sudo ip link set veth0 up
sudo ip link set veth1 up
sudo ip link set veth0p up
sudo ip link set veth1p up
sudo ip link set br0 up

# Give each veth an IP address
sudo ip addr add 10.0.0.1/24 dev veth0
sudo ip addr add 10.0.0.2/24 dev veth1

# Try to ping one from the other
ping 10.0.0.1 -I veth1

pingは機能しません。誰でもこの問題を解決するのに役立ちますか?互いにpingveth0するにはどうすればよいですか?veth2

出力はip r s次のとおりです

default via 192.168.0.1 dev ens160 proto dhcp src 192.168.0.119 metric 100 
10.0.0.0/24 dev veth0 proto kernel scope link src 10.0.0.1 
10.0.0.0/24 dev veth1 proto kernel scope link src 10.0.0.2 
192.168.0.0/24 dev ens160 proto kernel scope link src 192.168.0.119 
192.168.0.1 dev ens160 proto dhcp scope link src 192.168.0.119 metric 100 

これの目的は、veth後でこれら2つのインターフェイスをVXLANオーバーレイネットワークに配置することです。しかし、開発目的で今回はVXLANを設定せずにブリッジと2つのインターフェイスをテストしたいと思いました。 (ただし、VXLANを設定しなくても同じブリッジにある限り、互いにpingできる必要があります。そうですか?)

ありがとうございます!

答え1

ルーティングは、それぞれ独自のネットワークスタックを持つ複数のシステム間、つまり複数のネットワークスタック間で行う必要があります。

これをテストすることに興味はありません一つネットワークスタック。このように動作するには多くの調整が必要であり、最終結果は意図したターゲットと同様の構成を反映せず、そのようなプロジェクトを開発するのには役に立ちません。

Linuxでこれを行う最も簡単で正しい方法は、ネットワークネームスペース(またはコンテナ)を使用することです。

OPの設定を使用して、インターフェースは2つの名前空間(次のものを使用して作成)に移動されました。ip netns add)。インターフェイスで設定の損失が発生するため、欠落しているコンテンツをもう一度追加してください。だからユーザー、OP設定後(とにかく失われたアドレス割り当てを除く):

ip netns add system1
ip netns add system2

ip link set dev veth0 netns system1
ip link set dev veth1 netns system2

ip -n system1 link set lo up # this is optional for this problem
ip -n system2 link set lo up # this is optional for this problem
ip -n system1 address add 10.0.0.1/24 dev veth0
ip -n system2 address add 10.0.0.2/24 dev veth1
ip -n system1 link set dev veth0 up
ip -n system2 link set dev veth1 up

今、すべてが簡単です。システム1そしてシステム2実際の最終設定に使用するシステムをシミュレートします。次のコマンドは、スイッチを介して実際のシステムで期待どおりに成功し、通常のルーティング動作に従います。

ip netns exec system1 ping 10.0.0.2

注:最初に次のインターフェイスを作成して、接続なしで特定の設定全体(2つのピアのみを含む)を短縮できますip link add name veth0 type veth peer name veth1。ブリッジは問題の一部ではありませんが、3番目のピアシステムをシミュレートする必要がある場合は、必ずブリッジが必要です。


好奇心に対する報酬:質問に厳密に答えてください

目的:ホストが(インターフェースを介さずに)有線を介してそれlo自体をpingするようにします。もう一度警告します。これが機能しても、結果は複数のシステムシミュレーションを含む有用な用途には使用できません。

したがって、これはネットワークネームスペースなしでOPの初期設定で行われました。

一つネットワークスタックにはいくつかの調整が必要です。以下には、正しく機能しないようにする詳細がたくさんあります。

  • システムは次のようにする必要があります。Accept は、送信元 IP アドレスが自身に属するデータパケットを受信します。捨てる代わりに

    sysctl -w net.ipv4.conf.veth0.accept_local=1
    sysctl -w net.ipv4.conf.veth1.accept_local=1
    
  • 同じパケットが送信されたときに1回、受信されたときに1回、2回表示されます。これには異なる(ポリシーベース)ルーティングが必要です。

    システムは、パケットが生成されてローカルに送信される場合veth0と、その後にパケットが外部で受信される場合とを区別する必要があります。veth1パスラインで。 2つの異なるルーティングテーブルを選択するには、2つの異なるポリシールーティングルールが必要です。方向を逆にすると、合計4つのルールと4つのテーブルが形成されます。実際に地元のルーティングテーブルにはすでに半分(受信パケット用:ホスト用)が含まれているため、ローカルに送信されるパケットにのみ特別なルーティングルールとテーブルが必要です。

    ポリシールール:

    ip rule add priority 11 iif lo from 10.0.0.1 lookup 1001
    ip rule add priority 21 iif lo from 10.0.0.2 lookup 2001
    

    特殊は、iif loトラフィックがローカルで発生したことを意味します(実際にはインターフェイスで受信されませんlo)。

    リンクされたルーティングテーブルにはそれぞれ独自の単一パスがあります。

    ip route add 10.0.0.2 dev veth0 table 1001
    ip route add 10.0.0.1 dev veth1 table 2001
    
  • これ地元のルーティングテーブルが邪魔になる

    これまでのところ、

    # ip rule
    0:      from all lookup local
    11:     from 10.0.0.1 iif lo lookup 1001
    21:     from 10.0.0.2 iif lo lookup 2001
    32766:  from all lookup main
    32767:  from all lookup default
    
    # ip route show table local to root 10.0.0.0/24
    local 10.0.0.1 dev veth0 proto kernel scope host src 10.0.0.1 
    local 10.0.0.2 dev veth1 proto kernel scope host src 10.0.0.2 
    broadcast 10.0.0.255 dev veth0 proto kernel scope link src 10.0.0.1 
    broadcast 10.0.0.255 dev veth1 proto kernel scope link src 10.0.0.2 
    

    これ地元のテーブルは最も低い優先順位値ルールを持ち、最初に使用されます。最初の2つのエントリが最初に一致し、追加のルール(優先順位11と21)とルーティングをオーバーライドしてパケットをローカルに保ちます(たとえば、インターフェイスを使用lo)。

    これらのエントリは削除できますが、上記のように実際には必要ですが、ポリシールールを追加した後にのみ必要です。さらに、インターフェイスのアドレスを変更すると、すぐにカーネルがそのアドレスを再追加します。

    したがって、from all lookup localルールをより高い優先順位値に移動し、優先順位が 11 と 21 の追加ルールを最初に通過して、特別なパスを最初に取得できます。

    ip rule add priority 50 lookup local 
    ip rule del priority 0
    

単一のpingとそれに対する応答が続く経路を確認することができます。

初期パケットは

  • veth0以下を使用するときに強制パスping -I veth0 10.0.0.2

    # ip route get oif veth0 to 10.0.0.2
    10.0.0.2 dev veth0 src 10.0.0.1 uid 0 
        cache 
    
  • または、次の場合は、送信元IPアドレスを10.0.0.1にバインドしますping -I 10.0.0.1 10.0.0.2

    # ip route get from 10.0.0.1 to 10.0.0.2
    10.0.0.2 from 10.0.0.1 dev veth0 table 1001 uid 0 
        cache 
    

どちらの場合も、ルーティングは同じです(他のルーティングテーブルが使用されます)。

パケットはブリッジをスキップし(後でARPに関する警告を参照)、もう一方の端で受信されますveth1

# ip route get from 10.0.0.1 iif veth1 to 10.0.0.2
local 10.0.0.2 from 10.0.0.1 dev lo table local 
    cache <local> iif veth1 

応答は送信元アドレス 10.0.0.2 を使用して宛先 10.0.0.1 に返送されます。

# ip route get from 10.0.0.2 to 10.0.0.1
10.0.0.1 from 10.0.0.2 dev veth1 table 2001 uid 0 
    cache 

次の住所から返信を受けました(橋を渡って)veth0

# ip route get from 10.0.0.2 iif veth0 to 10.0.0.1
local 10.0.0.1 from 10.0.0.2 dev lo table local 
    cache <local> iif veth0 

フラットホイールが正常に完了すると予想されます。

ARPリクエストの発行と解決:

# ip neigh
10.0.0.1 dev veth1 lladdr f2:2a:75:82:17:d3 DELAY
10.0.0.2 dev veth0 lladdr 42:91:a1:a6:64:45 REACHABLE
10.0.0.1 dev br0 lladdr f2:2a:75:82:17:d3 STALE

br0ブリッジ自体のインターフェイスにはアドレスが設定されていませんが、LinuxのWeak実装のため、同じネットワークスタックにのみ存在し、ARPとルーティングに参加することがわかります。ホストモデル。上記は(から継承されている)42:91:a1:a6:64:45から来ています。したがって、最初の数個のpingは、最初に->(+ ->)の代わりに->(+は->に応答)にルーティングでき、暫定的に学習されたARPエントリが期限切れになると、数秒後に正しいフローに戻ります。br0veth1pveth0br0veth1veth0veth0veth1veth1veth0

br0ルーティングへの参加は、次のようなさまざまな方法でブロックできます。

  • そしてarp_ignore:

    sysctl -w net.ipv4.conf.br0.arp_ignore=1
    
  • または有効にするrp_filter(のため厳格なリバースパスの転送)ARPに応答しないように、次の操作を行います。

    sysctl -w net.ipv4.conf.br0.rp_filter=1
    
  • または、LinuxシステムがブリッジVLANフィルタリングをサポートしている場合は、ブリッジポートからブリッジ独自のインターフェイスを分離します。

    ip link set dev br0 type bridge vlan_filtering 1
    bridge vlan del vid 1 dev br0 self
    

    これにより、デフォルト設定では、ブリッジ自体のインターフェイスからのトラフィックを独自のブリッジポートに分けることができ、ローカルネットワークスタックからの「漏れ」をブロックします。 (この場合、tcpdump -i br0 -p無差別モードに設定されていないオプションでキャプチャしても-pトラフィックは受信されません。)

繰り返しますが、ブリッジが別の場所にある可能性があるため(たとえば、物理スイッチ、他のVM、または他のネットワーク名前空間/コンテナなど)、実際のシナリオではこの欠陥は発生しません。

関連情報