LinuxカーネルはARPリクエストを受信した場合、デフォルトの状態では他の(カーネルにLinuxを使用していない)OSとは一部違った挙動をします。あるホストがARPリクエストを受信した場合に、リクエストの内容が受信したネットワークインタフェースに付けられたIPアドレス以外について解決する要求である場合には、非Linux系OSではリクエストを無視します。一方、Linuxカーネルのデフォルトの状態では、ARPリクエストが受信したホストが保持するIPアドレスについての解決要求(※1)であった場合、受信したネットワークのアドレスであるかどうかに関係なく、受信したネットワークインタフェースのリンクレイヤアドレスで応答することになります。

右記のようなネットワーク環境で、このことを確認してみましょう。host-xではLinux-2.6.21を用いたOSが動作しています。host-x上ではproxy ARPの設定は全くしていません。また、sysctl変数 net.ipv4.ip_forward は 0 であり、IPルーティングは有効としていません。

host-aでは非Linux系のOS が動作しています(便宜上ネットワークインタフェース名は eth0 とします)。この環境において、host-xのARPに対する挙動を見てみます。
ARPに対する挙動の確認には、host-a上でarping(※2)を使用します。

 

 

まず、通常のARPリクエストの例から確認します。host-aから 192.168.1.20 についての解決要求をイーサネットのブロードキャストアドレス宛に送信してみます。この場合、host-xはARPリクエストを受信する eth0 に 192.168.1.20 が付けられているので、以下のように eth0 のイーサネットアドレス 00:0c:29:yy:yy:yy で応答することになります。これついてはよくあるARPの要求・応答であり、特に問題はありません。

host-a# arping -i eth0 -t ff:ff:ff:ff:ff:ff 192.168.1.20
ARPING 192.168.1.20
60 bytes from 00:0c:29:yy:yy:yy (192.168.1.20): index=0 time=10.967 usec
60 bytes from 00:0c:29:yy:yy:yy (192.168.1.20): index=1 time=13.113 usec
60 bytes from 00:0c:29:yy:yy:yy (192.168.1.20): index=2 time=12.875 usec
....

次に、host-aから 192.168.14.128 についての解決要求をイーサネットのブロードキャストアドレス宛に送信してみます。上記のネットワーク構成では、192.168.1.0/24 上においては 192.168.14.0/24 への経路はIPルーティングで解決されることが前提であり、host-xでproxy ARPの設定をしていない以上、192.168.14.128 についての解決要求は無視しても全く問題ないはずです。
しかし、結果は

host-a# arping -i eth0 -t ff:ff:ff:ff:ff:ff 192.168.14.128
ARPING 192.168.14.128
60 bytes from 00:0c:29:yy:yy:yy (192.168.14.128): index=0 time=12.875 usec
60 bytes from 00:0c:29:yy:yy:yy (192.168.14.128): index=1 time=13.113 usec
60 bytes from 00:0c:29:yy:yy:yy (192.168.14.128): index=2 time=14.067 usec
....

のように、192.168.14.128 の解決要求に対してhost-xの eth0 のイーサネットアドレス 00:0c:29:yy:yy:yy の応答が返されます。
念の為、host-xが 192.168.14.0/24 のproxy ARPをしているわけではないことをチェックする為に、192.168.14.129 についての解決要求を送信してみると、

host-a# arping -i eth0 -t ff:ff:ff:ff:ff:ff 192.168.14.129
ARPING 192.168.14.129
^C
--- 192.168.14.129 statistics ---
68 packets transmitted, 0 packets received, 100% unanswered

のように、全く応答が得られません。host-xは 192.168.14.0/24 のproxy ARPをしているわけではないことがわかります。
なお、この「ホストに付けられた IPアドレスなら受信したネットワークインタフェースに関係なく応答する」という挙動は、

net.ipv4.conf.(ネットワークインタフェース名).arp_ignore

というsysctl変数により制御が可能です。(ネットワークインタフェース名)の部分は、ARPリクエストを受信するインタフェースとなります。
ここでの例では、eth0 です。この変数の値を 1 に設定することで、そのネットワークインタフェース以外に付けられたIPアドレスの解決要求を無視することになります。(※3

この変数の効果を確認する為に、host-xでこの変数を 1 に設定し、再度host-aから 192.168.14.128 についての解決要求を送信してみます。

host-x# /sbin/sysctl -w net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth0.arp_ignore = 1

host-a# arping -i eth0 -t ff:ff:ff:ff:ff:ff 192.168.14.128
ARPING 192.168.14.128
^C
--- 192.168.14.128 statistics ---
44 packets transmitted, 0 packets received, 100% unanswered

今度は、192.168.14.128 についての解決要求に対して応答が返されないことがわかります。なお、ここでは実際に確認はしませんが、192.168.1.20 についての解決要求は今までと変わらず応答が返されます。

以上、LinuxのARPに対する挙動を見てきました。これらからわかるように、他のOSを用いた場合には完全に隔離した状態にできているネットワークでも、デフォルトの状態のLinuxを用いた場合には完全には隔離できないケースがあることがわかります。

また、今回の例では 192.168.14.128 のネットワークインタフェースはイーサネットのネットワークインタフェースでしたが、これはイーサネット限定ではなく、擬似的なネットワークインタフェースであってもあてはまる話です。例えば、Xenの仮想マシン環境をNATで構成し、domain 0 のカーネルとしてLinuxを使う場合にもあてはまります。この場合、domain 0 のvifネットワークインタフェースにはIPアドレスが割り当てられるので、仮想マシン環境を他に影響しないように構成したい場合には注意が必要になる場合があります。ただし、よほど複雑に構成されたネットワーク環境でない限り、ここで挙げた話が実際に問題となることは少ないとは思われます。

  • ※1 ループバックアドレスとマルチキャストアドレスは除く。
  • ※2 http://www.habets.pp.se/synscan/programs.php?prog=arping
  • ※3 ゼロか非ゼロで挙動が決定されているわけではなく、2 以上の値にもそれぞれ意味が定義されている。Linuxカーネルソースの net/ipv4/arp.c にあるarp_ignore()関数が参考になる。