IPv6 の不正利用を /64 プレフィックスでレート制限・ブロックする方法
IPv6 のレート制限はアドレス単位ではなくプレフィックス単位で行います。1人の契約者が /64 全体を持つためです。制限とブロックは /64 をキーにし、/56 と /48 へ段階的に広げ、レピュテーションを減衰させます。

本番環境にあるレートリミッター、ログインスロットル、IP ブロックリストのほとんどすべては IPv4 を前提に設計されています。そこでの考え方は単純で、アドレス1つがおおむねユーザー1人です。アドレスごとにリクエストを数え、アドレスを禁止して、次に進みます。このモデルは、いつの間にか成り立たなくなりました。トラフィックに IPv6 が含まれた時点で(しかもその割合は大きく、増え続けています)、数えている単位は人に対応しなくなり、「アドレス1つ」を前提にした防御はすべて穴が空きます。
これは些細なエッジケースではありません。ダッシュボードには1リクエストずつのアドレスがきれいに並んでいるのに、攻撃者がそのまま素通りしてしまうレートリミッターと、きちんと機能するレートリミッターの違いです。解決策はルールを増やすことではなく、正しいものを数えることです。これは、単一のアドレスよりも公開されている CIDR ブロックが重要になる、IP 範囲で AI クローラーとボットを検証するときと同じ習慣です。プレフィックス単位のカウントは、IP アドレスによるボット検知の1つのレイヤーであり、他のレイヤーはそのプレフィックスがどんな種類のネットワークに属するかを教えてくれます。

IPv6 で破綻する IPv4 の習慣
IPv4 では、アドレスの希少性が味方をしていました。アドレスは約43億個しかなく、高価で、契約者が一度に1つの公開アドレスを持つのが圧倒的に一般的な形でした。そのため「この /32 からのリクエスト」と「このユーザーからのリクエスト」はほぼ同じものとして扱えました。/32 を禁止しても、迷惑を被るのは多くてもその世帯か、その背後の NAT くらいでした。
IPv6 は希少性を取り除き、その前提も取り除きます。アドレスは32ビットではなく128ビット(4桁の16進数が8組)で、設計思想は倹約とは正反対です。単一のアドレスを配給する代わりに、IPv6 はすべての顧客にアドレスのブロックを渡します。誰もが受け取る最小のブロックでさえ巨大で、ユーザーの実体はそのブロックであって、個々のアドレスではありません。
IPv6 で今もアドレス全体ごとに数えているレートリミッターに対して、不正を行う側にボットネットやプロキシプールは必要ありません。普通の IPv6 割り当てが1つと、for ループが1つあれば足ります。
1人の契約者に 1,844京個のアドレス
この数字が問題全体の見え方を変えます。IPv6 のエンドユーザーに通常割り当てられる最小のルーティング可能なブロックは /64 です。上位64ビットがネットワークで、下位64ビットは自由に使えます。つまり1人の契約者のサブネットの中に、2^64 個の使えるアドレスがあります。
2^64 = 18,446,744,073,709,551,616 個のアドレス:約 1,844京個で、すべて1人のユーザーのものであり、すべて同じようにルーティング可能です。
これが偶然ではなく避けられないものである理由は2つあります。第一に、IPv6 のホストが自分でアドレスを割り当てる標準的な方法であるステートレスアドレス自動設定(SLAAC)は、サブネットごとに /64 全体を必要とします。通常の LAN にそれより小さいものは割り当てられません。第二に、RIR が従うアドレス計画のガイダンス(RFC 6177 / BCP 157)は、ISP が各エンドサイトに十分な割り当て、一般的には /56 や /48 を渡し、/64 より小さくしてはならないとしています。潤沢さこそがこのプロトコルの要点です。
次に攻撃者の側です。これらのアドレスを順に切り替えるのは、高価でも巧妙でもありません。ソケットオプションとして最初から用意されています。Linux の IP_FREEBIND フラグを使うと、プロセスはインターフェースにアドレスを1つずつ設定しなくても、ローカルにルーティングされているプレフィックス内の任意のアドレスにバインドして送信できます。広く参照されている freebind プロジェクトのような公開ツールは、まさにそれを「接続ごとに新しい送信元アドレスを使う」ものとしてまとめています。ルーティングされた /64 を渡せば、1,844京個の異なる送信元から、コストなしで通信を出せます。
したがって /128 単位のレート制限では、何分の一にも遅くなりません。どのリクエストも、一度だけ見る新しいアドレスに見えます。レートリミッターのカウンターは1を超えず、ブロックリストは何百万もの1回きりのエントリーで埋まって何にも一致せず、攻撃は帳簿上は完全に分散しているように見えたまま、全速力で進みます。
IPv6 の割り当て階層と、各レベルが意味するもの
正しい単位で制限するには、各プレフィックス長が実際に何を表すかを知る必要があります。IPv6 のプレフィックスは単なる CIDR ブロック(IPv4 と同じ /n 表記で、数字が小さいほど多くのアドレスを含む)ですが、慣例的な境界には、反対側にいるのが誰かについての意味があります。
| プレフィックス | 含まれるもの | 誰・何を表すか | 集約のキーにして安全か |
|---|---|---|---|
| /128 | アドレス1つ | 1つのインターフェース。契約者が持つ何京個のうちの1つで、無料で切り替えられる。 | いいえ。これが間違いの元で、単位にしてはいけない。 |
| /64 | サブネット1つ(2^64 個のアドレス) | 1人の契約者の LAN。1人のユーザーであることが保証される最小のブロック。 | はい。これがレート制限とブロックの標準のキー。 |
| /56 | /64 が256個 | ISP から割り当てられる典型的な家庭や小規模事業所の割り当て。 | はい、継続する場合に。1人の顧客の割り当て全体。 |
| /48 | /64 が65,536個 | より大きなサイトや事業所の割り当て。 | はい、継続する場合に。通常は依然として1つの主体。 |
| /32 | /64 が43億個 | ISP やホスティングプロバイダの割り当て全体。 | まれに。ネットワーク全体で、数千のユーザーを含む。 |
判断の形はこの表から自然に導かれます。/128 が単位になることはありません。/64 が下限であり、1つの行為者に対応する最も狭い範囲なので、標準になります。それより広いものはすべてエスカレーションであり、より広い割り当て全体が問題であるという証拠があるときにだけ使います。
ルール1:IPv6 はプレフィックス単位でレート制限する。出発点は /64
破綻の大部分を直す最も重要な変更は、アドレス単位で数えるのをやめて、/64 単位で数えることです。具体的には、受信するすべての IPv6 リクエストについて、最初の4つの16進数グループ(64ビット)を残して /64 を導き、それをレート制限のカウンター、ログイン試行の集計、ブロックリストの照合のキーとして使います。
// Normalize any IPv6 address to its /64 aggregation key.
// The first 64 bits (4 hextets) identify the subscriber's subnet;
// the last 64 bits are theirs to rotate through, so we discard them.
function ipv6Key(addr) {
// Expand "2001:db8::1" to full form, take the first four groups.
const full = expandIPv6(addr); // 8 groups of 4 hex digits
return full.split(":").slice(0, 4).join(":") + "::/64";
}
// "2001:0db8:85a3:0000:0000:8a2e:0370:7334" -> "2001:0db8:85a3:0000::/64"
主要なエッジツールはどれもすでにこれに対応しているため、自分で作る必要はほとんどありません。
- nginx: IPv6 を /64 にマスクする
map/geoブロックから制限キーを作り、$binary_remote_addrの代わりにlimit_req_zone/limit_conn_zoneに渡します。 - HAProxy: stick-table のキーを作るときに送信元へ64ビットのマスクを設定し、
srcが完全なアドレスではなく /64 に集約されるようにします。 - Cloudflare と大半の CDN / WAF: レート制限やチャレンジのロジックで、すでに IPv6 を /64 ブロック単位で扱っています。2つのレイヤーが一致するよう、オリジンのルールでも同じ粒度にそろえます。
- 自社アプリのリミッター: 生の
remote_addrを、Redis やトークンバケット、カウンターに届く前に、上記の /64 キーに置き換えます。
これだけで、無料で切り替える攻撃は本来の姿に戻ります。1,844京個のアドレスが1つのカウンターになり、不正を行う側は、単一の IPv4 アドレスの場合とまったく同じように抑制されます。このテーマ全体で最も価値の高い1行です。
ルール2:継続する場合は /56 と /48 に広げる
/64 をキーにすれば、1つのサブネットの内側でアドレスを切り替える攻撃者に対処できます。階段を1段上がると、サブネットを切り替える攻撃者がいます。契約者は /64 を1つではなく、それらで埋まった /56 や /48 全体を持っていることが多く、freebind のようなツールはそれらをまたいで動くこともできるからです。
広げる合図は継続性です。共通の親プレフィックスを持つ新しい /64 が、不正を続けている状態を指します。それが見えたら、その割り当て全体が1つの主体であり、1つとして範囲を決めるべきです。
| 観測されること | 意味すること | 対応 |
|---|---|---|
| 1つの /64 からの不正 | 単一のサブネットが発信元。 | その /64 をレート制限・ブロックする。 |
| 同じ /56 内の新しい /64 が繰り返し現れる | 家庭や小規模事業所の1つの割り当てがサブネットを切り替えている。 | カウンターとブロックを /56 に広げる。 |
| /48 全体に広がる不正 | サイトの割り当て全体が悪意を持っている。 | /48 に広げる。それでも通常は1つの顧客。 |
| /32 内の多数の /48 | ISP 全体の空間に紛れたノイズ。 | /32 はブロックしない。個々のプレフィックスをスコアリングする。 |
ロールアップするカウンターだと考えてください。/64 の集計を基本の単位として維持しつつ、/56 と /48 に集約した不正も追跡します。親プレフィックスが、正当な顧客1人では到達しないしきい値(多数の異なる子 /64 が短時間にすべて不正を行っている状態)を超えたら、親のレベルで制限を適用し、すべての子を一度にカバーします。こうすれば、大きな割り当てを持つ攻撃者の先を行きつつ、小さくて行儀のよい割り当ての持ち主を罰することがありません。
ルール3:反射的にではなく、ネットワークの種類で広げる
エスカレーションには失敗のパターンがあり、それは代償が大きいものです。広げすぎると、1回の禁止で数千の無実のユーザーが消えてしまいます。/48 は1つの事業所かもしれませんし、モバイルキャリアの一部かもしれません。/32 が1つの行為者であることはほとんどなく、通常は ISP やホスティングプロバイダ全体です。継続性のシグナルは、親プレフィックスが関与していることは教えてくれますが、その背後に実在の人が何人いるかは教えてくれません。それを知るには、そのプレフィックスがどんな種類のネットワークかを知る必要があります。
IP ルックアップがパイプラインで役立つのは、まさにここです。問題のプレフィックスから代表的なアドレスを選び、IP ルックアップ API を1回呼び出せば、積極的にまとめてよい借り物のインフラなのか、丁寧に扱うべき一般消費者向けのアクセスなのかがわかります。
curl -H "x-api-key: YOUR_API_KEY" \
https://api.geoiphub.com/v1/lookup/2001:4860:4860::8888
どこまで安全に広げてよいかを左右するフィールドは次のとおりです。
const res = await fetch(`https://api.geoiphub.com/v1/lookup/${addr}`, {
headers: { "x-api-key": process.env.GEOIPHUB_API_KEY },
});
const ip = await res.json();
ip.asn.asn_type; // "hosting" | "isp" | "mobile" | "cdn" ...
ip.asn.connection_type; // "datacenter" | "residential" | "mobile"
ip.asn.carrier; // set for cellular networks: a leniency signal
ip.detection.is_hosting; // true: infrastructure, aggregate up freely
ip.threat.is_cgnat; // shared address space; do not widen a hard ban
ip.scoring.fraud_score; // 0-100 composite, when you must decide per-address
ip.scoring.recommended_action; // "allow" | "review" | "step_up" | "block"
ip.scoring.detection_methods; // exactly which signals fired: your audit trail
実在の IPv6 アドレスである Google Public DNS の 2001:4860:4860::8888 を 2026-10-05 にルックアップした結果を示します(省略版です。範囲が移動すると結果も変わります)。
{
"ip": "2001:4860:4860::8888",
"asn": {
"asn": 15169,
"org": "GOOGLE - Google LLC",
"asn_type": "hosting",
"connection_type": "datacenter",
"carrier": "none"
},
"detection": {
"is_proxy": false,
"is_vpn": false,
"is_tor": false,
"is_hosting": true,
"is_mobile": false
},
"threat": {
"is_cgnat": false
},
"scoring": {
"fraud_score": 15,
"recommended_action": "allow",
"detection_methods": ["datacenter_ip", "no_ptr_datacenter"]
}
}
レスポンスの2つの部分は、別々の問いに答えています。asn_type: "hosting"、connection_type: "datacenter"、is_hosting: true は、そのプレフィックスがインフラであることを示しているので、/64 より広くブロックしても一般家庭には当たりません。一方で scoring.fraud_score は 15、recommended_action は allow です。このアドレス自体には VPN、Tor、不正利用のシグナルがなく、detection_methods には datacenter_ip と no_ptr_datacenter しかありません。ネットワークの種類は、どこまで広げてよいかを教えてくれますが、広げる理由そのものは、自分たちの継続性のカウンターが示さなければなりません。一度も不正を行っていないホスティングのプレフィックスは、開けたままにします。
読み方には方向性があり、リスクスコアの理由が加算・減算される仕組みの背後にある原則と同じです。強く対処してよいことを示すフィールドもあれば、控えるよう教えてくれるフィールドもあります。
| ネットワークの種類 | 広いプレフィックスに含まれるもの | どこまでエスカレートするか |
|---|---|---|
| ホスティング / データセンター | 借りられたサーバー。本物の買い物客はここにいない。 | 積極的に。ホスティング空間の悪意ある /48 を丸ごとブロックしてよい。 |
| 住宅用 ISP | 家庭。より広いプレフィックスの背後に、1世帯につき1つの /64。 | 慎重に。禁止は /64 から /56 にとどめる。/48 には多くの家族が含まれるかもしれない。 |
| モバイル / セルラー | キャリアの契約者。しばしばより広い空間を共有している。 | 狭く。キャリアの /32 は一国分の携帯電話を含むため、ハードブロックしてはならない。 |
| CGNAT / 共有 | 共有アドレス空間の背後にいる多数の契約者。 | スコアリングし、禁止はしない。共有 IPv4 アドレスと同じように扱う。 |
Google Ads でも数え方は同じです。その API は 2001:db8::/48 を1件の IP 除外エントリーとして受け付けるため、/48 は Google Ads の除外枠500件のうち1つを消費します。
この原則については、本物の顧客をブロックせずに匿名化トラフィックを検知する方法で詳しく論じています。hosting や datacenter のプレフィックスでは、チェックアウトや登録がサーバーラックから来る正当な理由はないので、自信を持ってブロックを広げられます。これはデータセンター IP アドレスとは何かで解説しているのと同じ手がかりです。mobile や residential のプレフィックスでは範囲を狭く保ち、広い CIDR の禁止ではなくリスクスコアに役割を担わせます。反射的に広げると、レートリミッターは知らないうちに本物のユーザーにとっての障害になります。
ルール4:プレフィックスのレピュテーションを減衰させる
最後のルールは時間に関するものです。IPv4 のブロックリストも、アドレスが再割り当てされるためすでに古くなります。IPv6 ではさらに悪化します。プレフィックス全体が委任され、返却され、再び委任されるため、先月ログインページを叩いた /64 が、今日は普通の世帯のものになっているかもしれないからです。入れ替わるアドレス空間に対する永続的なブロックリストは、いずれ安全には到達できない場所の一覧になってしまいます。
そこで、プレフィックスごとに永続的な判定を保存するのはやめましょう。代わりに、動くレピュテーションを保存します。
- 不正があれば上げる。 不正なリクエストのたびに /64 のスコアを上げ、それより小さな増分を親の /56 と /48 にもロールアップします。
- 時間とともに減衰させる。 プレフィックスが静かなままなら、スケジュールに沿ってスコアが下がり(ソフトなスロットルなら時間単位、ハードなブロックなら日単位)、しきい値を下回るとブロックは自動的に解除されます。
- 履歴ではなく現在のスコアで対処する。 レート制限、チャレンジ、ブロックは、レピュテーションが今どこにあるかに基づいて行います。更生したプレフィックスや再割り当てされたプレフィックスは、誰も整理しないリストに残り続けるのではなく、自動的に回復します。
- 証拠を残す。 各スコア変更の要因となったシグナル(ルックアップの
detection_methods、継続性のパターン)を保存しておけば、広範囲のブロックは正体不明のエントリーではなく、説明できる判断になります。
減衰があるからこそ、システム全体が誠実さを保てます。攻撃中の積極的なエスカレーションが永続的な傷跡にならず、ブロックリストは、かつて悪意があった相手ではなく、今まさに悪意のある相手を反映するようになります。
今週から始めること
- リミッターのキーを /64 に切り替える。 現在アドレス単位で数えたりブロックしたりしているすべての箇所で、先に IPv6 を上位64ビットにマスクします。この1つの変更で、無料での切り替えの穴が塞がります。nginx、HAProxy、アプリのいずれでも、通常は数行で済みます。
- /56 と /48 のロールアップカウンターを追加する。 親プレフィックスに集約した不正を追跡し、サブネットを切り替える攻撃者がより広い制限に引っかかるようにします。デフォルトで広げる必要はありません。
- 広げる前にネットワークを調べる。 /64 より広げるエスカレーションでは、
asn_type/connection_typeを確認します。ホスティングなら自由に集約し、モバイルと住宅用では範囲を狭く保ち、キャリアや CGNAT の範囲は決してハードブロックしません。 - 曖昧なケースはスコアリングする。 プレフィックスが共有または一般消費者向けの場合は、粗い CIDR の禁止ではなく、アドレスごとの総合的な
fraud_scoreとrecommended_actionを使います。 - すべてのブロックに減衰を持たせる。 プレフィックスのレピュテーションを半減期つきで保存し、現在のスコアで対処し、再割り当てされた空間が自動的に解除されるようにします。
IPv6 は不正利用対策を難しくしたというより、単位を変えました。もはやアドレスがユーザーではなく、/64 がユーザーです。それを数え、証拠に基づいてエスカレートし、ネットワークの種類で重みを付け、許すことは時間に任せてください。そうすれば、IPv4 で信頼してきた防御はどれも、再び機能します。
よくある質問
なぜ IPv4 と同じ方法で IPv6 アドレスをレート制限できないのですか?
2つのプロトコルでは、ユーザー1人あたりに割り当てられるアドレス空間の大きさがまったく違うからです。IPv4 では通常、契約者1人に1つのアドレスが割り当てられるため、/32(単一アドレス)単位の制限はユーザー単位の制限になります。IPv6 では、契約者1人に /64 全体が割り当てられるのが普通です。これは 2^64、約 1,844京個のアドレスで、IP_FREEBIND のようなツールを使えば、プロセスはそのブロック内の任意のアドレスから無料で通信を送れます。そのため /128(単一の IPv6 アドレス)をレート制限したりブロックリストに入れたりしても何も止まらず、不正を行う側は1,844京個のうち次のアドレスを使うだけです。IPv6 での正しい単位は /128 ではなく /64 です。
IPv6 はどのプレフィックス長でレート制限すべきですか?
/64 から始めます。SLAAC はサブネットごとに /64 全体を必要とし、ISP はすべての顧客に少なくとも /64 を割り当てるため、/64 は単一のエンドユーザーに属することが保証される最小のブロックです。カウンターとブロックリストをアドレスの上位64ビットをキーにして管理し、/64 全体を1人の行為者として扱います。同じ顧客から多数の /64 にわたって不正が続く場合は、対象範囲を /56(/64 が256個)、さらに /48(/64 が65,536個)へ広げます。これらは家庭や事業所全体に割り当てられる典型的なサイズです。
IPv6 の /64 全体をブロックしても安全ですか?
ほとんどの場合は安全で、IPv4 の単一アドレスをブロックするより安全です。/64 は1人の契約者のサブネットとなるよう設計されているため、共有される IPv4 の CGNAT アドレスのように無関係な第三者を巻き込むことはまずありません。本当のリスクはもっと広いプレフィックスにあります。/48 や /32 は、ISP 全体、モバイルキャリア、数千の無関係なユーザーを含む共有ホスティング範囲になりえます。範囲を広げるのはネットワークの種類がそれを正当化するときだけにしてください。ホスティングやデータセンターのプレフィックスでは積極的に、モバイルや住宅用では慎重に行います。
ブロックをどこまで広げるべきかは、どう判断しますか?
継続性とネットワークの種類の2つで決めます。継続性とは、同じ /56 や /48 の中の新しい /64 から不正が繰り返し現れるなら、その割り当て全体が1つの主体であり、そこまで広げるということです。ネットワークの種類については、ルックアップがホスティングまたはデータセンターの ASN を返すなら、そのプレフィックスはインフラなので素早くまとめて対処できます。モバイルキャリアや住宅用 ISP の場合は、広いプレフィックスの背後に多くの実在ユーザーがいる可能性があるため、範囲は狭いままにして、完全な禁止ではなくリスクスコアに頼ります。
CGNAT やモバイルネットワークは IPv6 の扱いを変えますか?
はい、広い側では変わります。モバイルでも通常、IPv6 の /64 は1人の契約者に対応するため、/64 単位の制限は依然として正しい方法です。ただしモバイルキャリアや 464XLAT/NAT64 の構成では、より広い共有プレフィックスの下に多くの契約者が置かれることがあり、モバイル ASN に対する /48 や /32 の広い禁止は、キャリアの顧客のかなりの部分を巻き込みかねません。ルールは IPv4 と同じで、1人の不正行為者を理由に共有範囲をハードブロックしてはいけません。スコアリングを行い、広範囲の禁止はインフラのプレフィックスに限ってください。
IPv6 プレフィックスはどのくらいの期間ブロックしておくべきですか?
永久にではありません。IPv6 のプレフィックスは再割り当てされ、先月不正を行った /64 が来月には別の顧客のものになっていることもあります。プレフィックスごとに永続的なエントリーを持つのではなく、減衰するレピュテーションを付与してください。不正があればスコアを上げ、何も起きなければ時間とともにスコアを下げ、しきい値を下回ったらブロックを自動で解除します。入れ替わるアドレス空間に対する永続的なブロックリストは、いずれ安全には到達できないアドレスの一覧になってしまいます。
GeoIPHub API を支えるチーム
GeoIPHub IP インテリジェンス API とそのスキャナーを開発している GeoIPHub チームが執筆しています。下書きは AI の支援を受けて作成し、チームが編集しています。API の例は、「説明用」と明記したものを除き、本番 API に対する実際のルックアップです。


