複数のネットワークインターフェイスがあり、それぞれが1つ以上のIPアドレスを持つコンピュータがあります。これらのIPアドレスは同じサブネット上にあってもそうでない場合もあります。たとえば、結果は次のようip a
になります。
1: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 11:11:11:11:11:11 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.2/24 brd 10.0.1.255 scope global eno1
valid_lft forever preferred_lft forever
inet 10.12.1.3/24 brd 10.12.1.255 scope global secondary eno1:0
valid_lft forever preferred_lft forever
2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 22:22:22:22:22:22 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.4/24 brd 10.0.1.255 scope global eno2
valid_lft forever preferred_lft forever
inet 192.168.1.3/24 brd 192.168.1.255 scope global secondary eno2:0
valid_lft forever preferred_lft forever
2: eno3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 33:33:33:33:33:33 brd ff:ff:ff:ff:ff:ff
inet 172.23.1.2/24 brd 172.23.1.255 scope global eno3
valid_lft forever preferred_lft forever
私が望むのは、インターフェイスに入ってくるトラフィックへの応答が同じインターフェイスを通過し、ターゲットに関係なく特定のインターフェイスを介してトラフィックを送信するようにアプリケーションに指示できることです。
たとえば、ネットワーク上の他のシステムping 10.0.1.2
から来た場合、応答はeno2を介してルーティングされるため、あらゆる種類の問題が発生します。192.168.1.0/24
どうすればいいですか?ルーティングテーブルを複数設定できますか?インターフェイス名または別の名前で受信パケットにタグを付けることはできますか?
答え1
注:設定に必要な事項知的財産権ネットワーク 10.0.1.0/24 と 192.168.1.0/24 は同じネットワーク上にあります。イーサネットネットワーク。そうでない場合は、以下を提供する必要があります。詳細ネットワークトポロジでは、ホストを1つだけ提供するだけでは不十分です。ここで問題は既に再現され修正される可能性がありますが、それに合わせてこの回答を編集します。これが、最終モデル設定で2つのブリッジを接続した理由です。1番そしてイノ2同じLAN内で。また、IP 10.0.1.1/24/192.168.1.1/24としてルータを追加しました。
2つの設定について何度も言及します。rp_filter
そしてarp_filter
、混同しないでください。
同じ解決策の2つの異なる問題:
- ARPフラックス(注:リンクのソリューションに提供されている2つのパラメータはの使用に置き換えられています。
arp_filter
)これは、LinuxがデフォルトでARPのルーティングルールに実際に従わないために存在します。両方のインターフェイスのアドレスが同じ IP LAN にある場合、問題が発生する可能性があります。この問題は解決する必要があります。そうしないと、数分間続く奇妙な問題が発生する可能性があります。したがって、arp_filter
パスを一致させるには有効にする必要があります。次の問題を解決するポリシー ルーティングもこの問題を解決するので、ここでは余分な作業なしで動作します。 - これは、ルーティングの問題、基本的に次の方法で192.168.0/24へのパスを直接表示できるためです。イノ2だから、1番答えは決して考慮されません。一度設定されると、
rp_filter
eno1を介して着信トラフィックが破棄されたり、応答がなくなったりする可能性があります。設定されていないか緩い場合は、10.0.1.2に問い合わせてください。1番無効なインターフェイスを介して応答を取得する:イノ2。
結論として:
ARPの修正出る動作により例外が修正されます。着信IPの問題。 10.0.1.2に入る要求はどこから来るのですか?イノ2。これは下げてみるとわかる1番以下のモデル設定では、1〜2分後(ルーターのARPキャッシュの有効期限が切れている)10.0.1.2のping要求を受け取り、すべての回答を使用できます。イノ2。今戻ってきて1番up は着信 IP を復元しません。これは、ルータのARPキャッシュにまだ10.0.1.2があるためです。イノ2MACアドレスは、代わりにそのアドレスに対して最初にユニキャストクエリを実行することによって更新されます。1番MACアドレス。一時的に減少イノ2ルーターからARPをフラッシュします(またはDAD /ギャップ利用申請
arping
ホストから)前の状況に戻ります(応答がない場合rp_filter=1
)。私の強調、Linux/ドキュメント/ネットワーク/ip-sysctl.txtの
arp_filter
:arp_filter - BOOLEAN
1 - 同じサブネットに複数のネットワークインターフェイスがあり、
各インターフェイスに対してARPに応答できます。
カーネルが
ARPに基づいてIPからパケットをルーティングするかどうかこのインターフェースの外側(
したがって、機能するにはソースベースのルーティングを使用する必要があります。)。つまり、
arp要求に応答するカード(通常1枚)を制御できます。0 - (既定値)
カーネルは他のインターフェイスのアドレスを使用してarp要求に応答できます。。これは間違っているように見えるかもしれませんが、
成功したコミュニケーションの可能性を高めるので、しばしば意味があります。
Linux の IP アドレスはホスト全体が所有します。
、特定のインターフェイスを介さずに。
この動作は、ロードバランシングなどのより複雑な設定でのみ問題を引き起こします。conf/{all,interface}/arp_filter の 1 つ以上が
TRUE に設定されている場合は、インターフェイスの arp_filter が有効になり、
それ以外の場合は無効になります。修理する出るIPルーティングの問題を解決するには、IPごとに1つの追加ルーティングテーブルが必要です。問題の各IPには、含まれていない特定のルートテーブルを使用するようにそのIPを選択する特定の規則が必要です。したがって、他のローカルIPの関連パスを無視し、代わりに指定されたインターフェイスを強制します。
これらの設定を展開する予定の場合は、いくつかの自動化を実行する必要があります。この種の問題を解決するには、通常はIPごとに1つのルーティングテーブルが必要で、最新のカーネルには2 ^ 32のルーティングテーブルがある可能性があるため、IPv4全体をルーティングテーブルにマッピングすることもできます(いくつかの特殊テーブルの数を考慮する)。十分低い)IP 0.xxx / 8が予約されているため、マッピングと上書きを防ぎます。この問題を軽減するために、いくつかのシェル機能を追加しました。これらのルーティングテーブル番号には名前は必要ありませんが、オプションで/etc/iproute2/rt_tables
同じ方法で名前を付けることができ、同じ目的でIPアドレスの名前を/etc/hosts
。ここでは必要ありません。
さて、説明になれば幸いです。これを修正する方法は次のとおりです。
ホストシステムで次のスクリプトを実行します。
fix.sh
:
#!/bin/sh
map_localip_to_interface () {
ip -brief address show to "$1" | awk '{ print $1 }'| sed 's/@.*$//'
}
map_ip_to_table () {
printf '%s\n' "$1" | awk -F. '{ print (((($1*256)+$2)*256)+$3)*256+$4 }'
}
#not used here
map_table_to_ip () {
local ip
local n="$1"
for i in 1 2 3 4; do
ip="$(($n%256)).$ip"
n=$(($n/256))
done
printf '%s\n' "$ip" | sed 's/\.$//'
}
ip rule add from 10.0.1.2 table $(map_ip_to_table 10.0.1.2)
ip rule add from 10.0.1.4 table $(map_ip_to_table 10.0.1.4)
ip rule add from 192.168.1.3 table $(map_ip_to_table 192.168.1.3)
ip route add table $(map_ip_to_table 10.0.1.2) 10.0.1.0/24 dev $(map_localip_to_interface 10.0.1.2)
ip route add table $(map_ip_to_table 10.0.1.2) default via 10.0.1.1 dev $(map_localip_to_interface 10.0.1.2)
ip route add table $(map_ip_to_table 10.0.1.4) 10.0.1.0/24 dev $(map_localip_to_interface 10.0.1.4)
ip route add table $(map_ip_to_table 10.0.1.4) default via 10.0.1.1 dev $(map_localip_to_interface 10.0.1.4)
ip route add table $(map_ip_to_table 192.168.1.3) 192.168.1.0/24 dev $(map_localip_to_interface 192.168.1.3)
ip route add table $(map_ip_to_table 192.168.1.3) default via 192.168.1.1 dev $(map_localip_to_interface 192.168.1.3)
sysctl -q -w net.ipv4.conf.eno1.arp_filter=1
sysctl -q -w net.ipv4.conf.eno2.arp_filter=1
結果は次のとおりです。
# ip rule
0: from all lookup local
32763: from 192.168.1.3 lookup 3232235779
32764: from 10.0.1.4 lookup 167772420
32765: from 10.0.1.2 lookup 167772418
32766: from all lookup main
32767: from all lookup default
# ip route show table all |grep 'table [1-9]'
default via 10.0.1.1 dev eno1 table 167772418
10.0.1.0/24 dev eno1 table 167772418 scope link
default via 192.168.1.1 dev eno2 table 3232235779
192.168.1.0/24 dev eno2 table 3232235779 scope link
default via 10.0.1.1 dev eno2 table 167772420
10.0.1.0/24 dev eno2 table 167772420 scope link
# sysctl net.ipv4.conf.eno{1,2}.arp_filter
net.ipv4.conf.eno1.arp_filter = 1
net.ipv4.conf.eno2.arp_filter = 1
これは、問題のすべてのIPに対してこれを使用すると、ルーティングスタックがプライベートルーティングテーブルに切り替えられ、正しいネットワークインターフェイスが使用されることを意味します。 ARPは同じ原則に従います。
同じ設定を使用すると、ローカルで開始された発信IPが正しく機能する可能性があります。 192.168.1.100がWebサーバーの場合:
ping -I 10.0.1.2 192.168.1.100 # through eno1 and via router
ping -I 10.0.1.4 192.168.1.100 # through eno2 and via router
ping -I 192.168.1.3 192.168.1.100 # through eno2 directly
同様に、192.168.1.100 で socat(1.7.3.2) を使用する場合は、次のコマンドを実行します。
socat tcp4-listen:5555,reuseaddr,fork exec:'printenv SOCAT_PEERADDR'
その後、マルチホームホストですべてがうまくいったという応答を受け取ることができます。
# socat tcp4:192.168.1.100:5555 -
192.168.1.3
# socat tcp4:192.168.1.100:5555,bind=10.0.1.2 -
10.0.1.2
# socat tcp4:192.168.1.100:5555,bind=10.0.1.4 -
10.0.1.4
tcpdump
トラフィックが予想されるインターフェイスを通過していることを確認できます。
他のIPにさらに多くのルーティング問題がある場合は、何をすべきかを知る必要があります。
メモ:
- ここで10.12.1.3を置いたが、すでにオンになっているから1番これでこれがうまくいくので、
arp_filter=1
うまく機能するためには、独自のルーティングテーブルとルールも必要です。 - ホストもルーティングする場合は、ルールとルーティングテーブルを改善する必要があります。テストする必要があります。
モデル設定:
次のスクリプトをrootとして実行してくださいsetup.sh
。これで、問題は次のように再現できます。
1学期:
ip netns exec mhost tcpdump -l -e -n -s0 -p -i eno1
2学期:
ip netns exec mhost tcpdump -l -e -n -s0 -p -i eno2
アイテム3:
ip netns exec h1921681100 ping -n 10.0.1.2
応答がありません。少なくともこれを行う:
ip netns exec mhost sysctl -w net.ipv4.conf.eno1.rp_filter=2
非対称ルーティングが許可されます。1番そして去るイノ2(またはすべて通過イノ2「ARPフラックス」効果が有効な場合)。
上記のスクリプトを実行すると、fix.sh
すべての問題が解決されます。
ip netns exec mhost sh fix.sh
setup.sh
:
#!/bin/sh
if ip netns id | grep -qv '^ *$' ; then
printf 'ERROR: leave netns "%s" first\n' $(ip netns id) >&2
exit 1
fi
hosts='mhost router h1921681100'
nets='net1001 net1921681 net10121 net172231'
for ns in $hosts $nets; do
ip netns del $ns 2>/dev/null || :
ip netns add $ns
ip netns exec $ns sysctl -q -w net.ipv6.conf.default.disable_ipv6=1
ip netns exec $ns sysctl -q -w net.ipv4.conf.default.rp_filter=1
ip netns exec $ns sysctl -q -w net.ipv4.conf.all.rp_filter=1
done
for ns in $hosts; do
ip -n $ns link set lo up
done
bmac=1
for ns in $nets; do
ip -n $ns link add bridge0 address 02:00:00:00:00:$(printf '%02d' $bmac) type bridge
ip -n $ns link set bridge0 up
bmac=$(($bmac+1))
done
link_lan () {
[ "$1" = "$2" ] && return 1
ip -n $2 link add p-$1 type veth peer netns $1 name p-$2 2>/dev/null || return 1
ip -n $2 link set p-$1 master bridge0 up
ip -n $1 link set p-$2 master bridge0 up
}
link_lan net1001 net1921681
ip -n h1921681100 link add eth0 type veth peer netns net1921681 name p-h1921681100
ip -n h1921681100 link set eth0 up
ip -n net1921681 link set p-h1921681100 master bridge0 up
ip -n h1921681100 address add 192.168.1.100/24 broadcast 192.168.1.255 dev eth0
ip -n h1921681100 route add default via 192.168.1.1
ip netns exec router sysctl -q -w net.ipv4.conf.default.forwarding=1
ip -n router link add eth10011 type veth peer netns net1001 name p-router10011
ip -n router link set eth10011 up
ip -n net1001 link set p-router10011 master bridge0 up
ip -n router address add 10.0.1.1/24 broadcast 10.0.1.255 dev eth10011
ip -n router link add eth1921681 type veth peer netns net1921681 name p-router1921681
ip -n router link set eth1921681 up
ip -n net1921681 link set p-router1921681 master bridge0 up
ip -n router address add 192.168.1.1/24 broadcast 192.168.1.255 dev eth1921681
ip netns exec mhost sysctl -q -w net.ipv4.conf.default.forwarding=0
ip -n mhost link add eno1 type veth peer netns net1001 name p-mhosteno1
ip -n mhost link set eno1 up
ip -n net1001 link set p-mhosteno1 master bridge0 up
ip -n mhost address add 10.0.1.2/24 broadcast 10.0.1.255 dev eno1
ip -n mhost address add 10.12.1.3/24 broadcast 10.12.1.255 dev eno1
ip -n mhost link add eno2 type veth peer netns net1921681 name p-mhosteno2
ip -n mhost link set eno2 up
ip -n net1921681 link set p-mhosteno2 master bridge0 up
ip -n mhost address add 10.0.1.4/24 broadcast 10.0.1.255 dev eno2
ip -n mhost address add 192.168.1.3/24 broadcast 192.168.1.255 dev eno2
ip -n mhost link add eno3 type veth peer netns net172231 name p-mhosteno3
ip -n mhost link set eno3 up
ip -n net172231 link set p-mhosteno3 master bridge0 up
ip -n mhost address add 172.23.1.2/24 broadcast 172.23.1.255 dev eno3