GeoIP2のデータベースを手に入れたので遊んでみる



## 背景

IPアドレスというのはIANA (Internet Assigned Numbers Authority)でどうするか決められます。
まずは地域で細かく分けられ更にNIR (National Internet Registry)で地域ごとに別れます。
そこからISP (Internet Service Provider)が一般ユーザーや企業に対してIPアドレスを提供します。

IPアドレスを管理している団体によっては様々な情報が詰まっていて、それが集まっているのがMaxmindのデータベース、つまりGeoIP2のデータベースです。

```mermaid
graph TD
    A[IANA （Internet Assigned Numbers Authority）]
    A --> C1[ARIN （北米）]:::rir
    A --> C2[RIPE NCC （ヨーロッパ・中東・中央アジア）]:::rir
    A --> C3[APNIC （アジア太平洋）]:::rir
    A --> C4[LACNIC （ラテンアメリカ・カリブ海）]:::rir
    A --> C5[AFRINIC （アフリカ）]:::rir

    C3 --> E1[JPNIC （日本）]:::nir
    C3 --> E2[KRNIC （韓国）]:::nir
    C3 --> E3[TWNIC （台湾）]:::nir
    C3 --> E4[SGNIC （シンガポール）]:::nir
    C3 --> E5[IDNIC （インドネシア）]:::nir

    E1 --> F1[ISP （日本のISP例: NTT, KDDI）]:::isp
    F1 --> G1[個人ユーザー]:::ip
    F1 --> G2[企業・データセンター]:::ip

    E2 --> F2[ISP （韓国のISP例: KT, LGU+）]:::isp
    F2 --> G3[韓国の個人ユーザー]:::ip
    F2 --> G4[韓国の企業]:::ip

    E3 --> F3[ISP （台湾のISP例: 中華電信）]:::isp
    F3 --> G5[台湾の個人ユーザー]:::ip
    F3 --> G6[台湾の企業]:::ip


    NIR[NIR （National Internet Registry）]:::rir
    RIR[RIR （Regional Internet Registry）]:::nir
    ISP[ISP （Internet Service Provider）]:::isp
    IP[IP　（IP Address）]:::ip

    NIR --> RIR
    RIR --> ISP
    ISP --> IP
    
    classDef rir fill:#ffcccb,stroke:#000,stroke-width:2px;  
    classDef nir fill:#cce5ff,stroke:#000,stroke-width:2px;  
    classDef isp fill:#d4edda,stroke:#000,stroke-width:2px;  
    classDef ip fill:#ffeeba,stroke:#000,stroke-width:2px;  

```

今回はIPアドレスからデータベースの情報を抜き出してみるアプリを作ってみました。

https://geoip2-demo.onrender.com/

## 作ってみる
    
データベースは無料で入手できますが、登録が必要です。
まずは以下からサインアップしてください。

https://www.maxmind.com/en/geolite2/signup

メールアドレスにパスワード設定のメールが来るのでパスワードを設定します。

するとメニューからデータベースファイルがダウンロードできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/020abf7e-4b72-4da4-fa3a-241a95f96e2c.png)

使えるデータベースはこれだけありますが、

* GeoLite2 ASN
* GeoLite2 ASN: CSV Format
* GeoLite2 City
* GeoLite2 City: CSV Format
* GeoLite2 Country
* GeoLite2 Country: CSV Format

今回は以下の２つを解凍して、`GeoLite2-ASN.mmdb`と`GeoLite2-City.mmdb`を使います。
* GeoLite2 ASN
* GeoLite2 City

Pythonで作ると[geoipのデータベースのライブラリ](https://github.com/maxmind/GeoIP2-python)があるのでそれを使います。

```python
import geoip2.database
import gradio as gr
from fastapi import FastAPI

asn_db='./GeoLite2-ASN.mmdb'
city_db='./GeoLite2-City.mmdb'

def get_asn(ip_address:str):
  with geoip2.database.Reader(asn_db) as reader:
    return reader.asn(ip_address)

def get_city(ip_address:str):
  with geoip2.database.Reader(city_db) as reader:
    return reader.city(ip_address)


def main(ip_address):
  asn=get_asn(ip_address)
  city=get_city(ip_address)
  return {
  "AS管理組織":asn.autonomous_system_organization, 
  "大陸":city.continent.names['ja'],
  "国":city.country.names['ja'],  
  "緯度":city.location.latitude,
  "経度":city.location.longitude,
  "精度":city.location.accuracy_radius,
  "登録国":city.registered_country.names['ja'],
  "細分":list(map(lambda x:x.names['ja'] or x.names['en'],city.subdivisions)),
  "IPアドレス":city.traits.ip_address,
  }


app = FastAPI()

io = gr.Interface(fn=main, inputs="text", outputs="json")
app = gr.mount_gradio_app(app, io, path="/")

```

## 遊んでみる

### とりあえずGoogleを試してみる

まずはIPアドレスを出してから
 
```
nslookup  google.com
;; communications error to 127.0.0.53#53: timed out
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	google.com
Address: 142.251.222.46
Name:	google.com
Address: 2404:6800:4004:818::200e
```

返ってきたIPアドレスを両方入れてみると…？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/c0474c07-c73e-4779-80f3-63072de5cc63.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/febcd3fa-7139-80a5-4a79-d1ea9a287bdd.png)

どうやらIPv4とIPv6でサーバーが違うみたいですね
DRの観点からでしょうか

### AWSのアドレスで試してみる

東京(ap-northeast-1)リージョンのアドレス：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/79929f40-ee74-0f19-96c8-c1b4b6fe1cd0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/228f9b76-1524-ba96-054f-17b1d55d4e6d.png)

大阪(ap-northeast-3)リージョンのアドレス：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/baa2dbe9-92f9-07a5-2698-9723685b1f24.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230043/4fd9a093-7c26-79e6-bfaa-c0110e506eb9.png)

[AWSのデータセンターの場所というのはリークされている](https://qiita.com/saitotak/items/f56234d0506b47ddbcfe)とはいえ登録上は都庁や市役所の近くにあるのは興味深いですね


## おまけ
pythonanywhereでデプロイしようとしたらだめでした。
仕方なくrenderにデプロイ。