Gratuitous ARPという「沈黙の叫び」:IP重複を未然に防ぐ現場の知恵
ネットワークのトラブルシューティングをしていると、たまに「なぜか通信が時々途切れる」「特定の端末を入れるとネットワークが不安定になる」といった、原因の特定に時間がかかる怪奇現象に遭遇することがあります。
その多くが、実は「IPアドレスの重複」という古典的かつ致命的なミスに起因しています。そして、この悲劇を防ぐための最前線で、ひっそりと、しかし極めて重要な役割を果たしているのが Gratuitous ARP(無償ARP) です。
今日は、教科書的な定義をなぞるのではなく、現場でこいつがどう動き、トラブルを未然に防いでいるのか、その泥臭い仕組みを紐解いていきましょう。
—
Gratuitous ARPとは何者か?
Gratuitous ARP(以下、GARP)を一言で言えば、「自分自身のIPアドレスをブロードキャストして、周りに存在を主張するパケット」のことです。
通常、ARPリクエストは「192.168.1.10のMACアドレスを教えてくれ」と問いかけるものですが、GARPは少し違います。送信元IPもターゲットIPも、自分自身のIPアドレスをセットして送出します。
なぜそんなことをするのか?
理由は大きく分けて2つあります。
1. IPアドレスの重複検知(DAD: Duplicate Address Detection)
OSがインターフェースを立ち上げた際、もし自分と同じIPを持つ端末が既にネットワーク上にいれば、その端末が「それは俺のIPだ!」とARPリプライを返してきます。これで「あ、先客がいるな」と気づくわけです。
2. 経路情報の更新(フェイルオーバー)
HA構成(冗長化)のロードバランサーやルーターが切り替わった際、GARPを投げつけることで、スイッチのMACアドレステーブルを強制的に書き換えさせ、通信先を新しい筐体へ一瞬で誘導します。
—
実際にパケットを覗いてみる
現場で「本当にGARPが飛んでいるか?」を確認するには、tcpdumpを使うのが一番早いです。以下は、LinuxサーバーでインターフェースをUPさせた際の様子を想定したコマンドです。
# eth0インターフェースでARPのみをキャプチャする
# -n: 名前解決をしない
# -e: MACアドレスを表示する
sudo tcpdump -i eth0 -n -e arp
もし、自分と同じIPを持つ端末がいれば、以下のようなログが流れてくるはずです。
# 自分が送出したGARP
10:00:00.000000 00:0c:29:ab:cd:ef > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.50 tell 192.168.1.50
# 既存端末からの返答(重複検知!)
10:00:00.000005 00:0c:29:12:34:56 > 00:0c:29:ab:cd:ef, ethertype ARP (0x0806), length 42: Reply 192.168.1.50 is-at 00:0c:29:12:34:56
この「Reply」が返ってきた瞬間に、OSは「IPの競合が発生した」と判断し、エラーをログに吐いて通信を停止させるのが正常な挙動です。
—
Web APIエンジニアが知っておくべき「切り替え」のリアル
クラウド環境やオンプレミスの冗長構成において、VIP(仮想IP)を切り替える際、このGARPがどれほど重要か。例えば、Keepalivedなどの構成で、MasterがダウンしてBackupが昇格する瞬間を想像してください。
# keepalived.conf の設定例
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.1.100 # このVIPに切り替わった瞬間、GARPが送信される
}
}
この設定で切り替えが発生すると、Keepalivedは自動的にGARPを送信します。これを受け取ったL2スイッチは、「お、192.168.1.100のMACアドレスが新しいポートに変わったのか」と学習し、トラフィックの向きを瞬時に変更します。
もし、このGARPがスイッチ側でフィルタリングされていたり、スイッチが学習に失敗すると、通信は数秒〜数十秒間「ブラックホール」に落ち込みます。Web APIなら、この瞬間に504 Gateway Timeoutが大量発生するわけです。
—
デバッグと実務のTips
もしあなたがインフラ運用に携わっていて、「切り替え時に通信が数秒止まる」という相談を受けたら、まずは以下を疑ってみてください。
1. GARPの送信回数が少なすぎないか
多くのOSやツールでは、GARP送信回数を設定できます。デフォルトが1回なら、スイッチがパケットをドロップした瞬間に負け確定です。3回程度に増やすのが現場の定石です。
2. スイッチのポート設定
スイッチ側で PortFast や Edge Port 設定が有効か確認してください。スパニングツリー(STP)の計算中にGARPが届くと、スイッチがポートを閉じていて無視されることがあります。
3. Pythonで簡易的な検知スクリプトを書く
本番環境の監視が難しい場合、scapy を使って特定のIPに対するGARPを監視する小さなPythonスクリプトを常駐させるのも手です。
from scapy.all import sniff, ARP
def detect_garp(pkt):
if pkt.haslayer(ARP) and pkt[ARP].op == 1: # ARP Request
if pkt[ARP].psrc == pkt[ARP].pdst:
print(f"GARP検知: IP {pkt[ARP].psrc} がMAC {pkt[ARP].hwsrc} から主張されています")
# eth0でARPトラフィックを監視
sniff(filter="arp", prn=detect_garp, store=0, iface="eth0")
—
まとめ:ネットワークは「おしゃべり」で成り立っている
Gratuitous ARPは、一見するとネットワークを騒がしくするだけのパケットに思えるかもしれません。しかし、これこそが「自分はここにいる」「自分はあそこに移動した」という、ネットワーク機器同士の絶え間ない信頼関係の構築そのものなのです。
「なぜか繋がらない」というトラブルの裏側には、必ずこうしたパケットの「言い分」があります。ぜひ、コマンドの出力結果だけでなく、その背後でパケットたちがどう会話しているのかを想像してみてください。それが、凄腕エンジニアへの第一歩です。
それでは、また次回の現場の知恵でお会いしましょう。トラブルに負けない強固なアーキテクチャを!
コメント