こんにちは。ナミレリです。みなさん、MacでPythonは使っていますか?
アクセスログのIPアドレスから国をサクッと調べたいときってありますよね。そこで今回は無料のGeoLite2を使ってPythonでIPアドレスから国を確認するプログラムを作ってみます。
この記事はこんな人にオススメ
- IPアドレスから国を確認したい
- 複数のIPアドレスから一気に国を確認したい
- しかも無料で簡単に確認したい
- M2 MacBook Air 13.6 インチ
- macOS Ventura 13.0.1
- pyenv 2.3.8
- miniforge3-4.10.3-10(Python 3.9.15)
目次
そもそもGeoLite2ってなに?
GeoLite2とはアメリカのMAXMIND社が提供する無料のIPジオロケーションのデータベースです。IPジオロケーションとはIPアドレスからデータベースを検索することを言います。
このGeoLite2は無料ですが、無料ではないGeoIP2というサービスもあります。こちらはより正確なデータ(緯度経度等でしょうか)で毎週データベースのアップデートがされるようです。
今回はプライベートなサーバに対して凄い勢いでアタックをするIPアドレスの国を確認したい程度で完璧な正確性は求めないので無料版のGeoLite2を使ってみます。
また、GeoLite2はデータをダウンロードして使用する方法と、APIへアクセスして使う方法があります。APIを使う場合は1日1,000回が上限のようなので、今回はデータをダウンロードして使用します。
IPアドレス割り振りの仕組みを理解し自前で作ることもできます
ちなみにGeoLite2を使わずとも各国に割り振られたIPアドレス公開されているのでそれを使えば今回の目的は達成できます。下の記事ではGeoLite2を使わずにpandasを使ってIPアドレスの国を確認していますので是非ご覧ください。
では世界的なIPアドレス割り振りの仕組みを簡単に紹介していきます。
IPアドレス割り振りの仕組み
世界のIPアドレスはICANNによってい管理されています。IPアドレスだけではなく新しいTLD(トップレベルドメイン)、AS番号の管理、ルートDNSの維持管理なども行っています。ICANNとは「Internet Corporation for Assigned Names and Numbers」の略です。
IPアドレスは、このICANNが世界に5つある地域インターネットレジストリ(Regional Internet Registry:RIR)に割り振り、このRIRがさらに各国に割り振り管理されています。
地域 | 名称 | 略 |
---|---|---|
北アメリカ | American Registry for Internet Numbers | ARIN |
ヨーロッパ、 中東 、中央アジア | RIPE Network Coordination Centre | RIPE NCC |
アジア・太平洋地域 | Asia-Pacific Network Information Centre | APNIC |
南アメリカ とカリブ海地域 | Latin American and Caribbean Internet Address Registry | LACNIC |
アフリカ | African Network Information Centre | AfriNIC |
アジア圏のRIRはAPNIC(Asia-Pacific Network Information Centre)です。このAPNICから日本であればJPNIC(Japan Network Information Center)に割り振りが行われます。
地域インターネットレジストリ(RIR)が公開しているIPアドレス割り振りデータ
前述の世界に5つある地域インターネットレジストリ(RIR)が各国に割り振りしたIPアドレスを公開しています。
アジア・太平洋地域の各国にIPアドレスを割り振るAPNICのサーバから世界に5つあるRIRのデータがダウンロードできます。ファイル名には規則性があります。
(北アメリカのARINのextendedではないフォーマットのデータが見つかりませんでした。)
地域 | 略 | FTP(最新IPアドレスデータ) |
---|---|---|
北アメリカ | ARIN | https://ftp.apnic.net/stats/arin/delegated-arin-extended-latest |
ヨーロッパ、 中東 、中央アジア | RIPE NCC | https://ftp.apnic.net/stats/ripe-ncc/delegated-ripencc-latest |
アジア・太平洋地域 | APNIC | https://ftp.apnic.net/stats/apnic/delegated-apnic-latest |
南アメリカ とカリブ海地域 | LACNIC | https://ftp.apnic.net/stats/lacnic/delegated-lacnic-latest |
アフリカ | AfriNIC | https://ftp.apnic.net/stats/afrinic/delegated-afrinic-latest |
crulなどでダウンロードしファイルサイズを見てみると下のようになります。
curl \
-O https://ftp.apnic.net/stats/arin/delegated-arin-extended-latest \
-O https://ftp.apnic.net/stats/ripe-ncc/delegated-ripencc-latest \
-O https://ftp.apnic.net/stats/apnic/delegated-apnic-latest \
-O https://ftp.apnic.net/stats/lacnic/delegated-lacnic-latest \
-O https://ftp.apnic.net/stats/afrinic/delegated-afrinic-latest
ls -lh
total 52608
-rw-r--r-- 1 u staff 388K 12 11 11:59 delegated-afrinic-latest
-rw-r--r-- 1 u staff 3.5M 12 11 11:59 delegated-apnic-latest
-rw-r--r-- 1 u staff 11M 12 11 11:59 delegated-arin-extended-latest
-rw-r--r-- 1 u staff 2.0M 12 11 11:59 delegated-lacnic-latest
-rw-r--r-- 1 u staff 7.2M 12 11 11:59 delegated-ripencc-latest
ファイルのフォーマット
ファイルのフォーマットは|で区切られたCSVで以下の通りです。
registry|cc|type|start|value|date|status
grep ipv4 delegated-apnic-latest | tail -10
apnic|KR|ipv4|223.255.208.0|4096|20100802|allocated
apnic|ID|ipv4|223.255.224.0|2048|20100809|allocated
apnic|AU|ipv4|223.255.232.0|1024|20100812|allocated
apnic|CN|ipv4|223.255.236.0|1024|20110311|allocated
apnic|HK|ipv4|223.255.240.0|1024|20100803|allocated
apnic|IN|ipv4|223.255.244.0|1024|20100804|allocated
apnic|HK|ipv4|223.255.248.0|1024|20151105|allocated
apnic|CN|ipv4|223.255.252.0|512|20110414|allocated
apnic|SG|ipv4|223.255.254.0|256|20110408|assigned
apnic|AU|ipv4|223.255.255.0|256|20110811|assigned
項目 | 例 | 意味 |
---|---|---|
registry | apnic | 地域インターネットレジストリ(RIR) |
cc | JP | ISO 3166の国コード |
type | ipv4 | ipv4, ipv6, asnのどれかが入ります |
start | 223.252.112.0 | 開始のIPアドレス(ネットワークアドレス) |
value | 4096 | IPアドレスの個数 |
date | 20100727 | 割り当てた年月日(YYYMMDD形式) |
status | allocated | allocated, assignedのどちらかのステータス |
extensions | A918B936 | extendedフォーマットのみ |
ここまでの説明のように各国に割り振られたIPアドレスはこのように公開されているので、それを使い自前で構築することもできます。詳しくは下記の記事をご覧ください。
GeoLite2にサインアップ
前置きが長くなりましたが、GeoLite2を利用するためにまずはアカウント登録が必要になります。下記のURLからアカウント登録します。
様々なサービス登録のためのEメールアドレスはMacの「メールを非公開」を使うと便利ですね。「メールを非公開」機能とは一意のランダムなメールアドレスを生成して管理できます。
GeoIPデータベースをダウンロードする
APIでアクセスする方法もありますが、今回はローカルにデータベースをダウンロードして使います。サイトにログインし、サイドバーのメニュー[Download Files]をクリックします。今回は国を確認したいので「GeoLite2 Country」のGZIPをダウンロードすれば良いのですが、「GeoLite2 City」でも取得できる情報を確認したいので両方ダウンロードしました。
なお、ダウンロードすると使用許諾契約に同意したことになりますのであらかじめ目を通しておきましょう。MaxMind End User License Agreement
データにはデータベース(MMDB)形式とCSV形式があり、GZIPでダウンロードするとMMDB形式のデータベースがダウンロードできます。今回は効率的に検索したいのでMMDB形式をダウンロードします。ちなみにMMDB形式とはMaxMindのMM、DataBaseのDBの略です。
「GeoLite2 Country」のダウンロードされたtar.gzを展開すると下記のファイルが入っています。GeoLite2-Country.mmdbのファイルサイズは約5.4MBです。
GeoLite2 Country
ls -lh
total 11048
-rw-r--r--@ 1 u staff 55B 12 9 07:43 COPYRIGHT.txt
-rw-r--r--@ 1 u staff 5.4M 12 9 07:43 GeoLite2-Country.mmdb
-rw-r--r--@ 1 u staff 398B 12 9 07:43 LICENSE.txt
「GeoLite2 City」のダウンロードされたtar.gzを展開すると下記のファイルが入っています。GeoLite2-City.mmdbのファイルサイズは約65MBです。
GeoLite2 City
ls -lh
total 132384
-rw-r--r--@ 1 u staff 55B 12 9 07:43 COPYRIGHT.txt
-rw-r--r--@ 1 u staff 65M 12 9 07:43 GeoLite2-City.mmdb
-rw-r--r--@ 1 u staff 398B 12 9 07:43 LICENSE.txt
-rw-r--r--@ 1 u staff 116B 12 9 07:43 README.txt
GeoLite2をPythonで使ってみる
ダウンロードした「GeoLite2 Country」や「GeoLite2 City」をローカル環境で使って、IPアドレスから国を確認してみます。
GitHub – maxmind/GeoIP2-python: Python code for GeoIP2 webservice client and database reader
GitHubpipでgeoip2モジュールをインストール
Pythonから簡単に操作できるようになるgeoip2モジュールをインストールします。
下記のコマンドでpipでgeoip2モジュールをインストールします。
pip install geoip2
GeoLite2 Cityを試してみる
まずは「GeoLite2 City」のMMDB(MaxMindのMM、DataBaseのDBの略)を使ってみます。調べるIPアドレスにはGoogle Public DNSにしてみます。
3行目には「GeoLite2 City」のMMDBのPATHを、4行目には調べたいIPアドレスを設定します。
import geoip2.database
db_path = '/path/to/GeoLite2-City.mmdb'
ip = '8.8.8.8'
with geoip2.database.Reader(db_path) as reader:
response = reader.city(ip)
print("country.iso_code:", response.country.iso_code)
print("country.name:", response.country.name)
print("subdivisions.most_specific.name:", response.subdivisions.most_specific.name)
print("subdivisions.most_specific.iso_code:", response.subdivisions.most_specific.iso_code)
print("city.name:", response.city.name)
print("postal.code:", response.postal.code)
print("location.latitude:", response.location.latitude)
print("location.longitude:", response.location.longitude)
print("traits.network:", response.traits.network)
実行すると下のように表示されます。
python ./geoLite2_city.py
country.iso_code: US
country.name: United States
subdivisions.most_specific.name: None
subdivisions.most_specific.iso_code: None
city.name: None
postal.code: None
location.latitude: 37.751
location.longitude: -97.822
traits.network: 8.8.0.0/19
この例では値がないNoneも多いですが、自分のグローバルIPで試したところ詳細に確認することができました。
GeoLite2 Countryを試してみる
次に「GeoLite2 Country」でやってみます。
3行目にはMMDBのPATHを「GeoLite2 Country」のPATHにし、7行目のreader.cityメソッドをreader.countryメソッドに置き換えます。
import geoip2.database
db_path = '/path/to/GeoLite2-Country.mmdb'
ip = '8.8.8.8'
with geoip2.database.Reader(db_path) as reader:
response = reader.country(ip)
print("country.iso_code:", response.country.iso_code)
print("country.name:", response.country.name)
# print("subdivisions.most_specific.name:", response.subdivisions.most_specific.name)
# print("subdivisions.most_specific.iso_code:", response.subdivisions.most_specific.iso_code)
# print("city.name:", response.city.name)
# print("postal.code:", response.postal.code)
# print("location.latitude:", response.location.latitude)
# print("location.longitude:", response.location.longitude)
print("traits.network:", response.traits.network)
reader.countryにはないメソッドはコメントアウトしました。
実行すると下のように表示されます。
python ./geoLite2_country.py
country.iso_code: US
country.name: United States
traits.network: 8.8.0.0/15
今回はIPアドレスから国を確認したいので「GeoLite2 Country」で十分です。
引数に複数のIPアドレスを指定できるようにする
sys.argvを使い引数に複数のIPアドレスを指定できるようにしてみます。
import geoip2.database
import sys
db_path = '/path/to/GeoLite2-Country.mmdb'
ips = sys.argv[1:]
with geoip2.database.Reader(db_path) as reader:
for ip in ips:
response = reader.country(ip)
print(ip, end=",")
print(response.country.iso_code, end=",")
print(response.country.name, end=",")
print(response.traits.network)
実行すると下のように表示されます。
IPアドレス, 国コード, 国名, CIDRの順番で出力しています。
python geoLite2_country_argv.py 8.8.8.8 8.8.4.4
8.8.8.8,US,United States,8.8.0.0/15
8.8.4.4,US,United States,8.8.0.0/15
ApacheのログからIPアドレスから国を確認してみる
catでログを指定しcutで1番目のフィールド(IPアドレス)を抜き出し、xargsで先程のプログラムに引数として与えています。様々な応用ができると思います。
cat <LOG> | cut -d ' ' -f 1 | xargs -L 1 python <PATH_to_geoLite2_country_argv.py>
データベースのアップデート(geoipupdate)
MMDB(MaxMindのMM、DataBaseのDBの略)をアップデートするコマンド(geoipupdate)も用意されています。MacではBrewでインストールできます。早速やってみましょう。
geoipupdateコマンドをインストールする
brew install geoipupdate
which geoipupdate
/opt/homebrew/bin/geoipupdate
GeoIP.confで設定する
設定ファイルは/opt/homebrew/etc/GeoIP.confです。最低限必要な設定をします。
vi /opt/homebrew/etc/GeoIP.conf
GeoIP.confの8行目にアカウントID、9行目にライセンスキー、18行目にMMDDがあるディレクトリを指定します。
8行目:AccountID YOUR_ACCOUNT_ID_HERE
9行目:LicenseKey YOUR_LICENSE_KEY_HERE
18行目:DatabaseDirectory /opt/homebrew/var/GeoIP
アカウントIDはログイン後に右上の[My Account]のプルダウンで確認できます。またライセンスキーは下のURLから確認できます。
https://www.maxmind.com/en/accounts/current/license-key
また、下のURLからGeoIP.confのサンプル使うこともできます。アカウントIDが既に入力されている状態です。
https://www.maxmind.com/en/accounts/current/license-key/GeoIP.conf
geoipupdateでアップデートする
-vをつけてgeoipupdateコマンドでアップデートしてみましょう。
geoipupdate -v
最後に
最後まで読んでいただきありがとうございます。今回の【Python】GeoLite2でIPアドレスから国を確認するはいかがでしたでしょうか。無料のGeoLite2を使ってPythonでIPアドレスから国を確認する方法を紹介しました。凄い勢いでアタックをするIPアドレスをgrepしてxargsで今回のプログラムに引数で渡すとdenyできて良いと思います。
MacやLinux、Pythonなど技術系のkindle本も豊富にあります。詳しくはこちらから。
Amazon unlimited:3ヶ月無料体験(10/20 23:59まで)→ 詳しくはこちら
Amazonの電子書籍読み放題サービス「Kindle Unlimited」でプライム会員を対象に、最初の3か月間を無料体験できるキャンペーンを実施中。マンガ、小説、ビジネス書、雑誌など500万冊から、好きな本を何冊でも読めるキャンペーンです。
初めてkindle unlimited 読み放題をご利用の方は30日間の無料で体験できます。
期間終了後は月額980円で、いつでもキャンセルできます。
200万冊以上が読み放題。お好きな端末で利用可能です。