web-dev-qa-db-ja.com

宛先インターフェースがローカル(Debian)の場合に強制的にpingを出力に

Proxmox4.4でDebianベースのLinuxコンテナを実行しています。このホストには5つのネットワークインターフェイスがあります(ただし、私が抱えている問題では2つしか機能しません)。

このホストにシェルインされている間、eth1に関連付けられているIPアドレスにpingを実行します。何が起こっているのか、そして私が信じていることは、2つの非常に異なることです。

私がしたいのは、pingパケットが出力eth3に送られ、そこでeth1にルーティングされることです。

何が起こっているのかというと、IPスタックは、私がローカルインターフェイスにpingを実行していることを認識し、スタックのすぐ上に応答を送信します。私は、2つの理由で、パケットが出たり戻ったりしないことを知っています。

  1. パケットキャプチャは、eth1またはeth3のいずれにもヒットしないことを示しています。
  2. Pingの待ち時間は平均0.013ミリ秒です。パケットが意図したとおりに出入りする場合、遅延は約60ミリ秒になります。

もちろん、eth3に関連付けられたIPアドレスにpingを実行するときに対応する動作が必要です。その場合、パケットをeth1から出力し、そこでeth3にルーティングします。残念ながら、上記と同様の動作が発生します。

以下に、目的の動作を誘発するために設定した静的ルートを示します。このようなルートは、Windowsマシンでは意図したとおりに機能しますが、私が使用しているLinuxセットアップでは機能しません。

意図したとおりに転送するようにこのホストを構成するにはどうすればよいですか?

root@my-Host:~# uname -a
Linux my-Host 4.4.35-1-pve #1 SMP Fri Dec 9 11:09:55 CET 2016 x86_64 GNU/Linux
root@my-Host:~#
root@my-Host:~# cat /etc/debian_version
8.9
root@my-Host:~#
root@my-Host:~# ifconfig
eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:192.0.2.65  Bcast:192.0.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:195028 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12891 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:92353608 (88.0 MiB)  TX bytes:11164530 (10.6 MiB)

eth1      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:128.66.100.10  Bcast:128.66.100.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:816 errors:0 dropped:0 overruns:0 frame:0
          TX packets:486 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:149517 (146.0 KiB)  TX bytes:34107 (33.3 KiB)

eth2      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:203.0.113.1  Bcast:203.0.113.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:738 errors:0 dropped:0 overruns:0 frame:0
          TX packets:880 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:423603 (413.6 KiB)  TX bytes:94555 (92.3 KiB)

eth3      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:128.66.200.10  Bcast:128.66.200.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:611 errors:0 dropped:0 overruns:0 frame:0
          TX packets:182 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:43921 (42.8 KiB)  TX bytes:13614 (13.2 KiB)

eth4      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:198.51.100.206  Bcast:198.51.100.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:183427 errors:0 dropped:0 overruns:0 frame:0
          TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:85706791 (81.7 MiB)  TX bytes:3906 (3.8 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:252 errors:0 dropped:0 overruns:0 frame:0
          TX packets:252 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:22869 (22.3 KiB)  TX bytes:22869 (22.3 KiB)
root@my-Host:~#
root@my-Host:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.0.2.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
128.66.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
203.0.113.0     0.0.0.0         255.255.255.0   U     0      0        0 eth2
128.66.200.0    0.0.0.0         255.255.255.0   U     0      0        0 eth3
198.51.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth4
root@my-Host:~#
root@my-Host:~# route -v add 128.66.200.10/32 gw 128.66.100.1
root@my-Host:~# route -v add 128.66.100.10/32 gw 128.66.200.1
root@my-Host:~#
root@my-Host:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.0.2.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
203.0.113.0     0.0.0.0         255.255.255.0   U     0      0        0 eth2
198.51.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth4
128.66.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
128.66.100.10   128.66.200.1    255.255.255.255 UGH   0      0        0 eth3
128.66.200.0    0.0.0.0         255.255.255.0   U     0      0        0 eth3
128.66.200.10   128.66.100.1    255.255.255.255 UGH   0      0        0 eth1
root@my-Host:~#
root@my-Host:~# ping -c 3 128.66.100.10
PING 128.66.100.10 (128.66.100.10) 56(84) bytes of data.
64 bytes from 128.66.100.10: icmp_seq=1 ttl=64 time=0.008 ms
64 bytes from 128.66.100.10: icmp_seq=2 ttl=64 time=0.014 ms
64 bytes from 128.66.100.10: icmp_seq=3 ttl=64 time=0.017 ms

--- 128.66.100.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.008/0.013/0.017/0.003 ms
root@my-Host:~#

2017年8月17日木曜日午前8時12分PDT更新

Dirktのリクエストに応じて、私は私たちのアーキテクチャと私の質問の理由について詳しく説明しています。

この投稿の主題である仮想ホスト(つまり、ネットワークインターフェイスeth1、eth3、および私の質問とは関係のない他の3つのネットワークインターフェイスを備えたホスト)は、セットアップした物理的な有線TCP/IPネットワークインフラストラクチャをテストするために使用されています。具体的には、このTCP/IPネットワークインフラストラクチャのルーティング機能をテストしています。

以前の投稿で説明したように、1つではなく、2つの仮想ホストがありました。これら2つのホスト間のpingは、テスト対象のTCP/IPネットワークインフラストラクチャがまだ機能していることを確認するためのスモークテストになります。

あまりにも詳細な理由で、2つのホストがあると、必要なログを収集することが困難になりました。そこで、1つのホストに切り替えて2つのNICを割り当て、静的ルートを設定して、NIC 2宛てのすべてがNIC 1に出力されるようにします。その逆も同様です。問題は、私が述べたように、それらが出力されていないことです。

この1つのホスト/ 2 NICセットアップは、Windowsで何年も機能しています。これは、Windowsが壊れていて、誤ってバグを利用していたためか、Windowsが原因かはわかりません。は問題なく(つまりRFC準拠)、同じ動作を得るにはLinuxVMで正しく構成を取得する必要があります。

上記のシェルテキストの長いブロックを要約して抽出するには:

2つのインターフェース:

eth1: 128.66.100.10/24; the router on this interface's network has IP address 128.66.100.1
eth3: 128.66.200.10/24; the router on this interface's network has IP address 128.66.200.1

関連するルート:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
128.66.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
128.66.100.10   128.66.200.1    255.255.255.255 UGH   0      0        0 eth3
128.66.200.0    0.0.0.0         255.255.255.0   U     0      0        0 eth3
128.66.200.10   128.66.100.1    255.255.255.255 UGH   0      0        0 eth1

私が実行しているコマンド:

ping -c 3 128.66.100.10

128.66.100.10の宛先は、上記の2つのルートと一致します。

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
128.66.100.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
128.66.100.10   128.66.200.1    255.255.255.255 UGH   0      0        0 eth3

プレフィックス一致が最も長いルートは次のとおりです。

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
128.66.100.10   128.66.200.1    255.255.255.255 UGH   0      0        0 eth3

私が理解しようとしているのは、このルートが存在する場合、パケットがeth3を出て、TCP/IPネットワークインフラストラクチャを通過して戻ってきて、外部からeth1にヒットしない理由です。

TCP/IPスタックは明らかに転送テーブルを参照していません。ローカルに接続されたインターフェイスにpingを実行していることを確認すると、TCP/IPスタックは「ああ、これはローカルインターフェイスです。したがって、転送テーブルを参照するつもりはありません。代わりに、スタックのすぐ後ろにエコー応答を送信します。」.

私が望む動作はRFCに準拠していますか?そうでない場合、私はその試みを断念しなければなりません。ただし、RFCに準拠している場合は、この動作を許可するようにLinux TCP/IPスタックを構成する方法を学びたいと思います。

2017年8月21日月曜日更新

Sysctl rp_filterおよびaccept_localカーネルパラメーターを発見しました。私はそれらを次のように設定しました:

root@my-Host:~# cat /proc/sys/net/ipv4/conf/eth1/accept_local
1
root@my-Host:~# cat /proc/sys/net/ipv4/conf/eth3/accept_local
1
root@my-Host:~# cat /proc/sys/net/ipv4/conf/all/accept_local
1
root@my-Host:~# cat /proc/sys/net/ipv4/conf/default/accept_local
1
root@my-Host:~# cat /proc/sys/net/ipv4/conf/eth1/rp_filter
0
root@my-Host:~# cat /proc/sys/net/ipv4/conf/eth3/rp_filter
0
root@my-Host:~# cat /proc/sys/net/ipv4/conf/all/rp_filter
0
root@my-Host:~# cat /proc/sys/net/ipv4/conf/default/rp_filter
0

このカーネルパラメータを設定し、再起動し、再起動後も存続することを確認し、再度テストしたところ、動作に違いは見られませんでした。

my-HostはProxmox4.4で実行されているlxcLinuxコンテナであることに注意してください。 my-Hostのeth1およびeth3インターフェイスに対応するハイパーバイザーインターフェイスに、上記のようにrp_filterおよびaccept_localも設定しました。

私の目的を要約すると、2つのNIC、eth1とeth3を備えたLinuxホストがあります。 eth1にpingを送信し、pingパケットをテスト対象のTCP/IPネットワークインフラストラクチャにルーティングして、eth3に戻そうとしています。

私が上で試したことは何も私にそうすることを許しませんでした。どうすればよいですか?

2017年8月27日更新

Dirktによるメモによると、eth1とeth3が純粋に仮想であるのか、それとも物理インターフェイスに対応するのかについては言及していませんでした... eth1とeth3は両方とも同じハイパーバイザーの物理インターフェイス。意図は、eth1を出力するパケットが実際にハイパーバイザーボックスを物理的に離れ、実際のTCP/IPネットワークに出て、ルーティングされて戻ることです。

2017年8月27日更新#2

Dirktごとに、非常に有望と思われるネットワーク名前空間を調査しました。ただし、「正しく機能する」わけではありません。

LXCコンテナーを使用していますが、コンテナーに存在する分離メカニズムの一部が、ネットワーク名前空間の作成を妨げているようです。コンテナで実行していなければ、ネットワーク名前空間を追加しても問題はないと思います。

LXCコンテナーでこれを機能させるための参照をいくつか見つけていますが、それらは非常にあいまいで難解です。まだそこにありません、そして今日のためにタオルを投げなければなりません...誰かがこの点に関して何か提案があれば、アドバイスしてください...

2
Dave

(コメントのため、他の回答は残しておきます)。

タスクの説明:2つのネットワークインターフェースeth1eth3を備えたLXCコンテナー内の単一の仮想ホストが異なるLANセグメント上にあり、ルーターを介して外部接続されている場合、「ブーメラン」を実装するにはどうすればよいですか。 eth3を離れ、eth1に戻るping(またはその逆)?

ここでの問題は、Linuxカーネルが宛先アドレスがeth1に割り当てられていることを検出し、ルーティングテーブルでパケットのルーティングが規定されている場合でも、パケットをeth1に直接配信しようとすることです。 eth3経由。

Pingに応答する必要があるため、eth1からIPアドレスを削除することはできません。したがって、唯一の解決策は、どういうわけか2つの異なるアドレスを使用することです(またはeth1eth3を互いに分離すること)。

これを行う1つの方法は、コメントでharrymcによってリンクされている この回答 のようにiptablesを使用することです。

1つのネットワーク名前空間を使用して外部ネットワークをシミュレートし、2つのネットワーク名前空間を使用して宛先IPアドレスを分離する、次の設定でマシンでテストした別の方法:

Routing NS     Main NS      Two NS's

+----------+                   +----------+
|   veth0b |--- veth0a ....... | ipvl0    |
| 10.0.0.1 |    10.0.0.254     | 10.0.0.2 |
|          |                   +----------+
|          |                   +----------+
|   veth1b |--- veth1a ....... | ipvl1    |
| 10.0.1.1 |    10.0.1.254     | 10.0.1.2 |
+----------+                   +----------+

Routing NSで転送が有効になっています。追加の10.0.*.2アドレスは[〜#〜] ipvlan [〜#〜]デバイスに割り当てられます。これは、に割り当てられた追加のIPアドレスと考えることができます。接続されているマスターインターフェイス。 IPVLANに関する詳細(例: ここ 。のように作成

ip link add ipvl0 link veth0a type ipvlan mode l2
ip link set ipvl0 netns nsx

ここで、nsxは新しいネットワーク名前空間であり、その名前空間では、

ip netns exec nsx ip addr add 10.0.0.2/24 dev ipvl0
ip netns exec nsx ip link set ipvl0 up
ip netns exec nsx ip route add default via 10.0.0.1 dev ipvl0

Main NSには、デフォルトのルールに加えて、次のルーティングルールがあります

ip route add 10.0.0.2/32 via 10.0.1.1 dev veth1a
ip route add 10.0.1.2/32 via 10.0.0.1 dev veth0a

次に、ping 10.0.0.2veth0aの両方でtcpdumpが確認できるように、veth1aは「ブーメラン」往復を実行します。したがって、この設定では、pingなどに関する限り、すべてのロギングをMain NSから実行できますが、ncなどを使用したより高度なテストでは、少なくともレシーバーを提供するために他の名前空間が必要になる場合があります。等.

LXCコンテナーは、ネットワーク名前空間(およびその他の名前空間)を使用します。私はLXCコンテナーにあまり詳しくありませんが、コンテナー内での新しいネットワーク名前空間の作成がブロックされている場合は、コンテナーの外部から作業してください。まず、コンテナの名前を次のように識別します

ip netns list

次に、上記のようにip netns exec NAME_OF_LXC_NS ...を実行します。 eth1eth3のLXCコンテナーへの移動を遅らせ、最初に2つのIPVLANを作成してから、次にコンテナーに移動することもできます。必要に応じてスクリプトを作成します。

編集

ネットワーク名前空間なしで機能する3番目のバリアントがあります。秘訣は、ポリシールーティングを使用し、ローカルルックアップに通常よりも高い(「悪い」)優先度を与え、特定のインターフェイスにバインドされたソケットからのパケットを異なる方法で処理することです。これにより、問題の主な原因であるローカルアドレスへの配信が妨げられます。

上記と同じシミュレーション設定からIPVLANを除いたもので、

ip rule add pref 1000 lookup local
ip rule del pref 0
ip rule add pref 100 oif veth0a lookup 100
ip rule add pref 100 oif veth1a lookup 101
ip route add default dev veth0a via 10.0.0.1 table 100
ip route add default dev veth1a via 10.0.1.1 table 101

コマンド

ping 10.0.1.254 -I veth0a
ping 10.0.0.254 -I veth1a

ping要求を正しく出力します。また、ping応答を取得するには、ソーススプーフィングに対するテストを無効にする必要があります。

echo "0" > /proc/sys/net/ipv4/conf/veth{0,1}a/rp_filter
echo "1" > /proc/sys/net/ipv4/conf/veth{0,1}a/accept_local

ncまたはsocatも試しましたが、特定のデバイスでリスナーに応答を強制するncのオプションがないため、それらを機能させることができませんでした。 socatにはそのようなオプションがありますが、効果がないようです。

したがって、この設定では、ping以外のネットワークテストは多少制限されます。

1
dirkt

したがって、要約すると、次の構成があります。

Host 1           Main Host            Host 2
  ethX -------- eth1   eth3 --------- ethY
       128.66.200.10   128.66.100.10

メインホストで/proc/sys/net/ipv4/ip_forwardが有効になっていて、ホスト1とホスト2の間の接続が機能することをテストする必要があります。

LinuxがインターフェースごとにIPパケットを処理する方法を簡単に思い出してください。

Linux packet processing

したがって、物理層からの入力パケットは、入力インターフェイスのPREROUTINGを通過し、宛先によってルーティングされてから、出力インターフェイスのPOSTROUTINGを通過し、物理層に出力されます。逆に、pingのようなアプリケーションはパケットをOUTPUTチェーンに送信し、次にルーティングされ(図には示されていません)、次にPOSTROUTINGチェーンをトラバースし、最後に出力します。

ここでは、「物理層に入る」という意味でingressを使用し、「物理層を離れる」という意味でegressを使用しています。層"。

あなたがやろうとしていることは、どういうわけかLinuxカーネルにこの方法でパケットを処理しないように指示することですが、代わりにアプリケーションpingを使用してeth3でパケットingressingをシミュレートします。その後、eth1にルーティングされ、egressesになります。

しかし、それだけです機能しません:アプリケーションはOUTPUTチェーンを介してパケットを送信します。 eth3オプションを使用してping-Iにバインドするように強制すると、Linuxはこれがパケットの間違ったインターフェイスであると判断し、パケットをドロップします。パケットをeth3入力したかのように処理しようとはしません。

したがって、通常の方法これを処理するには、ホスト1からpingを送信し、ホスト2(および他の方向)に到着するかどうかを確認します。素晴らしく、シンプルで簡単で、ゆがみは必要ありません。

「メインホスト」は仮想であるため、eth1eth3は実際のインターフェイスではない可能性が非常に高いです(あなたは言わなかった)。それらがvethペアの一方の端にすぎない場合は、もう一方の端を簡単に取得し、その端でpingを生成するだけです(どこにある場合でも)。

何らかの理由で「メインホスト」ですべてをテストすることを主張する場合は、いくつかのゆがみを経て、eth3を他のインターフェイスveth-pairにブリッジすることもできます。次に、thatveth-pairのもう一方の端にあるping。パケットはvethからブリッジされるため、ingressingとしてeth3に処理されるため、必要な処理が実行されます。しかし、それは本当に不必要に複雑です。

ingressingパケットをシミュレートする他の方法はわかりません。

iptableの魔法を試すこともできますが、ネットワーク接続をテストしようとしている場合、それは悪い考えです。iptablesルールが実際のトラフィックでも機能することは決してわかりません。それはあなたがテストするものではないからです。

0
dirkt