同じ Wi-Fi・同じLANにいる誰かが、あなたとインターネットの間にこっそり割り込む——これが**中間者攻撃(Man-in-the-Middle, MITM)**で、その最も古典的かつ強力な入口が ARPスプーフィングです。攻撃者は一発の銃弾も撃たず、ただ「嘘のARP応答」を撒くだけで、被害者の全通信を自分の手のひらに乗せます。
この記事は、ネットワークペンテストの全体像に続き、ARPスプーフィング/MITM の仕組みを正確に解説し、検知と、RFC・ベンダ標準に準拠した防御を型安全なコードとともに示します。核心は「ARP に認証がない」というTCP/IP の根本的な信頼の前提です。
安全地帯の徹底:ARPスプーフィングは同一セグメントの第三者の通信を巻き込む性質上、特に危険です。本記事の手順は隔離ラボ(内部ネットワークの自分のVM 3台)の中だけで実行します。職場・学校・カフェ・自宅の共有Wi-Fiで試すことは、他人の通信の秘密を侵害し、不正アクセス禁止法・電気通信事業法に明確に違反します。攻撃ツールの「コマンド」より、向ける「先」を間違える方が、はるかに重大です。法律の記事を必ず先に。
1. なぜ ARP は騙せるのか — 「認証なき信頼」
ARP(Address Resolution Protocol)は、「IPアドレス → MACアドレス」を解決するL2のプロトコルです。同じLAN内で 10.10.10.1(ゲートウェイ)に通信したいホストは、こう尋ねます。
[ Who has 10.10.10.1? Tell 10.10.10.10 ] ← ブロードキャストで全員に質問
[ 10.10.10.1 is at aa:bb:cc:dd:ee:ff ] ← ゲートウェイが応答
ホストはこの応答をARPキャッシュに保存し、以後そのMAC宛に送ります。問題は——ARPには送信元を検証する仕組みが一切ないこと。誰でも「私が 10.10.10.1 だ」と応答でき、しかも尋ねられてもいないのに勝手に応答(Gratuitous ARP)を撒けます。受け取った側は無条件に信じ、キャッシュを上書きします。「言った者勝ち」——これが全ての元凶です。
2. ARPスプーフィング → MITM の成立
攻撃者(10.10.10.5)は、被害者とゲートウェイの双方に嘘をつき、自分を経路に挿入します。
攻撃者が撒く2つの嘘(偽 ARP 応答):
① 被害者(10.10.10.10) へ → 「10.10.10.1(GW) のMACは 攻撃者のMAC だよ」
② ゲートウェイ(10.10.10.1) へ → 「10.10.10.10(被害者) のMACは 攻撃者のMAC だよ」
結果、通信経路が捻じ曲がる:
被害者 ──► [ 攻撃者 ] ──► ゲートウェイ ──► インターネット
◄── ◄──
(双方は「直接やり取りしている」と思い込んでいる)
経路を奪った攻撃者は、IP フォワーディングを有効にして通信を素通しさせれば被害者に気づかれず、その上で:
- 盗聴:流れる平文(HTTP・古いプロトコル)をそのまま読む(→パケット盗聴)。
- 改ざん:応答を書き換える(HTTPSへのリダイレクトを剥がす SSL ストリップ等)。
- セッションハイジャック:TCPセッションを奪う土台にする。
ラボでは
arpspoof(dsniff)やettercap/bettercapが教材として使われます。本記事では攻撃の発射コマンドは示しません——仕組みの理解が目的であり、無害化(防御)にページを割きます。再現が必要なら、必ず隔離ラボの自分のVM間でのみ、各ツールの公式ドキュメントに従ってください。
3. 検知 — 「MACとIPの矛盾」を見張る
ARPスプーフィングには、消せない痕跡が残ります:「1つのMACアドレスが複数のIPを主張する」「ゲートウェイのMACが突然変わる」。これを監視すれば気づけます。
3.1 現場でまず使うもの
arpwatch:MAC↔IP の対応を学習し、変化したらアラートする古典的な定番。- エンドポイントでのARPテーブル監視:
ip neigh(Linux)/arp -a。ゲートウェイのMACが既知の値か。 - スイッチのログ:管理スイッチは DAI(後述)でドロップを記録する。
3.2 仕組みを理解する最小の検知ロジック(型安全)
ARP 観測イベントから「矛盾」を検出する純粋関数を書きます。原理の可視化であり、本番では arpwatch/IDS に乗せるべきものです。
/** 観測した1件のARPアナウンス(IP がこの MAC を主張した、の記録)。 */
interface ArpObservation {
readonly ip: string;
readonly mac: string;
readonly timestamp: number;
}
interface ArpAnomaly {
readonly kind: "mac-claims-multiple-ips" | "ip-mac-changed";
readonly detail: string;
}
/**
* ARP 観測列から、スプーフィングの兆候を検出する純粋関数。
* - 同一 MAC が多数の IP を主張(経路に挿入しようとする攻撃者の典型)
* - 既知の IP↔MAC 対応が別 MAC に変化(ゲートウェイ詐称の典型)
* 副作用なし=決定的でテスト容易。誤検知は既知の信頼マップで除外する。
*/
export function detectArpSpoofing(
observations: readonly ArpObservation[],
trustedIpToMac: ReadonlyMap<string, string>,
ipCountThreshold = 3,
): readonly ArpAnomaly[] {
const anomalies: ArpAnomaly[] = [];
const ipsByMac = new Map<string, Set<string>>();
for (const o of observations) {
// (1) 信頼済みの IP↔MAC が変化していないか(ゲートウェイ詐称の検出)
const trusted = trustedIpToMac.get(o.ip);
if (trusted !== undefined && trusted !== o.mac) {
anomalies.push({
kind: "ip-mac-changed",
detail: `${o.ip} expected ${trusted} but saw ${o.mac}`,
});
}
// (2) 1つの MAC が複数 IP を主張していないか
const ips = ipsByMac.get(o.mac) ?? new Set<string>();
ips.add(o.ip);
ipsByMac.set(o.mac, ips);
}
for (const [mac, ips] of ipsByMac) {
if (ips.size >= ipCountThreshold) {
anomalies.push({
kind: "mac-claims-multiple-ips",
detail: `${mac} claims ${ips.size} IPs: ${[...ips].join(", ")}`,
});
}
}
return anomalies;
}
trustedIpToMac(ゲートウェイ等の既知の正しい対応)を渡すことで、誤検知を構造的に減らしつつ、ゲートウェイ詐称という最も危険なケースを確実に捉えます。検知ロジックを純粋関数に切り出す利点は、ゴールデンベクタでテストを固定でき、運用中に閾値を安全に調整できることです。
4. 防御 — 3層で無害化する
ARP攻撃は、**インフラ統制(予防)→ 認証(接続制御)→ 暗号化(最後の砦)**の3層で無害化します。
4.1 L2 インフラ統制:Dynamic ARP Inspection + DHCP Snooping(本命)
管理スイッチの機能で、偽のARPを物理的にドロップします。これが最も効く予防です。
- DHCP Snooping:スイッチが「どのポートのどのMACに、どのIPが正規に割り当てられたか」を信頼テーブルとして学習する。
- Dynamic ARP Inspection(DAI):ARP応答をこの信頼テーブルと突き合わせ、矛盾するARP(=スプーフィング)をポートで落とす。
[ Cisco IOS の概念例(ベンダ公式手順に従う) ]
ip dhcp snooping
ip dhcp snooping vlan 10
ip arp inspection vlan 10 ← VLAN10 で DAI 有効化
interface gi0/1
ip dhcp snooping trust ← アップリンク(GW側)だけ信頼
! 端末ポートは untrust のまま → 端末からの偽ARPは検査され落ちる
4.2 接続制御:802.1X でそもそも入れない
IEEE 802.1X によるポートベース認証で、認証を通らない端末はLANに接続すらできません。攻撃者の物理/無線アクセス自体を断つ、ゼロトラストの入口です。
4.3 最後の砦:TLS — 「経路を奪われても中身は守る」
ここが本質的に重要です。たとえ ARP で経路を奪われても、正しく検証された TLS なら攻撃は無害化されます。
- 盗聴:TLS で暗号化されていれば、攻撃者が読むのは暗号文だけ。
- 改ざん:TLS は完全性を保証する。書き換えれば検知され接続が切れる。
- なりすまし:証明書検証により、攻撃者は正規サーバーの証明書を提示できない。
ただし条件があります——証明書検証を絶対に無効化しないこと(rejectUnauthorized: false は厳禁)。そして HTTP→HTTPS の格上げ前を突く SSL ストリップを防ぐため HSTS(Strict-Transport-Security)を効かせること。
import { request } from "node:https";
// ✅ TLS 検証は既定で有効。MITM 下でも証明書不一致で接続が落ちる=安全側に倒れる
const req = request(
{ hostname: "api.example.com", port: 443, path: "/", method: "GET" },
(res) => {
// res.socket は TLSSocket。検証済みでなければここに到達しない
res.resume();
},
);
// ❌ 絶対にやってはいけない:rejectUnauthorized: false(MITM を自ら招き入れる)
req.on("error", (e) => console.error("TLS handshake/verify failed:", e.message));
req.end();
ゼロトラストの結論:「社内LANだから安全」という前提を捨て、ネットワーク位置を信頼の根拠にしない。すべてのサービス間通信を相互TLS(mTLS)等で暗号化・認証すれば、ARP で経路を奪われても攻撃者は何も得られません。これが ARP 攻撃を時代遅れにする最終解です。
5. まとめ
- ARPスプーフィングの根本原因は「認証なき信頼」。誰でも「私がそのIPだ」と偽れ、受信側は無条件に信じる。
- MITM が成立すると盗聴・改ざん・セッションハイジャックが可能。前提は「同一セグメントにいること」。
- 検知:MAC↔IP の矛盾(1MACが複数IP・GWのMAC変化)を
arpwatch/IDS/純粋関数で監視。 - 防御は3層:①DAI+DHCP Snooping(偽ARPを物理ドロップ)②802.1X(無許可端末を入れない)③TLS/mTLS(経路を奪われても中身を守る最後の砦)。
- TLS の証明書検証を無効化しない・HSTS を効かせる。ゼロトラストが ARP 攻撃を無意味化する。
次は、名前解決そのものを乗っ取る**DNSスプーフィング / キャッシュポイズニング**を、DNSSEC による防御まで含めて扱います。
私(友田 陽大)は、サービス間通信の TLS/mTLS 化、証明書運用、ゼロトラストなネットワーク設計(プライベートサブネット分離・最小権限・暗号化必須)を本番で実装してきました。「社内ネットワークの MITM 耐性を上げたい」「平文通信が残っていないか棚卸ししたい」「mTLS を導入したい」——こうした“経路を信頼しない”設計を、攻撃者の視点で診断し、検知と暗号化の両輪で実装します。お気軽にご相談ください。