OSPFによる動的ルーティングをdocker container間で動かす

ひとつのVM内でdocker containerを複数立ち上げ,その間でOSPFを動かす.

pingを通すだけでなく,動的に経路が切り替わるのを確認する. コードはこちら.

github.com

ホストの立ち上げから必要な設定の注入に関しては以下のサイトにとても丁寧に書いてある. 今回の設定については,ほんの数行なのでgithubを参照してください. qiita.com

環境

ネットワーク構成

large/docker-compose.yamlの通りです.

動作

1. コンテナの立ち上げ

$ git clone https://github.com/kkti4216/docker-ospf.git
$ cd docker-ospf/large
$ docker-compose up -d

2. h1からh2への経路を確認

h1 -> frr1 -> frr2 -> h2となっている.

$ docker container exec -it h1 bash
bash-5.1# traceroute -n 192.168.2.12
traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.004 ms  0.002 ms  0.002 ms
 2  192.168.11.22  0.003 ms  0.003 ms  0.002 ms
 3  192.168.2.12  0.002 ms  0.002 ms  0.003 ms

3. frr1 - frr2のリンクのコストを大きく

沼に嵌った話はおまけへ.

frr1-eth1 (frr2側のインターフェース) のコストを編集.

$ docker container exec -it frr1 bash
bash-5.1# vtysh

Hello, this is FRRouting (version 8.2.2_git).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

frr1# conf
frr1(config)# int eth1
frr1(config-if)# ip ospf cost 100

frr2-eth0も同様にコストを編集.

$ docker container exec -it frr2 bash
bash-5.1# vtysh

Hello, this is FRRouting (version 8.2.2_git).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

frr2# conf
frr2(config)# int eth0
frr2(config-if)# ip ospf cost 100

再びh1からh2への経路を確認. frr3を経由するようになった.

$ docker container exec -it h1 bash
bash-5.1# traceroute -n 192.168.2.12
traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.005 ms  0.002 ms  0.002 ms
 2  192.168.33.33  0.001 ms  0.002 ms  0.002 ms
 3  192.168.22.22  0.002 ms  0.003 ms  0.002 ms
 4  192.168.2.12  0.002 ms  0.003 ms  0.003 ms

この時のh1のルーティングテーブルは以下のようになる.

$ docker container exec -it frr1 bash
frr1# show ip ospf route
============ OSPF network routing table ============
N    192.168.1.0/24        [10] area: 0.0.0.0
                           directly attached to eth0
N    192.168.2.0/24        [30] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.3.0/24        [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.11.0/24       [100] area: 0.0.0.0
                           directly attached to eth1
N    192.168.22.0/24       [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.33.0/24       [10] area: 0.0.0.0
                           directly attached to eth2

============ OSPF router routing table =============

============ OSPF external routing table ===========

4. frr2-eth2をdownさせる

frr3 - frr2の接続が切れるため,h1 -> h2のパケットはコストの大きいリンクを通ることになる.

$ docker container exec -it frr2 bash
bash-5.1# ip link set eth2 down

h1から再びtracerouteすると,たしかにfrr3を経由しない経路へ戻った.

$ docker container exec -it f1 bash
bash-5.1# traceroute -n 192.168.2.12
traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.004 ms  0.003 ms  0.003 ms
 2  192.168.11.22  0.003 ms  0.002 ms  0.003 ms
 3  192.168.2.12  0.002 ms  0.003 ms  0.002 ms

この時のfrr1のルーティングテーブルは以下. 192.168.2.0/24へのコストが大きくなっている.

 $ docker container exec -it frr1 bash
 frr1# show ip ospf route
============ OSPF network routing table ============
N    192.168.1.0/24        [10] area: 0.0.0.0
                           directly attached to eth0
N    192.168.2.0/24        [110] area: 0.0.0.0
                           via 192.168.11.22, eth1
N    192.168.3.0/24        [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.11.0/24       [100] area: 0.0.0.0
                           directly attached to eth1
N    192.168.22.0/24       [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.33.0/24       [10] area: 0.0.0.0
                           directly attached to eth2

============ OSPF router routing table =============

============ OSPF external routing table ===========

また,frr3のルーティングテーブルを確認すると,h2 (192.168.2.0/24) への経路がfrr1経由となっておりdownさせたリンクを迂回できている.

$ docker container exec -it frr3 bash
bash-5.1# vtysh

Hello, this is FRRouting (version 8.2.2_git).
Copyright 1996-2005 Kunihiro Ishiguro, et al.

frr3# show ip ospf route
============ OSPF network routing table ============
N    192.168.1.0/24        [20] area: 0.0.0.0
                           via 192.168.33.11, eth2
N    192.168.2.0/24        [120] area: 0.0.0.0
                           via 192.168.33.11, eth2
N    192.168.3.0/24        [10] area: 0.0.0.0
                           directly attached to eth1
N    192.168.11.0/24       [110] area: 0.0.0.0
                           via 192.168.33.11, eth2
N    192.168.22.0/24       [10] area: 0.0.0.0
                           directly attached to eth0
N    192.168.33.0/24       [10] area: 0.0.0.0
                           directly attached to eth2

============ OSPF router routing table =============

============ OSPF external routing table ===========

5. まとめ

実際に経路が切り替わるのはネットワークを弄れている実感が湧いて楽しい. docker network や docker-compose などdockerまわりのいい勉強にもなった.

おまけ

コストを大きくする際,片方のインターフェースのみしか編集しておらず沼に嵌った.

3. frr1 - frr2のリンクのコストを大きくから分岐.

frr1のeth1 (frr2と接続しているinterface) のコストを大きくする.

$ docker container exec -it frr1 bash
bash-5.1# vtysh
frr1# conf
frr1(config)# interface eth1
frr1(config-if)# ip ospf cost 100

再びh1からh2への経路を確認. frr3を経由するようになっている.

$ docker container exec -it h1 bash
bash-5.1# traceroute -n 192.168.2.12
traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.004 ms  0.002 ms  0.002 ms
 2  192.168.33.33  0.002 ms  0.002 ms  0.003 ms
 3  192.168.11.22  0.001 ms  0.002 ms  0.002 ms
 4  192.168.2.12  0.002 ms  0.002 ms  0.003 ms

ただし,3 192.168.11.22 0.001 ms 0.002 ms 0.002 ms のルータのアドレスが 192.168.22.22 になっていない. 試しにfrr2-eth0をdownさせてみる.

$ docker container exec -it frr2 bash
bash-5.1# ip link set eth0 down

もう一度経路を確認.

$ docker container exec -it h1 bash
bash-5.1# traceroute -n 192.168.2.12
traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.004 ms  0.002 ms  0.003 ms
 2  192.168.33.33  0.001 ms  0.002 ms  0.003 ms
 3  192.168.22.22  0.002 ms  0.002 ms  0.003 ms
 4  192.168.2.12  0.002 ms  0.003 ms  0.003 ms

正しく192.168.22.22を経由できている. tracerouteTTL値をインクリメントしながら送信し,返ってくるICMPパケットを見る. frr2でTTL=0となるパケットの経路がfrr2-eth0経由となったのが原因と考えられる.

本来一番最初にするべきであるルーティングテーブルを確認. frr2では,

$ docker container exec -it frr2 bash
frr2# show ip ospf route
============ OSPF network routing table ============
N    192.168.1.0/24        [20] area: 0.0.0.0
                           via 192.168.11.11, eth0
N    192.168.2.0/24        [10] area: 0.0.0.0
                           directly attached to eth1
N    192.168.3.0/24        [20] area: 0.0.0.0
                           via 192.168.22.33, eth2
N    192.168.11.0/24       [10] area: 0.0.0.0
                           directly attached to eth0
N    192.168.22.0/24       [10] area: 0.0.0.0
                           directly attached to eth2
N    192.168.33.0/24       [20] area: 0.0.0.0
                           via 192.168.11.11, eth0
                           via 192.168.22.33, eth2

============ OSPF router routing table =============

============ OSPF external routing table ===========

h1(192.168.1.12)へのパケットはコストを100に設定したはずのfrr1-eth1を経由することになっている(通常のインターフェースのコストは10). インターフェースにコストを設定した場合,送信する側のコストのみが影響する様子? 調べてみると一般的には受信側のコストで計算されるらしいがよくわからず...

frr1のルーティングテーブルも確認してみると,192.168.11.0/24への経路はfrr1 -> frr3 -> frr2 -> となっている.

$ docker container exec -it frr1 bash
bash-5.1# vtysh
frr1# show ip ospf route
============ OSPF network routing table ============
N    192.168.1.0/24        [10] area: 0.0.0.0
                           directly attached to eth0
N    192.168.2.0/24        [30] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.3.0/24        [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.11.0/24       [30] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.22.0/24       [20] area: 0.0.0.0
                           via 192.168.33.33, eth2
N    192.168.33.0/24       [10] area: 0.0.0.0
                           directly attached to eth2

============ OSPF router routing table =============

============ OSPF external routing table ===========

frr2でTTL=0となるパケットの経路がfrr2-eth0経由となったのが原因と考えられる.

で正しそう. 本当はfrr1-eth1でtcpdumpとかすれば良さそう.

ここでfrr2-eth0のコストもfrr-eth1と同様にコストを高くする.

$ docker container exec -it frr2 bash
frr2:/# ip link set eth0 up
frr2:/# vtysh
frr2# conf
frr2(config)# int eth0
frr2(config-if)# ip ospf cost 100

経路を確認.

traceroute to 192.168.2.12 (192.168.2.12), 30 hops max, 46 byte packets
 1  192.168.1.11  0.005 ms  0.002 ms  0.002 ms
 2  192.168.33.33  0.024 ms  0.002 ms  0.002 ms
 3  192.168.22.22  0.002 ms  0.002 ms  0.002 ms
 4  192.168.2.12  0.004 ms  0.002 ms  0.002 ms

正しく192.168.22.22を経由してくれるようになった.

おまけここまで