上限に達する前にキーの使用状況を監視する
割り当てヘッダーを随時確認しておけば、リクエストが実際に拒否されるよりずっと前に、上限が近づいていることが分かります。
203.0.113.42のようなアドレスと2001:db8::1のようなアドレスは見た目が明らかに異なりますが、アドレスがログファイルやデータベースの列に埋もれてしまうと、一方の形式を前提としたスクリプトは、もう一方を知らないうちに誤って処理してしまいます。
/v1/ipエンドポイントは、すべてのレスポンスで、その他の位置データとあわせて4または6のいずれかのversionフィールドを返します。アドレスがどちらのファミリーに属するかを判断するために、アドレス文字列を自分で解析する必要はありません。
GET /v1/ip?ip=2001:db8::1{
"status": "ok",
"ip": "2001:db8::1",
"version": 6,
"found": true,
"country": "Canada",
"country_code": "CA",
"region": "Ontario",
"city": "Toronto",
"postcode": "M5H",
"lat": 43.6511,
"lon": -79.3808,
"timezone": "America/Toronto",
"asn": 4321,
"org": "Example ISP"
}無料枠はネットワーク単位で集計され、そのネットワークの定義はアドレスファミリーごとに異なります。同じ/24を共有するすべてのIPv4アドレスは1つの枠を共有し、同じ/48を共有するすべてのIPv6アドレスは1つの枠を共有します。大きなブロックを割り当てられている1人のIPv6の顧客は、実際には1つの共有枠の中にいるにもかかわらず、ログでは多数の異なるアドレスのように見えることがあります。バージョンがわかっていれば、異なるアドレス文字列をすべて無関係なものとして扱うのではなく、正しい種類のネットワーク境界でログのエントリをグループ化できます。
両方のアドレスファミリーに対応した自宅のインターネット回線を使う訪問者は、その日にデバイスがたまたまどちらを使ったかによって、2回の訪問でIPv4とIPv6の、一見無関係な2つのアドレスとしてログに現れることがあります。単純に扱うと、2人の別々の訪問者のように見えます。生のアドレスだけでグループ化するのではなく、セッションCookieのような安定した識別子とあわせてバージョンでグループ化すれば、訪問者数が水増しされたり、1人の顧客の履歴が2つのプロフィールに分かれたりするのを防げます。
生のログをもとに独自のアナリティクスや不正利用の検出を作る場合は、ネットワークプレフィックスを計算しようとする前に、versionフィールドで処理を分岐させてください。/24のマスクをIPv6アドレスに適用しても意味がなく、/48のマスクをIPv4アドレスに適用しても意味がないからです。ログを読み返すたびに文字列の解析からバージョンを導き出し直すのではなく、アドレスそのものとあわせてバージョンを保存しておいてください。
IPv4のドット区切り表記向けに書かれた1つの正規表現を、IPv6アドレスも含む列に適用すると、ログの行が知らないうちに欠落したり誤って分類されたりする原因になります。1つのパターンで両方のファミリーをカバーできると想定するのではなく、IPv6アドレスでよく使われるダブルコロンの省略表記も含めて、アドレスを解析するコードを両方の形式で明示的にテストしてください。
この方法でバージョンを調べると、他のIP検索と同じく、確認するアドレス1件につき1リクエストかかります。大きなログファイルを監査する場合は、1行ごとに1リクエストを送るのではなく、一括POSTでアドレスをまとめて処理してください。項目あたりのコストは同じまま、呼び出し回数をはるかに少なくできます。
IPv4とIPv6を、単に文字列の長さが違うだけのものではなく、本当に別々のアドレスファミリーとして扱うことで、IPv6のトラフィックが訪問者のかなりの割合を占めるようになって初めて表面化する種類のバグを避けられます。このエンドポイントの詳細はIPv6検索のドキュメントで説明しています。