要求されたIPアドレスが別の(無効な)インターフェースに関連付けられている場合、LinuxはARP要求メッセージに応答しません


9

私はPC(カーネル3.2.0-23-generic)を持ってい192.168.1.2/24ますが、これはeth0インターフェイスするように構成されて192.168.1.1おり192.168.1.2tun0インターフェイスのアドレスを使用しています。

root@T42:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:41:54:01:93 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 scope global eth0
    inet6 fe80::216:41ff:fe54:193/64 scope link
       valid_lft forever preferred_lft forever
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: irda0: <NOARP> mtu 2048 qdisc noop state DOWN qlen 8
    link/irda 00:00:00:00 brd ff:ff:ff:ff
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:13:ce:8b:99:3e brd ff:ff:ff:ff:ff:ff
    inet 10.30.51.53/24 brd 10.30.51.255 scope global eth1
    inet6 fe80::213:ceff:fe8b:993e/64 scope link
       valid_lft forever preferred_lft forever
6: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc pfifo_fast state DOWN qlen 100
    link/none
    inet 192.168.1.1 peer 192.168.1.2/32 scope global tun0
root@T42:~# ip route show dev eth0
192.168.1.0/24  proto kernel  scope link  src 192.168.1.2 
root@T42:~# 

上記のように、tun0は管理上無効になっています(ip link set dev tun0 down)。これで、のARP要求を受信192.168.1.2しても、PCはそれらの要求に応答しません。

root@T42:~# tcpdump -nei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:30:34.875427 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:36.875268 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:39.138651 00:1a:e2:ae:cb:b7 > 00:1a:e2:ae:cb:b7, ethertype Loopback (0x9000), length 60:
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel
root@T42:~#

tun0インターフェイス(ip link del dev tun0)を削除した後にのみ、PCはインターフェイスのARP要求に応答192.168.1.2eth0ます。

ルーティングテーブルは、前後でまったく同じように見えますip link del dev tun0

root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# ip link del dev tun0
root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# 

以下のルーティングエントリはすでにip link set dev tun0 downコマンドで削除されています:

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.1.2     0.0.0.0         255.255.255.255 UH        0 0          0 tun0

ただし、ルーティングテーブルはip link del dev tun0コマンドの前後でまったく同じですが、カーネルが行う実際のルーティング決定は次のとおりではありません。

T42:~# ip route get 192.168.1.1
local 192.168.1.1 dev lo  src 192.168.1.1 
    cache <local> 
T42:~# ip link del dev tun0
T42:~# ip route get 192.168.1.1
192.168.1.1 dev eth0  src 192.168.1.2 
    cache  ipid 0x8390
T42:~# 

これは予想される動作ですか?カーネルがルーティングテーブルを無視するのはなぜですか?


どちらの場合も、netstat -rnの出力を貼り付けることができますか?通常、ルーティングテーブルは、この種のエラーを探す最初の場所です。
Clarus、2015年

@Claris最初の投稿を更新しました。
マーティン

2つのインターフェースで同じIPを使用すると問題が発生する可能性があるため、問題を追跡できるはずであると言われていますが、回避するのが最善です。次のステップは、arpキャッシュを確認することです。arp-aは有用なものを示していますか?
Clarus、2015年

@Claris根本的な原因のように見えるのは、tun0インターフェースが無効になっているが存在する場合、カーネルがルーティングテーブルを無視することです。ip route get更新された最初の投稿でコマンドの出力を確認してください。しかし、なぜカーネルはそのように振る舞うのですか?
マーティン

回答:


17

ルーティングテーブルは正確に無視されていません。これは、優先度の高いルーティングテーブルによって却下されています。

どうしたの

入力時に表示されるip route showルーティングテーブルは、カーネルが使用する唯一のルーティングテーブルではありません。実際、デフォルトでは3つのルーティングテーブルがあり、それらはip ruleコマンドで表示される順序で検索されます。

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

最もよく知っているテーブルはですmainが、最優先のルーティングテーブルはlocalです。このテーブルは、ローカルおよびブロードキャストルートを追跡するためにカーネルによって管理されます。つまり、このlocalテーブルは、自身のインターフェースのアドレスにルーティングする方法をカーネルに伝えます。次のようになります。

# ip route show table local
broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1
local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1
local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1
broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1
broadcast 192.168.1.0 dev eth0  proto kernel  scope link  src 192.168.1.2
local 192.168.1.1 dev tun0  proto kernel  scope host  src 192.168.1.1
local 192.168.1.2 dev eth0  proto kernel  scope host  src 192.168.1.2
broadcast 192.168.1.255 dev eth0  proto kernel  scope link  src 192.168.1.2

その行参照を確認してくださいtun0。それが、からの奇妙な結果の原因route getです。192.168.1.1はローカルアドレスです。つまり、ARP応答を192.168.1.1に送信するのは簡単です。私たちはそれを私たちに送ります。localテーブルでルートを見つけたので、ルートの検索を停止し、mainor defaultテーブルをチェックする手間を省きます。

なぜ複数のテーブルなのか?

少なくとも、ip route入力が可能route printで、表示が雑然とする「明白な」ルートがすべて表示されないのは良いことです(Windowsマシンで入力してみてください)。また、設定ミスに対する最小限の保護としても機能します。メインのルーティングテーブルが混同された場合でも、カーネルは自分自身と通信する方法を認識しています。

(なぜローカルルートを最初にしておくのですか?カーネルはローカルアドレスに対して他のものと同じように同じルックアップコードを使用できます。それは物事を内部的に単純化します。)

この複数テーブルスキームで実行できる他の興味深いことがいくつかあります。特に、独自のテーブルを追加して、検索時のルールを指定できます。これは「ポリシールーティング」と呼ばれ、送信元アドレスに基づいてパケットをルーティングしたい場合は、Linuxでこれを行う方法です。

特にトリッキーまたは実験的なことをしている場合は、コマンドでlocal指定することtable localにより、自分でルートを追加または削除できますip route。ただし、自分が何をしているのかを知らない限り、カーネルを混乱させる可能性があります。そしてもちろん、カーネルは引き続き独自のルートを追加および削除するため、ルートが上書きされないように注意する必要があります。

最後に、すべてのルーティングテーブルを一度に表示したい場合:

# ip route show table all

詳細については、ip-rule(8)manページまたはiproute2 docsを確認してください。また、できることのいくつかの例については、高度なルーティングとトラフィック制御のHOWTOを試すこともできます。


ありがとう!後のルールはまだ確かに存在したルーティングテーブル。上記のルールを実行すると、削除されました。それでも、1つの質問-私は、すべての最新のLinuxカーネル(2.6.x、3.x、4.x)がルートルックアップにRPDBを使用し、したがって複数のテーブルを使用していることを訂正していますか?ip link set dev tun0 downlocal 192.168.1.1 dev tun0 proto kernel scope host src 192.168.1.1localip link del dev tun0
Martin

2
はい、あなたは正しいです。RPDBは驚くほど古いです! 「RPDB自体は、Linuxカーネル2.2のネットワークスタックの書き換えの不可欠な部分でした。」 そして、ip(8)ipAlexey N. Kuznetsofによって作成され、Linux 2.2で追加されました。」
Jander

これは、私が見た複数のカーネルルーティングテーブルの最も良い説明の1つです。ありがとう!
djluko

1

あなたのリバースパスフィルタリング設定は、おそらく問題です。RFC3704-セクション2.4

エンタープライズLinuxディストリビューション(RHEL、CentOS、Scientific Linuxなど)では、これを解決するためのおそらく最良の方法は/etc/sysctl.confrp_filter = 2

RHELに複数のIPが構成されている場合、リモートネットワークから到達できるのは1つだけです。または、送信トラフィックのルートが受信トラフィックのルートと異なる場合、RHELはパケットを無視するのはなぜですか?


緩いRPFチェック(2)を使用する場合、またはfor rp_filter_file in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$rp_filter_file"; doneカーネルと一緒にRPFチェック(0)を無効にする場合でも、eth0パケットを192.168.1.1にルーティングするためにインターフェイスを使用しません。カーネルtun0とのインターフェースを一度削除すると、インターフェースのip link del dev tun0使用が開始されeth0ます。
Martin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.