1
1

More than 1 year has passed since last update.

BatfishでNW障害時の影響分析を行う②

Last updated at Posted at 2022-03-11

1. はじめに

前回の記事では、Configファイルをインプットに、ネットワークConfig解析ツール「Batfish」で正常時の確認を行いました。
BatfishでNW障害時の影響分析を行う①

本記事では筐体障害、リンク障害時の確認と、正常時・障害時を比較した影響分析を行ってみたいと思います。

2. 筐体障害時の確認

2-1. 筐体障害発生

※前回の記事の「3. Batfishのセットアップ」まで終わっている前提とします。
正常時のスナップショットtest_snapshotをフォークし、iosvl2-0筐体障害発生時のスナップショットfail_accessを作成します。引数deactivate_nodesには障害機器のホスト名iosvl2-0を指定します。

snippet1
FAIL_ACCESS_SNAPSHOT_NAME = "fail_access"
bf.fork_snapshot(BASE_SNAPSHOT_NAME,
                 FAIL_ACCESS_SNAPSHOT_NAME,
                 deactivate_nodes=["iosvl2-0"],
                 overwrite=True)

2-2. 通信経路確認

bidirectionalTraceroute()を使用し、10.1.1.100から10.4.1.100宛ての疎通性および通信経路を確認します。
正常時の確認と異なるのは、answer()の引数としてフォークしたスナップショットを明示指定している点です。

snippet2
result_bdtr_dev_fail = bf.q.bidirectionalTraceroute(
    startLocation='@enter(csr1000v-0[GigabitEthernet2])',
    headers=HeaderConstraints(dstIps='10.4.1.100', srcIps='10.1.1.100')).answer(
    snapshot=FAIL_ACCESS_SNAPSHOT_NAME).frame()
result_bdtr_dev_fail.Forward_Traces[0][0]

iosvl2-0障害時は、iosvl2-1経由に切り替わるのが想定結果です。ただし今回は、iosvl2-1でACL許可設定漏れがあり、10.1.1.100から10.4.1.100宛ての通信が拒否される状態になっています。
行きの実行結果では想定通りDENIED_INとなり、iosvl2-1Vlan100に適用されているin方向ACLacl_testで拒否されています。
image.png

戻りの実行結果も確認してみます。

snippet3
result_bdtr_dev_fail.Reverse_Traces[0][0]

以下の通りエラーとなりました。
image.png

代わりに、traceroute()10.4.1.100から10.1.1.100宛ての疎通性および通信経路を確認してみます。

snippet4
result_bdtr_dev_fail2 = bf.q.traceroute(
    startLocation='@enter(iosvl2-3[GigabitEthernet0/2])',
    headers=HeaderConstraints(dstIps='10.1.1.100', srcIps='10.4.1.100')).answer(
    snapshot=FAIL_ACCESS_SNAPSHOT_NAME).frame()
result_bdtr_dev_fail2.Traces[0][0]

traceroute()は片方向の通信がNGでも結果を返してくれるので、想定通りの通信経路が表示されました。3.でiosvl2-0の代わりにiosvl2-1を経由していることが分かります。
image.png

3. リンク障害時の確認

3-1. 単一リンク障害発生

正常時のスナップショットtest_snapshotをフォークし、iosvl2-0GigabitEthernet0/2リンク発生時のスナップショットfail_linkを作成します。
筐体障害時の引数はdeactivate_nodesでしたが、リンク障害はdeactivate_interfacesを使います。

snippet5
FAIL_LINK_SNAPSHOT_NAME = "fail_link"
bf.fork_snapshot(BASE_SNAPSHOT_NAME,
                 FAIL_LINK_SNAPSHOT_NAME,
                 deactivate_interfaces=[Interface(hostname="iosvl2-0", interface="GigabitEthernet0/2")],
                 overwrite=True)

3-2. 単一リンク障害時の通信経路確認

スナップショット名以外は筐体障害時と同じです。

snippet6
result_bdtr_link_fail = bf.q.bidirectionalTraceroute(
    startLocation='@enter(csr1000v-0[GigabitEthernet2])',
    headers=HeaderConstraints(dstIps='10.4.1.100', srcIps='10.1.1.100')).answer(
    snapshot=FAIL_LINK_SNAPSHOT_NAME).frame()
result_bdtr_link_fail.Forward_Traces[0][0]

LAN側の単一リンク障害だけではVRRP切り替わりは発生しない設計のため、正常時と同様の結果となりました。
image.png

3-3. 多重リンク障害発生

正常時のスナップショットtest_snapshotをフォークし、今度はiosvl2-0GigabitEthernet0/2, 1/0, 1/1の多重リンク発生時のスナップショットfail_multiple_linkを作成します。

snippet7
FAIL_MULTIPLE_LINK_SNAPSHOT_NAME = "fail_multiple_link"
bf.fork_snapshot(BASE_SNAPSHOT_NAME,
                 FAIL_MULTIPLE_LINK_SNAPSHOT_NAME,
                 deactivate_interfaces=[Interface(hostname="iosvl2-0", interface="GigabitEthernet0/2"),
                                        Interface(hostname="iosvl2-0", interface="GigabitEthernet1/0"),
                                        Interface(hostname="iosvl2-0", interface="GigabitEthernet1/1")],
                 overwrite=True)

3-4. 多重リンク障害時の通信経路確認

こちらもスナップショット名以外は筐体障害時と同じです。

snippet8
result_bdtr_mlink_fail = bf.q.bidirectionalTraceroute(
    startLocation='@enter(csr1000v-0[GigabitEthernet2])',
    headers=HeaderConstraints(dstIps='10.4.1.100', srcIps='10.1.1.100')).answer(
    snapshot=FAIL_MULTIPLE_LINK_SNAPSHOT_NAME).frame()
result_bdtr_mlink_fail.Forward_Traces[0][0]

LAN側IFがすべて塞がれてVRRP切り替わりが発生し、想定通り筐体障害時と同様の結果になりました。
image.png

4. 正常時・障害時を比較した影響分析

最後に、正常時と筐体障害時を比較し、前者で許可されるが、後者ではドロップされる通信を出力したいと思います。
QuestionはdifferentialReachability()を使います。(参考) 通信経路確認で用いるQuestion
結果を見やすくするため、引数pathConstraintsで開始ノード、headersで対象通信、maxTracesでTrace出力結果数を絞っています。引数を指定しない場合、各機器から障害機器宛ての通信を含むすべての差分が出力されます。

snippet9
result_diff_reachability = bf.q.differentialReachability(
    pathConstraints=PathConstraints(startLocation = f'@enter({"csr1000v-0"}[{"GigabitEthernet1"}])'),
    headers=HeaderConstraints(dstIps='10.4.1.100', srcIps='10.1.1.100'),
    maxTraces=1).answer(
    snapshot=FAIL_ACCESS_SNAPSHOT_NAME,
    reference_snapshot=BASE_SNAPSHOT_NAME)
result_diff_reachability.frame()

結果は以下の通りです。Reference_Traces(正常時)ではDELIVERED_TO_SUBNETSnapshot_Traces(筐体障害時)ではDENIEDとして差分出力されていることが分かります。
image.png

送信元と宛先を逆にした場合、正常時・障害時ともに通信可能なため差分出力されませんでした。

snippet10
    headers=HeaderConstraints(dstIps='10.1.1.100', srcIps='10.4.1.100'),

image.png

5. 最後に

今回は小規模なネットワークで、1パターンの通信経路のみで影響分析を実施しました。
一方で大規模ネットワークに対し、あらかじめ定義した筐体・リンク障害パターンで複数の通信経路確認も当然可能です。
Batfishのツールとしての性質上、複雑な設計、特殊な設定ではうまく解析できないケースもあるかもしれませんが、まずは「問題が見つかったらラッキー」くらいの感覚で使ってみるのも良いかも知れません。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1