2022.06.29 コラム
【テックコラム】RIR | IPアドレスから国の特定を自前でしてみる
●お国はどちら?
サイトのアクセス分析や各国のプライバシーポリシー対応には、「どの国からのアクセスか」を特定することが求められます。
アクセス元IPアドレスから国を判定する場合は、下記の様なサービスを利用することが多いですね。
SurfPoint / Geolocation Technology
これらのサービスは国名だけでなく市町村名など、より詳細の情報を判定する事が可能です。一方、国名のみ判定できれば良いというニーズにはオーバースペックであり、可能であれば無料で且つ更新頻度の高い情報を取得したいところです。そこで注目するのが RIR データです。
●RIR とは
RIR (Regional Internet Registry、地域インターネットレジストリ)は、それぞれの地域でIPアドレスの割り当て管理を行う組織です。
各 RIR は、それぞれの国へ割り当てるIPアドレスの情報をWebサイトで公開しています。RIR の一つである APNIC のデータは下記URLが最新になります。
各 RIR は、それぞれの国へ割り当てるIPアドレスの情報をWebサイトで公開しています。APNIC であれば、最新版は下記になります。
https://ftp.apnic.net/stats/apnic/delegated-apnic-latest
各RIR でも同様に公開していますが、さらに自組織のみならず他組織のデータも相互に公開しています。これにより特定RIRの Webサイトのダウンなどで参照できなくなることを防いでいるのです。
●RIRデータ
RIRデータのファイル形式はパイプ区切りのCSVとなっており、各フィールのカラムはこのようになっています。
- registry(レジストリ名)
- cc(国コード)
- type(IPv4/IPv6/AS番号)
- start(開始アドレス)
- value (IPv4:アドレス個数、IPv6:CIDR プレフィックス)
- date(割り当て年月日。YYYYMMDD形式)
- status(割り当て状態。allocated であれば割り当て済)
それぞれのカラムの詳細は、こちらのリンク先に解説されています。
実際の内容は下記のようになっています。
afrinic|ZA|ipv4|41.0.0.0|2097152|20071126|allocated afrinic|ZA|ipv6|2001:4200::|32|20051021|allocated
●CIDR表記とは
この情報を CIDR 表記にすることで使い勝手が良くなります。CIDR表記とは、192.168.1.0/24 といったネットワークアドレスとアドレス範囲(プレフィックス)を組み合わせた表記です。RIRデータの場合 IPv6 はvalueの値がCIDRプレフィックスのため、開始アドレスとプレフィックスを用いて CIDR 表記にすることは容易です。一方 IPv4 のアドレス個数は、このままでは扱いづらいため IPv6 と同じプレフィックスに変換します。
●CIDR 変換の前処理
変換に使用するのが python の ipaddress モジュールです。自前でCIDRプレフィックスを求めることは手間ですが、このモジュールではスマートに求めることが出来ます。
最初にブロードキャストアドレスを算出します。ブロードキャストアドレスは開始アドレスとアドレス個数 -1 の組み合わせから ipaddress モジュールの四則演算で容易に求めることが出来ます。それぞれのアドレスを IPv4Address オブジェクトへ変換します。
from ipaddress import ip_address ip_start = '41.0.0.0' ip_count = 2097152 addr_start = ip_address(ip_start) addr_bcast = addr_start + ip_count - 1
●CIDR 表記へ変換
CIDR の取得は summarize_address_range 関数を用います。アドレス個数によっては複数の CIDR に別れるため、この関数の返り値はイテレータです。
from ipaddress import summarize_address_range cidr_iter = summarize_address_range(addr_start, addr_bcast)
イテレータから取得できる値は IPv4Network または IPv6Network オブジェクトです。
>>> cidr = next(cidr_iter) >>> cidr IPv4Network('41.0.0.0/11') >>>str(cidr) '41.0.0.0/11'
これを保持すれば、CIDR と国コードの対応が準備出来ますね。
country_code = 'ZA' cidr_data = [(cidr, country_code) for cidr in cidr_iter ]
●CIDRとIPアドレスの照合
CIDR と国コードの準備が出来ましたら、次は任意のアドレスが CIDR に含まれるか判定しましょう。ipaddress モジュールの良い点は、この判定にも IPv4 と IPv6 を抽象的に扱える点です。
>>> from ipaddress import ip_network >>> cidr_v4 = ip_network('41.0.0.0/11') >>> ip_address('41.23.45.6') in cidr_v4 True >>> cidr_v6 = ip_network('2001:4200::/32') >>> ip_address('2001:4200:d6a4:2400:92c6:91fe:fb17:f194') in cidr_v6 True
●IPアドレスから国コードを取得する
CIDR と国コードの対応と、 CIDR に IPアドレスが含まれることが分かれば、それらを組み合わせて国コードを判定することが出来ます。
target_addr = ip_address('41.23.45.6') detect_code = [cidr[1] for cidr in cidr_data if target_addr in cidr[0] ] >>> detect_code ['ZA']
●最後に
公開されているデータを工夫し利用することにより、商用サービスに頼ることなくIPアドレスから国を判定できることが分かりました。参考にしていただければと思います。
弊社では事業会社様のデジタルマーケティング活動の支援を行っています。
また、自社に専門人材がいない、リソースが足りない等の課題をお持ちの方に、エンジニア領域の支援サービス(Data Engineer Hub)をご提供しています。
お困りごとがございましたら、是非お気軽にご相談ください。
本件に関するお問い合わせは下記にて承ります。
株式会社DataCurrent
info@datacurrent.co.jp