Batfishを使ったネットワーク設定情報の抽出と妥当性確認

# Batfishとは

Batfishとは、ネットワーク機器のConfigを分析し、セキュリティ、信頼性、コンプライアンス(設定が組織内の基準に従っているか)などの妥当性を確認してくれるツールです。
Configファイルを使って分析するため、"適用前"のConfigが本番環境に与える影響を評価することができます。

# 具体的に確認できること

#### (1) コンフィグレーションコンプライアンス
- 必要な設定が入っていなかったり、逆に不要な設定が入っていたりしないか(ACL、ルートマップ等)
- MTU、AAA、NTP、ロギング等のコンフィグ設定がテンプレートにマッチするか
- 対象機器がSSHv2のみでアクセスでき(Telnetが無効化され)、かつパスワードが設定されているか

#### (2) 信頼性
- 単一障害点の検出
- DNSなどのサービスがグローバルに到達できるか

#### (3) セキュリティ
- 高い機密性が求められるサービスに対し、必要最低限のサブネット/ホストのみからアクセスできる設定になっているか
- エンドポイント間の経路が想定通りか(例えば、ファイアウォールが少なくとも2つの等コストマルチパスを持っているか等)

#### (4) 変更分析
- エンド間の到達性が、現状と設定後で変わらないか
- 適用予定のACLもしくはファイアウォール設定変更がおそらく正しく、他のトラフィックへの影響がないか
- 異なるベンダーの2つのConfigが機能的に同じかどうか

# 対応ネットワーク機器/OS
2018年11月末時点で対応しているのは以下の通りです。

- Arista
- Aruba
- AWS (VPCs, Network ACLs, VPN GW, NAT GW, Internet GW, Security Groups, etc…)
- Cisco (All Cisco NX-OS, IOS, IOS-XE, IOS-XR and ASA devices)
- Dell Force10
- Foundry
- iptables (on hosts)
- Juniper (All JunOS platforms: MX, EX, QFX, SRX, T-series, PTX)
- MRV
- Palo Alto Networks
- Quagga / FRR
- Quanta
- VyOS

最新情報はこちらを参照願います。
https://github.com/batfish/batfish/blob/master/README.md#what-kinds-of-correctness-checks-does-batfish-support


これ以降の記事では、(1)のコンプライアンスについて、Pythonコードを交えてご紹介します。

# コンプライアンスチェック(1/2) - ネットワーク設定情報の抽出
まずは、Pybatfish(BatfishのPythonクライアント)のインポート、チェック対象Configの格納先指定と読み込みを行います。
ここでは`networks/branch`を指定していますが、configファイルは、配下に作成したconfigsディレクトリ中に格納する必要があります。
スナップショット名や、hosts、iptables等の任意情報は省略しています。

![1_1.png](https://qiita-image-store.s3.amazonaws.com/0/310082/9c163179-a714-9a49-7193-5c8b3363c715.png)


次に、Pybatfishの`nodeProperties`クラスを使い、ノード`hqborder2`(Cisco1812J)のConfigから各種設定情報を抽出します。
ホスト名、インターフェース構成、ACL、IPSec、Syslog、NTP、SNMP、TACACS、VRFはもちろんのこと、Vendor Family(CISCO)、Configuration_Format(CISCO_IOS)やDevice_Type(ROUTER)なんかも判定して表示してくれます。

![1-3.png](https://qiita-image-store.s3.amazonaws.com/0/310082/a98ca39c-60fc-62cf-a8c1-de5b981c8863.png)

ご参考までに、`hqborder2`のConfigもアップしておきます。

```text:show_running-config
!
! Last configuration change at 20:56:21 JST Sat Dec 1 2018 by test
! NVRAM config last updated at 20:56:22 JST Sat Dec 1 2018 by test
!
version 12.4
service timestamps debug datetime localtime
service timestamps log datetime localtime
service password-encryption
!
hostname hqborder2
!
boot-start-marker
boot-end-marker
!
no logging console
enable secret 5 $1$wD.F$WXmDhYs9APx451X1fKoyj/
!
no aaa new-model
!
resource policy
!
clock timezone JST 9
!
!
ip cef
!
!
no ip domain lookup
ip domain name hqborder2
ip ssh version 2
!
!
!
username test privilege 15 password 7 1403171818
!
!
class-map match-all C-DATA2
 match access-group 101
class-map match-all C-DATA1
 match access-group 100
!
!
policy-map P-CHILD
 class C-DATA1
  priority percent 40
 class C-DATA2
   compress header ip 
  bandwidth percent 30
 class class-default
   compress header ip 
  bandwidth percent 30
policy-map P-PARENT
 class class-default
  shape average 10000000
  service-policy P-CHILD
!
! 
!
!
!
!
interface Tunnel1
 description << To brborder2 >>
 bandwidth 100
 ip address 10.1.1.9 255.255.255.252
 delay 10
 tunnel source Loopback0
 tunnel destination 1.1.1.2
!
interface Loopback0
 ip address 1.1.1.1 255.255.255.255
!
interface FastEthernet0
 description << To PE Router >>
 ip address 10.1.1.5 255.255.255.252
 duplex auto
 speed auto
!
interface FastEthernet1
 description << border2 - dist1 Segment >>
 ip address 192.168.200.9 255.255.255.252
 speed 100
 full-duplex
!
interface BRI0
 no ip address
 encapsulation hdlc
 shutdown
!
interface FastEthernet2
 description << To hqdist2 Fa0/2 >>
 switchport access vlan 203
 duplex full
 speed 100
!
interface FastEthernet3
!
interface FastEthernet4
!
interface FastEthernet5
!
interface FastEthernet6
!
interface FastEthernet7
!
interface FastEthernet8
!
interface FastEthernet9
!
interface Vlan1
 no ip address
!
interface Vlan203
 description << border2 - dist2 Segment >>
 ip address 192.168.200.13 255.255.255.252
!
router eigrp 1
 network 10.1.1.8 0.0.0.3
 network 192.168.200.8 0.0.0.3
 network 192.168.200.12 0.0.0.3
 no auto-summary
!
ip route 1.1.1.2 255.255.255.255 10.1.1.6
!
!
no ip http server
no ip http secure-server
!
logging 192.168.100.107
access-list 100 permit ip 192.168.100.0 0.0.0.255 any
access-list 101 permit ip 192.168.101.0 0.0.0.255 any
snmp-server community C1sc0 RO
snmp-server host 192.168.100.107 C1sc0 
!
!
!
!
!
!
control-plane
!
banner login ^C
============NOTICE==============
| This is test device for demo |
================================
^C
!
line con 0
line aux 0
line vty 0 4
 login local
line vty 5 15
 login local
!
ntp clock-period 17179867
ntp server 192.168.100.44
!
webvpn context Default_context
 ssl authenticate verify all
 !
 no inservice
!
end
```

# コンプライアンスチェック(2/2) - NTPサーバ設定の妥当性確認

(1/2)で取得した情報の中から、プロパティ`NTP_Servers`(NTPサーバのIPアドレス)の情報を、複数台まとめて抽出します。
![1-5.png](https://qiita-image-store.s3.amazonaws.com/0/310082/33de5157-945b-3c24-b207-349ab217d87e.png)

仮にコンプライアンスポリシーが、「`192.168.100.44`、`10.10.1.44`いずれかをNTPサーバとして設定すること」だったとします。これに対し、以下のコードでいずれも含まないノードを抽出できます。
![1-6.png](https://qiita-image-store.s3.amazonaws.com/0/310082/9c667483-6b1e-109d-1793-2ea242c44b0b.png)

データはGistにも置いています。
https://gist.github.com/Tachashi/c4089d27af0249c507d2a3b21c7ce089

# 所感
今回紹介した`nodeProperties`クラスは、グローバル設定をパースして変数に格納していますが、現時点ではすべての設定は網羅できていないようです。
(例：HTTP/HTTPSサーバ設定 `ip http server`、`ip http secure-server`は取得できていない。)
また、作成Configのコマンドが省略されていた場合、誤った確認結果が出ることもあります。
(例：`ntp ser 192.168.100.44`とした場合、コマンドは問題なく入るが、パースは失敗するため妥当性確認結果はNGとなる。)
これらに注意した上で、使う場面を見極める必要があると感じました。
ただし、これはあくまでもBatfishの一機能であり、Batfish自体が強力なツールであることは間違いないと思います。
現在も新しい機能が続々とリリースされていますので、引き続き今後の動向に注目していきたいです。