BGPフルルート情報を基にしてipv4-heatmapを塗る

# はじめに
ipv4-heatmap という IPv4 アドレス空間を可視化するツールがあります。
![20080301-s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31573/8a55568e-89c0-0bc8-b897-2b1f62cf184c.png)
図．http://maps.measurement-factory.com/ より引用

上記は2008年に作成された画像であるため、まだ Unallocated がある等、古い情報です。
ここでは、2019年版画像の作成を目的に、BGPフルルート情報を用いた ipv4-heatmap の使用方法についてまとめます。

# ipv4-heatmap のインストール
https://github.com/measurement-factory/ipv4-heatmap

## 1. Build
```
git clone https://github.com/measurement-factory/ipv4-heatmap.git
cd ipv4-heatmap
make
```
ビルドにはGDが必要です。

## 2. Label の更新
`Net::CIDR::Lite` と `XML::Simple` が必要になります。適宜インストールしてください。

```
cd labels/iana
wget -O ipv4-address-space https://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xml
perl grok.pl < ipv4-address-space > iana-labels.txt
```

`iana-labels.txt` の生成後に下記のコマンドを実行すると、アドレスブロックの割当組織を一覧できる画像が作成できます。

```
../../ipv4-heatmap -a iana-labels.txt  < /dev/null
```

![map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31573/0009659b-42e2-cb34-3eff-d95e5bfd0824.png)
図．アドレスブロック割当組織図

# BGP フルルート
ここでは、routeviews.org で公開されている、MRT形式のBGPフルルート情報を利用します。
さらに、ipv4-heatmapに読み込ませるために、MRTをテキスト形式に変換します。

## 1. ダウンロード
http://archive.routeviews.org/ から最新の rib.bz2 をダウンロードし、展開してください。(MRT format RIBs and UPDATEs from DIXIE (WIDE)など)

## 2. MRT から テキスト形式へ変換
ipv4-heatmap では shade というテキスト形式のファイルを読み込ませると、色を塗ることができます。

```:shadeファイル例
10.0.0.0/8      0x7F7FFF        64
172.16.0.0/12   0x7F7FFF        64
192.168.0.0/16  0x7F7FFF        64
```

MRTからshadeに変換するために、下記のプログラムを保存し、コマンドを実行してください。

```go:mrt-to-shade.go
package main

import (
        "fmt"
        "os"
        "strconv"
        "strings"

        "github.com/osrg/gobgp/pkg/packet/mrt"
        "gopkg.in/alecthomas/kingpin.v2"
)

var (
        filename = kingpin.Arg("filename", "mrt file path").Required().String()
        color    = []string{
                "fde725", "eae51a", "d5e21a", "c0df25", "a8db34", "93d741",
                "7fd34e", "6ccd5a", "58c765", "48c16e", "3aba76", "2eb37c",
                "25ab82", "20a386", "1e9c89", "1f948c", "228c8d", "25848e",
                "287d8e", "2b758e", "2e6d8e", "32658e", "365d8d", "3a548c",
                "3e4a89", "424186", "453882", "472e7c", "482374", "48186a",
                "470d60", "440154",
        }
)

func Run() int {
        // Reference: https://github.com/osrg/gobgp/blob/master/cmd/gobgp/mrt.go
        f, err := os.Open(*filename)
        if err != nil {
                fmt.Println(err)
                return 1
        }
        defer f.Close()

        for {
                buf := make([]byte, 12)
                _, err = f.Read(buf)
                if err != nil {
                        break
                }

                h := &mrt.MRTHeader{}
                err = h.DecodeFromBytes(buf)
                if err != nil {
                        fmt.Println(err)
                        return 1
                }

                buf = make([]byte, h.Len)
                _, err = f.Read(buf)
                if err != nil {
                        break
                }

                msg, err := mrt.ParseMRTBody(h, buf)
                if err != nil {
                        continue
                }

                if h.SubType == mrt.RIB_IPV4_UNICAST.ToUint16() {
                        rib := msg.Body.(*mrt.Rib)

                        s := strings.Split(rib.Prefix.String(), "/")
                        n, err := strconv.Atoi(s[1])
                        if err != nil {
                                continue
                        }

                        fmt.Printf("%s\t0x%s\t64\n", rib.Prefix, color[n - 1])
                } else {
                        continue
                }
        }

        return 0
}

func main() {
        kingpin.Version("0.0.1")
        kingpin.Parse()
        os.Exit(Run())
}
```

```:shade作成コマンド
go run mrt-to-shade.go rib.20191126.1200 > /tmp/rib.shade
```

## 3. heatmap 生成

```
../../ipv4-heatmap -a iana-labels.txt -s /tmp/rib.shade < /dev/null
```

![map-viridis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31573/79d260bc-5485-5981-969d-7c0df03b7d67.png)
図．2019年版heatmap

明るい(黄色)ところは大きいサブネット(/8など)で広報されていることを表していて、暗くなるにつれて細かくなっていきます。(viridisで色付け)
真っ黒はBGPで広報されていないネットワークです。

# おわりに
ipv4-heatmapとrouteviews.orgを利用して、BGP で広報されているアドレスの可視化をしました。