Help us understand the problem. What is going on with this article?

Proxy ARPについて(proxy_arp, proxy_arp_pvlanの違い)

More than 1 year has passed since last update.

Recap

Proxy ARPの説明に入る前に、念のためARPとは何か簡単にまとめてから、Proxy ARPについてまとめたいと思います。
ARPとは、RFC826で定義されている、IP AddressをEthernet Address(MACアドレス)に変換するプロトコルです。
一見、あーただのIPからMACを調べるやつね?って思いガチですが、例えばスイッチでいくつかのPORTでBroadcastを全てDropするような仕組み(現実的にあるのかは不明ですが)を導入すれば、BroadcastがDropされているPCへの通信を他所から制御(man in the middle attack)することが可能になったりと、面白い仕組みです。

ARPには大きく分けて

  • NICが所属しているL2ネットワークにおいてIPアドレスの持ち主を問うARP Request
  • 自身のNICがIPを所持していた場合に自分のMACアドレスに該当IPが割り当たっていることをARP Request発信元に知らせるARP Reply

があります。ClientがARP Requestを使ってIPアドレスからMACアドレスを調べるざっくりとした手順は下記です。

  1. [IP(A)のMACを調べたい]
    • 下記のようなARP Requestパケットを作成し、送信します
      • source mac: 自身のMAC
      • dest mac : ブロードキャスト or IP(A)のMACアドレス(ARP CacheのVerifyが目的の場合はMAC)
      • source IP : 自身のIP
      • dest IP : IP(A)
  2. [IP(A)を保持してるPC]
    • ARP送信元にunicastで、ARP Replayを返します
    • ARP Requestより、source IPと source macのペアがわかるのでARP Cacheのエントリに追加します
  3. [IP(A)を保持してないPC]
    • ARP Requestより、source IPと source macのペアがわかるのでARP Cacheのエントリに追加します

特徴として、ARP Requestをベースとして同じL2ネットワークに参加しているPCが自身のARP Cacheに追加するという挙動があるので、受動的にARP Cacheを構成することが可能です。

なので、Dummy IP宛てへのARP requestを虚偽Source IP, Source MACでブロードキャストで送ることで同じL2 Networkに参加しているPCに学習させることができます。これを踏まえるとSource IPを変更したARP requestを大量に送り続けることで途中かから参加したPCへ、実態と違うIPとMACのARP Cacheエントリを作成させることが可能です。

また、この特徴を生かして同じL2のPCのARP Cacheを無理やり更新させる(GARP)と呼ばれるARPも存在します。
こちらは、VIPで複数台で冗長化を組んでいる時に、仮想MACアドレスを設定していない場合にVIPが移動するとペアになるMACアドレスも変わるので、MACが変わったことを同じL2の全PCに知らせるためにこのGARPを飛ばすことがあります。このGARPは、特殊なタイプのARPパケットではなく、通常のARP Requestと同じようにパケットを作成し、dest IPを自身のsource IPに設定したものをGARPと呼びます。

Proxy ARP

これは、ARP Requestを受け取ったPC自身は該当IPを所持していないが、到達可能なIPアドレス宛てへのARP Requestへ自身のMACで代理応答する仕組みです。

モチベーション

多分いろんなモチベーションがあると思いますが、おそらく一番メジャーなモチベーションを説明したいと思います。例えば下記のような構成があったとして

Screen Shot 2017-12-16 at 14.13.17.png

特殊なスイッチを用いていて、Router以外の端末間で通信(L2)ができない設定をしていたとします(図を書いてから思いましたが、全ServerのVLANを分けて同一サブネットにしてもよかったですね)
なので、下記のように、同一サブネットにも関わらず、192.168.0.2から192.168.0.3への通信ができません。というのも端末間での通信が制限されいているので、192.168.0.2からARP Requestを送信しても、192.168.0.3へは届きません。

Screen Shot 2017-12-16 at 15.11.14.png

この構成で、Router(192.168.0.1)-端末(192.168.0.2)では通信ができるので、もし192.168.0.2 - 192.168.0.3への通信をRouterを介させることができたら、通信ができることになります。なのでやりたいことは、下記ような感じです

Screen Shot 2017-12-16 at 15.12.04.png

ただ、ここで問題なのがARP Recapで説明した通り、ARPは自身がIPを持っている場合のみARP Replyを返すという仕様ですので、192.168.0.2からARP Request(問192.168.0.3)が来ても、Routerは無視します。なので、通信ができません。

この問題を解決するために、あるのがProxy ARPです。Proxy ARPをOnにするとRouterは、192.168.0.2、192.168.0.3ともに 到達可能 ですので、それらのIP宛てのARP RequestにARP Reply(RouterのMAC)を返します。
そうすると、リクエスト元は、てっきりRouterがそのIPを持っていると思い込んでRouterに転送します。でそのあとRouterはもちろん該当IPを持っていないので、該当IPがあるInterfaceにそのパケットを転送し、本当にその該当IPを持っている端末へ転送され、上記の図のような通信が可能になります。

無線LANなどでは、端末間通信が制限されることが多いのでこのような仕組みが有効になります。

Linuxの実装

実は、Linux Kernelで標準でProxy ARPを実施する機能が備わっているので特にソフトウェアをインストールせずに設定を有効にするだけで、Proxy ARPを動かすことができます。まぁ、それだけだったらこの記事は書いてないんですが、実は2つオプションがあって違いがわからなかったのでここにまとめました。

  • /proc/sys/net/ipv4/conf/<dev>/proxy_arp
  • /proc/sys/net/ipv4/conf/<dev>/proxy_arp_pvlan

簡潔に話すと、Proxy ARPする対象のIPが上記2つで違います。

/proc/sys/net/ipv4/conf/<dev>/proxy_arp

とりあえず、Kernelドキュメントから引用

proxy_arp - BOOLEAN

Do proxy arp.
proxy_arp for the interface will be enabled if at least one of
conf/{all,interface}/proxy_arp is set to TRUE,
it will be disabled otherwise

なるほど、情報が少ない。ので色々試してみると。下記のようなことがわかりました。

このproxy_arpを有効にするとLinux Routerから見てもARPの宛先IPには、フォワーディング(in interfaceとout interfaceが別になる転送とここでは定義します)が必要だと判断したARP Requestに対してのみProxy ARP Replyを返します。
下記のような、構成の場合このオプションをONにしても192.168.0.2から192.168.0.0/24のサブネットに所属するIP宛てには、Proxy ARPを返しません。

Screen Shot 2017-12-16 at 16.59.47.png

たとえスイッチ側で、端末間でのL2リーチャビリティがなかったとしても、Linux Router側からはルーティングテーブルより、L2リーチャビリティがあるように見えるので(in if.vlan10, out if.vlan10なので)、ARP Proxyを返さず放置します。逆にいうと、フォワーディングが必要な全IPに対するARPに関しては返します。例えば1.1.1.1向けのARPは、デフォゲでフォワーディング可能(in if.vlan10, out if.vlan1000)なので、ARP Replyを返します

Screen Shot 2017-12-16 at 16.59.32.png

なのでこの構成で端末間で通信するために、ARP ProxyをLinux Routerに喋らせる方法は、Linux Router側のルーティングテーブルをいじり、フォワーディング可能と認識させる必要があります。色々方法はありますが例えば下記のような構成もできます(まぁ、ARP解決はしますが、フォワーディング先がデフォゲに向くので、L3リーチャビリティはありませんが)

Screen Shot 2017-12-16 at 17.07.41.png

ちなみに、ARP Reply時に自身のルーティングテーブルを見てL2リーチャビリティがない(dev <interface>)経路には、ARP Replyを返せないので上記の構成では、192.168.0.3からはProxy ARPどころかどのIP向けもARP解決できないです。
上記環境では、192.168.0.2から192.168.0.3へのARP RequestのみProxy ARPされます。

長々と説明しましたが。要はルーティングテーブル上でL2リーチャビリティがないものだけProxy ARPを返すというのが /proc/sys/net/ipv4/conf/<dev>/proxy_arp です。

ですがここでまだ疑問が残ります、最後の構成のような環境があったら、通信する方法ないじゃん!って思いますよね。最後のルーティングテーブルの変更は、ARP Proxyはしますが、ルーティングテーブルを評価した際にデフォゲに飛ぶので、IPリーチャビリティがないです。このLinux Routing Tableからは、L2リーチャビリティがあるように見えるけど実際は特殊なスイッチ、アクセスポイントによる影響でないような環境ではどのように通信すればいいのでしょうか?

ここで次の機能が生きてきます。

/proc/sys/net/ipv4/conf/<dev>/proxy_arp_pvlan

定番のとりあえず、Kernelドキュメントから引用

proxy_arp_pvlan - BOOLEAN

Private VLAN proxy arp.
Basically allow proxy arp replies back to the same interface
(from which the ARP request/solicitation was received).

This is done to support (ethernet) switch features, like RFC
3069, where the individual ports are NOT allowed to
communicate with each other, but they are allowed to talk to
the upstream router. As described in RFC 3069, it is possible
to allow these hosts to communicate through the upstream
router by proxy_arp'ing. Don't need to be used together with
proxy_arp.

This technology is known by different names:
In RFC 3069 it is called VLAN Aggregation.
Cisco and Allied Telesyn call it Private VLAN.
Hewlett-Packard call it Source-Port filtering or port-isolation.
Ericsson call it MAC-Forced Forwarding (RFC Draft).

これ、一度理解したらなんとなく何が言いたいのかわかりますが、最初僕は理解できませんでした。特に Basically allow proxy arp replies back to the same interface (from which the ARP request/solicitation was received). いや、ARP Requestが入ってきたinterfaceからARP Reply返さないとARPの意味なくない?って思って?????となりました。まぁ、これは英語の問題かもしれませんが。。。

このProxy ARPは、先ほどの /proc/sys/net/ipv4/conf/<dev>/proxy_arp と逆の挙動をします。ルーティングテーブルを見てL2リーチャビリティがあると判断したARP RequestのみProxyします。

Screen Shot 2017-12-16 at 17.27.22.png

ですので、先ほどはProxy ARPしてた下記のようなARP Requestはこのオプションでは、Proxy ARPしません

Screen Shot 2017-12-16 at 17.29.47.png

両方ともおそらくユースケースはあると思うので、機能をきちんと理解して使い分けて行きたいですね。
network namespaceのおかげで、今回楽々テストして挙動調査できましたが、namespaceがない時代大変そうですね。。。。

おまけ

試してみた方は、気づくと思うのですがデフォルトではProxy ARPすごく遅いです。というのも、デフォルトでは0.8秒の遅延を挿入しているからです。もしハードに使いたいという方は、下記のオプションを調整するといいです

  • /proc/sys/net/ipv4/neigh/<interface>/proxy_delay
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした