Batfish を使ってネットワーク構成を可視化してみよう (1)

## はじめに

### 元ネタ

[inet\-henge 利用例: Batfish ネットワークトポロジーの可視化 \- LGTM](https://codeout.hatenablog.com/entry/2019/02/04/142027) です。今回および一連の記事 ((3)まである予定) では、batfish + inet-henge の記事に対する私なりのアプローチ……みたいな話をしたいなーと思っています。

このあと説明する中でやっていることは同じで、「可視化」するのに自分がいま作っている  [netoviz: RFC8345\-based Network Topology Visualizer](https://github.com/corestate55/netoviz) というツールを使っているところが異なる点ですね。ざっと内容見てもらえるようにデモ動画を作ってみたので一回これ見てもらえると良いかと。以降の解説もこのデモ動画に沿った流れにしてあります。

<!-- youtube はる -->
<iframe width="560" height="315" src="https://www.youtube.com/embed/YKKWg7Ap6H8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

同じこと:

* Batfish を使って NW 機器コンフィグからトポロジ情報を取り出す
* 取り出したデータを使って「ネットワーク図」(ネットワークトポロジ) を描画する

違うこと:

* プロトコルごとの隣接関係をもとに複数のネットワーク図(レイヤ)をつくる: RFC8345
  * Batfish を使って取り出すトポロジ情報を増やす: プロトコルごとのトポロジ情報を取り出す

* レイヤごとの依存関係を定義する
* レイヤ間の関係性を含めたネットワーク図の見せ方を提示する

という感じかな。ノード間の隣接関係だけではなくて、見方に応じた「ネットワークの構成」の可視化をしよう、プロトコルや上位構造の関係なんかを含めてどうにかモデル化しよう、という試みです。なお、デモ動画で使ったツールとデータは [Heroku 上にデプロイしてある](https://netoviz.herokuapp.com/) ので実際に触ってみることができます。

### 課題感

簡単に言うと、ネットワークの設計・構築・運用では図を読み書きすることは重要な要素なのに、図の読み書きをどうしても人がやらないといけなくて、そこがボトルネックになっているのではないか、ということです。

設計で図を書いて、図をレビューして、図と設計書を突き合わせて整合性をチェックして、図を見てパラメータやコンフィグを起こして、修正箇所を図に反映して……。図に対する Read/Write の処理は全部人がやってる。そして「ネットワーク構成図」をどう作るかが「お絵描き職人」みたいな人に頼りがちだったり、論理物理あるいは断片的に分かれた図を脳内マッピングしながらオペレーションを組み立てるのに知識や習熟が必要だったり、全体の造りが見えなくてどこで何が起きているのかわからなかったり……、いろんな課題がある。

<!-- ![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/9037a364-3d72-47dc-1633-af37765731df.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/9037a364-3d72-47dc-1633-af37765731df.png" width="90%">

「ネットワーク構成図」のためのデータを上手く作って、機械と人とのやりとりをトポロジ(図)データを中心にやれるともっといろいろ楽になることがあるのではなかろうか、ということを考えています。

で、今回はデータソースとしての batfish とそこで取れる構成情報(特に隣接関係 = トポロジ)の可視化の話をします。

## Batfish によるデータの抽出とトポロジデータの組み立て

[inet\-henge 利用例: Batfish ネットワークトポロジーの可視化 \- LGTM](https://codeout.hatenablog.com/entry/2019/02/04/142027) との対比、っていう観点でも見てみたいので、Batfish のチュートリアルのデータ(Config)をそのまま使っています。

* [pybatfish/jupyter\_notebooks/networks/example at master · batfish/pybatfish · GitHub](https://github.com/batfish/pybatfish/tree/master/jupyter_notebooks/networks/example)

あとは [Batfish](https://www.batfish.org/) にこの config を食わせてデータを取り出す……んですが、今回はまず可視化の話をやりたいので、あとの記事で解説します。(エントリが長くなりすぎるので分割します。)

## 階層のあるネットワークの可視化について

[RFC8345](https://tools.ietf.org/html/rfc8345), [RFC8346](https://tools.ietf.org/html/rfc8346) っていうのがあるんですが、それについては  [「ネットワーク図」のモデル化とモデルを起点にした自動化の可能性 \- Speaker Deck](https://speakerdeck.com/corestate55/onic2018) を参照してください。(とってもこの資料も RFC8345 の話をそんなに細かく解説しているわけではないけど。) 要は、ネットワークのトポロジをどういうデータモデルで表現するか、という RFC です。ノード間の隣接関係をトポロジとして表現するんですが、複数の階層(レイヤ)をつくって、レイヤ間のノードやリンクの関係性を指定できる、というのが含まれています。
左側のクラス図は  [draft\-medved\-i2rs\-topology\-im\-01 \- An Information Model for Network Topologies](https://datatracker.ietf.org/doc/draft-medved-i2rs-topology-im/) からの抜粋です。まずお見せするのは、この構造のデータを右側の形でひとつの階層ごとに図示するやり方です。

![a1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/85ff3a9d-ff72-4ffd-5c8e-ee7314c11120.png)

今回のポイントは、その「階層間の関係性」というところをどう表現するか、ですね。デモ動画にあるとおり、Batfish を使って 5つのネットワークトポロジ情報を取り出しています。

* BGP (AS)
* BGP Process (BGP neighbor)
* OSPF (Area)
* OSPF Process (OSPF neighbor)
* L3

[inet-henge の記事](https://codeout.hatenablog.com/entry/2019/02/04/142027)では BGP AS と L3 Topology のデータを中心にトポロジを描画しています。シンプルなデータでグルーピングを含めていい感じにトポロジを描いてくれる(自動レイアウト)のが便利ですよね inet-henge...

今回は BGP に加えて OSPF の情報を入れ、各プロトコルのプロセスどうしの隣接関係 (neighbor) を含めて図を描きます。以降、[チュートリアルで用意されている元 NW 図](https://github.com/batfish/pybatfish/blob/master/jupyter_notebooks/networks/example/example-network.png) を見ながら対比しながら見るのがよいと思います。

<!-- ![example-network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/93baa1be-3151-893a-0bfd-f0ebdd4dcec8.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/93baa1be-3151-893a-0bfd-f0ebdd4dcec8.png" width="75%">
https://github.com/batfish/pybatfish/blob/master/jupyter_notebooks/networks/example/example-network.png

## レイヤ単品で隣接関係(トポロジ)を見てみる

トポロジデータの中身に何があるのかわからないとどうにもならないので、ひとつずつ見ていきましょう。

### BGP AS

AS をノードに、AS 間をつなぐインタフェース (RFC 的には termination point, TP) は border router のインタフェースの IP を持ってきて入れています。素直に batfish からデータを取り出すと private AS (AS2 内部, 元図では AS2 の内側、as2dept1 とhost1/2 を囲む四角形で表現) の区別が特にないのでこういう形でデータ化してあります。

<!-- ![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/164cb308-5973-162d-dcc1-0ea22ae2b8d1.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/164cb308-5973-162d-dcc1-0ea22ae2b8d1.png" width="40%">

### BGP Process

BGP neighbor の情報を中心にトポロジを組んであります。BGP Process をノードにするんですが、Router IDをノード名にしてあります。Batfish はすごくて、コンフィグをもとに各ノードが持つルーティングテーブルの情報なんかも出せるんですよね。なので、BGP/OSPF Process に対しては、それぞれのプロトコルで取得されるであろう経路情報を埋め込んで [^rfc8346] あります。

[^rfc8346]: この L3 経路情報など L3 のノード用の attribute を追加するデータモデル拡張が RFC8346 の内容。

<!-- ![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/6802e1f3-b6b8-d1d2-d82f-077f33f4c56d.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/6802e1f3-b6b8-d1d2-d82f-077f33f4c56d.png" width="70%">

### OSPF Area

ここは省略。というのも AS 内シングルエリアなので特に何もないので。
(これは トポロジ図としてみると何もないっていうだけで、依存関係の定義としては意味があります。)

### OSPF Process

OSPF Process も AS ごとのクラスタ (Area) が 3 つ出てくる形なので代表して AS2 のものをピックアップ。(ここでは [D3.js の force layout]( https://github.com/d3/d3-force) というのを使ってるんですが、リンクがないとお互いの斥力で吹っ飛んでしまう……。) AS2 の OSPF Speaker 間の関係が取れてるのが分かると思います。ノードは OSPF プロセス…ですが 1-router:1-process だったということもありノード名そのままになってます。

<!-- ![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/d97a495a-1325-29b3-e85c-1e57b0377f4b.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/d97a495a-1325-29b3-e85c-1e57b0377f4b.png" width="70%">

### Layer3

Layer 3 トポロジとして出てくるのが元のNW図ですね。(というのは、もともとの NW が VLAN のない L3 構成になっているため。) これは、素直にルータごとの接続関係です。また、connected/local な経路を載せています。

<!-- ![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/3b530dd8-cb0a-856e-25ec-775ed1cf63b6.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/3b530dd8-cb0a-856e-25ec-775ed1cf63b6.png" width="90%">

## 補足: NWトポロジにおける「レイアウト」の課題

このあたりを見ていくと、トポロジの自動レイアウトの難点というか、inet-henge が「NW 構成図 / NWトポロジとして見やすいレイアウト」を課題感にしている理由が何となく見えてくるんじゃないかと思います。一般的なライブラリによる NW トポロジのレイアウトってどうしても普段仕事で書くような NW 構成図にはならないんですよね。NW 構成図では通常、ノードが配置される「位置」にも意味があります。今回の元の NW 図でも、 border/core/distribution などの役割を位置(行/列)で表現しています。そのほか NW 図では active/standby, 1系/2系などの冗長系列や、上流下流などの方向性、システムや拠点などのグルーピングなど、「どこに配置してあるか」に意味を持たせてあります。でも、一般的なグラフ描画ライブラリはこうした "ネットワーク図固有の事情" を加味しないので、位置に意味は無い [^graph] んですよね。

[^graph]: グラフ理論的な文脈では、ノードの位置などの見た目の情報は無視して、隣接関係などグラフの普遍的な性質の話をするので当たり前の話ではありますが。

## レイヤ間の関係だけ取り出してみる

### 上のレイヤから

上の図だけだと、1 枚ずつプロトコル別に NW 図を描いてみた、というだけで終わってしまいます。が、実際にはそのデータの中に、あるプロトコル(レイヤ)のこのノードは、別なレイヤのあののノードに依存しているんだ、みたいな階層間の関係性が定義してあるのでそこを見てみましょう。階層内のノード隣接関係をいったん無視して、階層間の関係だけ取り出してみます。(元データは同じで、可視化の方法が違うだけ、という点に注意。)

<!-- ![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/2e1f5c97-5d61-216b-94c2-897180092bfb.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/2e1f5c97-5d61-216b-94c2-897180092bfb.png" width="70%">

上の図は、一番上、AS1 を指定して、その下にあるもの(子)を再帰的に探索している図です。単純に AS1 に含まれる BGP/OSPF process, それらが載っているルータをたどっていくイメージですね。

### 下のレイヤから

<!-- ![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/aa12dff1-1c07-b4d7-8e96-0d5eea86fc18.png) -->
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154230/aa12dff1-1c07-b4d7-8e96-0d5eea86fc18.png" width="70%">

次は逆に、一番下 Layer3/as1border1 を起点にしてその上(親)をたどっています。こうしてみると、あるルータに乗っている routing process, それらがどの AS/Area に属しているか、というのを順にみている……あるルータの config を読みながら、全体のどこに属するものなのかを考えるようなイメージになります。

RFC8345 では、ノード/リンク/Term point それぞれについて、別の階層にあるノード/リンク/TP との関係を定義できるようになっています。このビューでは、指定したオブジェクトのレイヤ間の関係性を、上下(親子)それぞれ探索して、どこと関係があるのかを可視化しています。

## 隣接関係(トポロジ)と階層間関係を合成してみる

……という話が本題なんですが、いったんここまでで切って[次回に回そう](https://qiita.com/corestate55/items/9d8023eb19637f9bbd1e)と思います。

## まとめ / 次回

ここまでで、階層を持ったネットワークトポロジを定義できること、各階層はどんなトポロジになっているのか、階層間にはどんな関係があるのか、というのをそれぞれのカット(ビュー)で可視化してみました。ですが、これが見やすいか、これを見て仕事ができるか、という話になるとまた別なんですよね。目標は、実際に業務に使えるレベルの図を作る(可視化する)ことで、途中レイアウトに関する補足とかを入れたのはその伏線だったりします。が、一度に全部出すとちょっとボリュームが多いので、[「見せ方」に関しのメイントピックを次回に回します](https://qiita.com/corestate55/items/9d8023eb19637f9bbd1e)。