スポンサーリンク

docker-composeで動かしたBatfishをpybatfishから使う

aws
この記事は約26分で読めます。

はじめに

Batfishというossのネットワーク構成分析ツールがあるのを知ったので使ってみました。

 

今回はbatfish/allinoneに入っているpybatfishを使い、自分が用意したciscoルータのconfigを分析(と言ってもIPアドレス抽出とかですが)してみたいと思います。

pybatfishをGUIで見れるJupyter Notebookは次回使います。今回はまったく使いません。

 

ciscoルータのconfigはCisco Packet Tracerで作ってみました。このシュミレーター、便利すぎてやばいと言う言葉しか出て来ませんでした。CCNAどころかCCNPくらいまでは使えるんじゃないかな?欠点はter len 0が使えないくらいかな。

 

参考サイト

Batfishに詳しい日本語のサイト。Batfishって何?という方はこちらのサイトがおすすめ。

 

公式のPybatfishのGetting started

 

quesions一覧。ここを見て色々作っていく感じ。

 

quesions一覧日本語版。参考になりました。

 

Cisco Packet Tracer ダウンロードの方法

 

Cisco Packet Tracerの使い方全般。

 

使ったconfig

適当なネットワークを組んでみました。構成図はdraw.io使ってます。
※さくっと作ったので構成に関する細かい突っ込みは勘弁してください。。

 

 

各種configはこんな感じです。SWは何も設定してないので割愛。

Router0.cfg

version 15.1
service timestamps log datetime msec
service timestamps debug datetime msec
no service password-encryption
!
hostname Router0
!
!
!
!
!
!
!
!
ip cef
no ipv6 cef
!
!
!
!
license udi pid CISCO1941/K9 sn FTX1524HJ26-
!
!
!
!
!
!
!
!
!
no ip domain-lookup
!
!
spanning-tree mode pvst
!
!
!
!
!
!
interface GigabitEthernet0/0
 ip address 10.10.10.1 255.255.255.0
 duplex auto
 speed auto
!
interface GigabitEthernet0/1
 ip address 192.168.100.253 255.255.255.0
 duplex auto
 speed auto
 standby 100 ip 192.168.100.254
 standby 100 preempt
!
interface Vlan1
 no ip address
 shutdown
!
router eigrp 1
 network 10.10.10.1 0.0.0.0
 network 192.168.100.253 0.0.0.0
 
!
ip classless
!
ip flow-export version 9
!
!
!
!
!
!
!
!
line con 0
!
line aux 0
!
line vty 0 4
 login
!
!
!
end

 

Router1.cfg

version 15.1
service timestamps log datetime msec
service timestamps debug datetime msec
no service password-encryption
!
hostname Router1
!
!
!
!
!
!
!
!
ip cef
no ipv6 cef
!
!
!
!
license udi pid CISCO1941/K9 sn FTX152497F5-
!
!
!
!
!
!
!
!
!
no ip domain-lookup
!
!
spanning-tree mode pvst
!
!
!
!
!
!
interface GigabitEthernet0/0
 ip address 20.20.20.1 255.255.255.0
 duplex auto
 speed auto
!
interface GigabitEthernet0/1
 ip address 192.168.100.252 255.255.255.0
 duplex auto
 speed auto
 standby 100 ip 192.168.100.254
 standby 100 priority 95
!
interface Vlan1
 no ip address
 shutdown
!
router eigrp 1
 network 192.168.100.252 0.0.0.0
 network 20.20.20.1 0.0.0.0
 
!
ip classless
!
ip flow-export version 9
!
!
!
!
!
!
!
!
line con 0
!
line aux 0
!
line vty 0 4
 login
!
!
!
end

 

Router2.cfg

version 15.1
service timestamps log datetime msec
service timestamps debug datetime msec
no service password-encryption
!
hostname Router2
!
!
!
!
!
!
!
!
ip cef
no ipv6 cef
!
!
!
!
license udi pid CISCO1941/K9 sn FTX15240M0A-
!
!
!
!
!
!
!
!
!
no ip domain-lookup
!
!
spanning-tree mode pvst
!
!
!
!
!
!
interface GigabitEthernet0/0
 ip address 10.10.10.254 255.255.255.0
 duplex auto
 speed auto
!
interface GigabitEthernet0/1
 ip address 192.168.200.253 255.255.255.0
 duplex auto
 speed auto
 standby 200 ip 192.168.200.254
 standby 200 preempt
!
interface Vlan1
 no ip address
 shutdown
!
router eigrp 1
 network 10.10.10.254 0.0.0.0
 network 192.168.200.253 0.0.0.0
 
!
ip classless
!
ip flow-export version 9
!
!
!
!
!
!
!
!
line con 0
!
line aux 0
!
line vty 0 4
 login
!
!
!
end

 

Router3.cfg

version 15.1
service timestamps log datetime msec
service timestamps debug datetime msec
no service password-encryption
!
hostname Router3
!
!
!
!
!
!
!
!
ip cef
no ipv6 cef
!
!
!
!
license udi pid CISCO1941/K9 sn FTX1524AY88-
!
!
!
!
!
!
!
!
!
no ip domain-lookup
!
!
spanning-tree mode pvst
!
!
!
!
!
!
interface GigabitEthernet0/0
 ip address 20.20.20.254 255.255.255.0
 duplex auto
 speed auto
!
interface GigabitEthernet0/1
 ip address 192.168.200.252 255.255.255.0
 duplex auto
 speed auto
 standby 200 ip 192.168.200.254
 standby 200 priority 95
!
interface Vlan1
 no ip address
 shutdown
!
router eigrp 1
 network 192.168.200.252 0.0.0.0
 network 20.20.20.254 0.0.0.0
 
!
ip classless
!
ip flow-export version 9
!
!
!
!
!
!
!
!
line con 0
!
line aux 0
!
line vty 0 4
 login
!
!
!
end

 

Batfishを動かすための構成

AWSのEC2でubuntu18.04を使いました。

構成

ubuntu@MyEC2 ~/batfish % tree -a --charset=C
.
|-- docker-compose.yaml
`-- mynet
    `-- configs
        |-- Router0.cfg
        |-- Router1.cfg
        |-- Router2.cfg
        `-- Router3.cfg

2 directories, 5 files

 

docker-compose.yaml

ちなみにdockerは18.09.8 docker-composeは1.24.1を使用してます。

version: "3.7"
services:
  batfish:
    image: batfish/allinone:latest
    container_name: batfish
    volumes:
      - ./mynet:/notebooks/mynetworks
    network_mode: host

docker-composeのversionが古いとversion3.7は動かないかも。version3.0とかでも普通に動くとは思います。

batfishのallinoneの方を使います。pybatfishも入っているのでコンテナ内に入ればそのままpybatfishが使えます。Jupyter Notebookも入っていますが今回は使いません。次回さわります。

mynet配下に自分で用意したconfigをdockerコンテナ内の/notebooks/mynetworksに配置してます。

 

コンテナ起動&pybatfishの実行

各ファイル、ディレクトリを用意したら以下コマンドでdockerを起動します。

docker-compose up -d

※停止はdocker-compose down

 

続いてコンテナ内でpythonの実行します。

docker exec -it batfish python3

※終了はCtrl + D

 

ここから公式のGetting startedの通りに実行します。

まずpybatfishのimport。

from pybatfish.client.commands import *

from pybatfish.question.question import load_questions, list_questions

from pybatfish.question import bfq

 

question読み込み。

load_questions()

 

volumesで指定したmynetを/notebooks/mynetworks/としてsnapshotの取得

bf_init_snapshot(‘/notebooks/mynetworks/’)

以下ここまでのlog

ubuntu@MyEC2 ~/batfish % docker exec -it batfish python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from pybatfish.client.commands import *
>>>
>>> from pybatfish.question.question import load_questions, list_questions
>>>
>>> from pybatfish.question import bfq
>>>
>>> load_questions()
Successfully loaded 63 questions from remote
>>>
>>> bf_init_snapshot('/notebooks/mynetworks/')
status: TRYINGTOASSIGN
.... no task information
status: TRYINGTOASSIGN
.... no task information
status: CHECKINGSTATUS
.... no task information
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: ASSIGNED
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: ASSIGNED
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4.
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:05 elapsed)
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:06 elapsed)
status: ASSIGNED
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:07 elapsed)
status: ASSIGNED
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:08 elapsed)
status: ASSIGNED
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:09 elapsed)
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Parse network configs 0 / 4. (00:00:10 elapsed)
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Reading, unpacking, and deserializing files containing 'org.batfish.datamodel.GenericConfigObject' instances 4 / 4. (00:00:11 elapsed)
status: CHECKINGSTATUS
.... Wed Aug 14 15:31:38 2019 UTC Deserializing objects of type 'org.batfish.datamodel.Configuration' from files 4 / 4. (00:00:12 elapsed)
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:31:38 2019 UTC Deserializing objects of type 'org.batfish.datamodel.Configuration' from files 4 / 4. (00:00:13 elapsed)
Default snapshot is now set to ss_5b37207b-618c-4966-9003-262e26c7cc45
status: UNASSIGNED
.... no task information
status: CHECKINGSTATUS
.... no task information
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:31:51 2019 UTC Begin job.
'ss_5b37207b-618c-4966-9003-262e26c7cc45'
>>>

ここまででお膳立て終了。実際に動かす面白いところはここから。

各configのIFにあるIPアドレスを取得します。

ip_owners_ans = bfq.ipOwners().answer()

ip_owners_ans.frame()

>>> ip_owners_ans = bfq.ipOwners().answer()
status: TRYINGTOASSIGN
.... no task information
status: CHECKINGSTATUS
.... no task information
status: ASSIGNED
.... Wed Aug 14 15:32:43 2019 UTC Begin job.
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:32:43 2019 UTC Begin job.
>>>
>>> ip_owners_ans.frame()
      Node      VRF           Interface               IP Mask Active
0  router0  default  GigabitEthernet0/0       10.10.10.1   24   True
1  router1  default  GigabitEthernet0/1  192.168.100.252   24   True
2  router3  default  GigabitEthernet0/1  192.168.200.252   24   True
3  router2  default  GigabitEthernet0/1  192.168.200.253   24   True
4  router0  default  GigabitEthernet0/1  192.168.100.253   24   True
5  router1  default  GigabitEthernet0/0       20.20.20.1   24   True
6  router3  default  GigabitEthernet0/0     20.20.20.254   24   True
7  router2  default  GigabitEthernet0/0     10.10.10.254   24   True
>>>

.head()つけると上から5行表示するみたい。確認用かな?とりあえずパス。

 

router0のGigabitEthernet0/0の情報を取得。

iface_ans = bfq.interfaceProperties(nodes=’router0′, interfaces=’GigabitEthernet0/0′, properties=’all_prefixes’).answer()

iface_ans.frame()

>>> iface_ans = bfq.interfaceProperties(nodes='router0', interfaces='GigabitEthernet0/0', properties='all_prefixes').answer()
status: UNASSIGNED
.... no task information
status: ASSIGNED
.... no task information
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:33:20 2019 UTC Begin job.
>>>
>>>
>>> iface_ans.frame()
                     Interface       All_Prefixes
0  router0[GigabitEthernet0/0]  ['10.10.10.1/24']
>>>

これで動作確認完了。でももうちょっと遊んでみます。

 

Jupyter NotebookにあったGetting started with Batfish.ipynbより以下を拝借。全configのルーティングテーブルが出てくる・・・すごい・・・

routes_ans = bfq.routes().answer()

routes_ans.frame()

>>> routes_ans = bfq.routes().answer()
status: BLOCKED
.... no task information
status: BLOCKED
.... no task information
status: BLOCKED
.... no task information
status: BLOCKED
.... no task information
status: ASSIGNED
.... Wed Aug 14 15:34:57 2019 UTC Begin job.
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:34:57 2019 UTC Begin job.
>>>
>>> routes_ans.frame()
       Node      VRF             Network  ... Metric Admin_Distance   Tag
0   router0  default       20.20.20.0/24  ...   3072             90  None
1   router1  default  192.168.100.252/32  ...      0              0  None
2   router0  default    192.168.200.0/24  ...   3072             90  None
3   router2  default     10.10.10.254/32  ...      0              0  None
4   router2  default    192.168.100.0/24  ...   3072             90  None
5   router2  default       20.20.20.0/24  ...   3072             90  None
6   router0  default       10.10.10.1/32  ...      0              0  None
7   router0  default    192.168.100.0/24  ...      0              0  None
8   router3  default  192.168.200.252/32  ...      0              0  None
9   router3  default    192.168.100.0/24  ...   3072             90  None
10  router2  default  192.168.200.253/32  ...      0              0  None
11  router2  default       10.10.10.0/24  ...      0              0  None
12  router1  default       20.20.20.0/24  ...      0              0  None
13  router1  default       20.20.20.1/32  ...      0              0  None
14  router1  default       10.10.10.0/24  ...   3072             90  None
15  router1  default    192.168.100.0/24  ...      0              0  None
16  router3  default       20.20.20.0/24  ...      0              0  None
17  router0  default  192.168.100.253/32  ...      0              0  None
18  router3  default       10.10.10.0/24  ...   3072             90  None
19  router3  default    192.168.200.0/24  ...      0              0  None
20  router0  default       10.10.10.0/24  ...      0              0  None
21  router1  default    192.168.200.0/24  ...   3072             90  None
22  router2  default    192.168.200.0/24  ...      0              0  None
23  router3  default     20.20.20.254/32  ...      0              0  None

[24 rows x 10 columns]
>>>

 

node指定してみます。

routes_ans = bfq.routes(nodes=”router0″).answer()

routes_ans.frame()

>>> routes_ans = bfq.routes(nodes="router0").answer()
status: TRYINGTOASSIGN
.... no task information
status: ASSIGNED
.... Wed Aug 14 15:35:39 2019 UTC Begin job.
status: TERMINATEDNORMALLY
.... Wed Aug 14 15:35:39 2019 UTC Begin job.
>>>
>>> routes_ans.frame()
      Node      VRF             Network  ... Metric Admin_Distance   Tag
0  router0  default       20.20.20.0/24  ...   3072             90  None
1  router0  default    192.168.200.0/24  ...   3072             90  None
2  router0  default  192.168.100.253/32  ...      0              0  None
3  router0  default       10.10.10.1/32  ...      0              0  None
4  router0  default       10.10.10.0/24  ...      0              0  None
5  router0  default    192.168.100.0/24  ...      0              0  None

[6 rows x 10 columns]
>>>

一応router0のログだけPacker Tracerと見比べてみたけど同じでした。

Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP
       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
       E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP
       i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
       * - candidate default, U - per-user static route, o - ODR
       P - periodic downloaded static route

Gateway of last resort is not set

     10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C       10.10.10.0/24 is directly connected, GigabitEthernet0/0
L       10.10.10.1/32 is directly connected, GigabitEthernet0/0
     20.0.0.0/24 is subnetted, 1 subnets
D       20.20.20.0/24 [90/3072] via 192.168.100.252, 03:35:48, GigabitEthernet0/1
     192.168.100.0/24 is variably subnetted, 2 subnets, 2 masks
C       192.168.100.0/24 is directly connected, GigabitEthernet0/1
L       192.168.100.253/32 is directly connected, GigabitEthernet0/1
D    192.168.200.0/24 [90/3072] via 10.10.10.254, 03:36:19, GigabitEthernet0/0

Router0#

 

最後に

batfishとpybatfishを動かしてみました。

これは面白い!

次はjupyter notebookからpybatfishを動かしてみます。

 

タイトルとURLをコピーしました