VRF 間で Route Leakを設定してみた

# はじめに
この記事は Cisco Systems 合同会社 社員有志による Cisco Systems Japan Advent Calendar 2022 (2枚目) の 23日目として投稿しています。

2017年版: https://qiita.com/advent-calendar/2017/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2019年版: https://qiita.com/advent-calendar/2019/cisco
2020年版①: https://qiita.com/advent-calendar/2020/cisco
2020年版②: https://qiita.com/advent-calendar/2020/cisco2
2021年版①: https://qiita.com/advent-calendar/2021/cisco
2021年版②: https://qiita.com/advent-calendar/2021/cisco2
**2022年版①②: https://qiita.com/advent-calendar/2022/cisco**

# Route Leak とは
グローバルルーティングテーブルやVRFでprefix情報はそれぞれ個別に保持されますが、Route Leak を使用することで異なるルーティングテーブル間で prefix 情報を渡すことができます。
IOS-XRでの例になりますが、Route Leakのわかりやすい説明は[こちら](https://community.cisco.com/t5/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%83%97%E3%83%AD%E3%83%90%E3%82%A4%E3%83%80-%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88/ios-xr-route-leak-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/ta-p/4107876)を参考にしてください。

今回はもう少し凝った環境においてRoute Leakをしてみます。
また今回書いた設定、出力結果はOSやバージョンによって異なることがあります。

# トポロジー図
## 物理トポロジー
以下が今回用意した物理トポロジー図、OSになります。
![topology-physical.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355483/8d753c73-3a1d-736e-47db-12fce0951a02.png)

```
OSのバージョン
- Router: IOSv Software (VIOS-ADVENTERPRISEK9-M), Version 15.9(3)M4
- Ubuntu: Ubuntu 20.04.3 LTS
```

実際は物理トポロジーというのは名ばかりで[CML](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html)の上にたてた仮想マシンになります。
こちらのトポロジーにおいて、２つのVRF(VRF1、VRF2)を作成し、UbuntuからR1へPingを飛ばすためにRoute Leakを設定します。
最終目標は以下の図の赤線にあるような**UbuntuからVRF2を使用してR4からR2かR3へ到達し、そこからVRF1のルートでR1へ到達すること**です。
![ping-route.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355483/1da3bee1-1442-5bbf-7e8a-6b759be982fb.png)


## VRF1 トポロジー
以下はVRF1のトポロジー図です。VRF1を使用しているインタフェースはオレンジ色の丸が置いてあります。
![topology-vrf1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355483/d80c2ef4-defa-e205-fa21-01680fae7d5d.png)


また以下の設定をVRF1を使用して加えています。
- R1、R2、R3でMP-BGPを実行 → VRF上の情報を交換するためにはMP-BGPで動かすことが必須です
- Route DistinguisherをVRFに設定 → MP-BGPを動かすために必要な設定です
- R1-R2、R1-R3間でEBGPピアを張る
  - R1はLo0(1.1.1.1)のルーティング情報をEBGPで広告しています
- R2-R4、R3-R4の間はL3サブインタフェースを使用 →　1つのインタフェースで2つのVRFを動かすためです　

UbuntuはVRF2のインタフェースにつながっているとします。
この状態ではUbuntuはもはや、R4からも1.1.1.1へはPingが飛びません。

## VRF2 トポロジー
以下はVRF2のトポロジー図です。VRF2を使用しているインタフェースはピンク色の丸が置いてあります。
![topology-vrf2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355483/c729308e-f4c1-ff5a-5bb5-334ce300a30d.png)

また以下の設定をVRF2を使用して加えています。
- R2、R3、R4でOSPFを実行し、ルートを交換 → UbuntuからR2とR3へ通信を可能にします
- R2-R4、R3-R4の間はL3サブインタフェースを使用 →　1つのインタフェースで2つのVRFを動かすためです　
- R4にてDHCPサーバーを設定し、Ubuntuのインタフェースに40.0.0.2/24、UbuntuのデフォルトゲートウェイをR4に設定

ここでUbuntuからR1のLo0(1.1.1.1)へPingを飛ばしてみると
```
cisco@ubuntu:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
From 40.0.0.1 icmp_seq=1 Destination Host Unreachable
From 40.0.0.1 icmp_seq=2 Destination Host Unreachable
From 40.0.0.1 icmp_seq=3 Destination Host Unreachable
```
もちろん通信はできません。ここからR1へ通信ができるようにします。

# それでは Route Leak してみよう
このままの設定だとUbuntuからR1のLo0(1.1.1.1)への疎通ができません。
以下はR4のVRF2のルーティングテーブルです。
```
R4#sh ip route vrf VRF2

Routing Table: VRF2
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
       i - IS-IS, su - IS-IS summary, 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, H - NHRP, l - LISP
       a - application route
       + - replicated route, % - next hop override, p - overrides from PfR

Gateway of last resort is not set

      20.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        20.0.20.0/24 is directly connected, GigabitEthernet0/0.20
L        20.0.20.2/32 is directly connected, GigabitEthernet0/0.20
      30.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        30.0.20.0/24 is directly connected, GigabitEthernet0/1.20
L        30.0.20.2/32 is directly connected, GigabitEthernet0/1.20
      40.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        40.0.0.0/24 is directly connected, GigabitEthernet0/2
L        40.0.0.1/32 is directly connected, GigabitEthernet0/2
```
1.1.1.1へのルートがないですね。
そこでRoute Leakによって通信を可能にします。

# Route Leak の設定
Route Leakの設定方法はいくつかあると思いますが、今回は以下の方法で設定します。
1. Route target を設定
2. Route map で Leak したいルートを指定
3. Route map を使用して Route Leak

## 1. Route target を設定
Route targetはMP-BGPの拡張コミュニティ属性として、MP-BGPネイバーにアドバタイズされます。
アドバタイズされたルーターではこの値を見てVRFテーブルに取り込みます。
ですのでRoute leak元のVRF、Route leak先のVRFでこの値を揃えてexport、importをします。
以下はR2での設定例です。
```
R2#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
R2(config)#vrf definition VRF1
R2(config-vrf)#route-target export 64700:101
R2(config-vrf)#route-target import 64700:201
R2(config-vrf)#exit
R2(config)#vrf definition VRF2
R2(config-vrf)#route-target import 64700:101
R2(config-vrf)#route-target export 64700:201
R2(config-vrf)#end
```

## 2. Route mapでLeakしたいルートを指定
Route mapの説明は省略しますが、Route mapによってVRFのルーティングテーブルに載せるルートを指定します。
以下はR2での設定例です。
```
R2(config)#ip access-list standard VRF1-to-VRF2
R2(config-std-nacl)#permit 1.1.1.1 0.0.0.255 
R2(config-std-nacl)#exit
R2(config)#ip access-list standard VRF2-to-VRF1
R2(config-std-nacl)#permit 40.0.0.0 0.0.0.255
R2(config-std-nacl)#exit

R2(config)#route-map RM_VRF1-to-VRF2    
R2(config-route-map)#match ip address VRF1-to-VRF2
R2(config-route-map)#exit                         
R2(config)#route-map RM_VRF2-to-VRF1    
R2(config-route-map)#match ip address VRF2-to-VRF1
R2(config-route-map)#exit
```

## 3. Route map を使用して Route Leak
定義したRoute mapをVRFに対し使用し、Route leakを実行します。
以下はR2での設定例です。
```
R2(config)#vrf definition VRF1
R2(config-vrf)#address-family ipv4
R2(config-vrf-af)#import map RM_VRF2-to-VRF1
R2(config-vrf-af)#export map RM_VRF1-to-VRF2
R2(config-vrf-af)#exit
R2(config-vrf)#exit
R2(config)#vrf definition VRF2
R2(config-vrf)#address-family ipv4       
R2(config-vrf-af)#import map RM_VRF1-to-VRF2
R2(config-vrf-af)#export map RM_VRF2-to-VRF1
R2(config-vrf-af)#exit
R2(config-vrf)#exit
```

## Pingは飛ぶかな？
これでRoute Leakは完璧！ということでUbuntuからR1にPingを飛ばしてみます。
```
cisco@ubuntu:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
From 40.0.0.1 icmp_seq=1 Destination Host Unreachable
From 40.0.0.1 icmp_seq=2 Destination Host Unreachable
From 40.0.0.1 icmp_seq=3 Destination Host Unreachable
```
あれ、通信ができません。
またR2のVRF1のルーティングテーブルを確認してみると
```
R2#sh ip route vrf VRF1

Routing Table: VRF1
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
       i - IS-IS, su - IS-IS summary, 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, H - NHRP, l - LISP
       a - application route
       + - replicated route, % - next hop override, p - overrides from PfR

Gateway of last resort is not set

      1.0.0.0/24 is subnetted, 1 subnets
B        1.1.1.0 [20/0] via 10.0.1.1, 00:23:27
      10.0.0.0/8 is variably subnetted, 3 subnets, 2 masks
C        10.0.1.0/24 is directly connected, GigabitEthernet0/0
L        10.0.1.2/32 is directly connected, GigabitEthernet0/0
B        10.0.2.0/24 [20/0] via 10.0.1.1, 00:23:27
      20.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        20.0.10.0/24 is directly connected, GigabitEthernet0/1.10
L        20.0.10.1/32 is directly connected, GigabitEthernet0/1.10
      30.0.0.0/24 is subnetted, 1 subnets
O        30.0.10.0 [110/2] via 20.0.10.2, 02:09:12, GigabitEthernet0/1.10
```
40.0.0.0/24のルートもありません。

## Route Leak するために必要な条件
Route LeakはMP-BGPを使用し、異なるVRF間のBGP上でルートをやりとりします。
ということはLeak元、さらにLeak先でBGPを動かす必要があります。

VRF2ではBGPを動かしていません。
ですのでR2においてBGPを動かし、そこに40.0.0.0/24のルートを渡します。
またR2においてBGPからOSPFへの再配送もしていなかったのでそちらもしておき、LeakしたルートをR4へ渡します。
```
R2(config)#router bgp 64700
R2(config-router)#address-family ipv4 vrf VRF2
R2(config-router-af)#redistribute ospf 2 vrf VRF2
R2(config-router-af)#end
R2(config)#router ospf 2 vrf VRF2 
R2(config-router)#redistribute bgp 64700
```

これでやっとRoute Leakは完璧！ということで
UbuntuからR1にPingを飛ばしてみます。
```
cisco@ubuntu:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
From 40.0.0.1 icmp_seq=1 Destination Host Unreachable
From 40.0.0.1 icmp_seq=2 Destination Host Unreachable
From 40.0.0.1 icmp_seq=3 Destination Host Unreachable
```
まだ飛ばない。。。
Route Leakができていないのか？？R2のVRF2のルーティングテーブルを確認してみます。
```
R2#sh ip route vrf VRF2

Routing Table: VRF2
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
       i - IS-IS, su - IS-IS summary, 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, H - NHRP, l - LISP
       a - application route
       + - replicated route, % - next hop override, p - overrides from PfR

Gateway of last resort is not set

      1.0.0.0/24 is subnetted, 1 subnets
B        1.1.1.0 [20/0] via 10.0.1.1 (VRF1), 00:40:32
      20.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        20.0.20.0/24 is directly connected, GigabitEthernet0/1.20
L        20.0.20.1/32 is directly connected, GigabitEthernet0/1.20
      30.0.0.0/24 is subnetted, 1 subnets
O        30.0.20.0 [110/2] via 20.0.20.2, 02:02:35, GigabitEthernet0/1.20
      40.0.0.0/24 is subnetted, 1 subnets
O        40.0.0.0 [110/2] via 20.0.20.2, 01:54:43, GigabitEthernet0/1.20
```
しっかりRoute Leakできてる様子です。

R4のVRF2のルーティングテーブルを確認してみると
```
R4#sh ip route vrf VRF2

Routing Table: VRF2
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
       i - IS-IS, su - IS-IS summary, 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, H - NHRP, l - LISP
       a - application route
       + - replicated route, % - next hop override, p - overrides from PfR

Gateway of last resort is not set

      20.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        20.0.20.0/24 is directly connected, GigabitEthernet0/0.20
L        20.0.20.2/32 is directly connected, GigabitEthernet0/0.20
      30.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        30.0.20.0/24 is directly connected, GigabitEthernet0/1.20
L        30.0.20.2/32 is directly connected, GigabitEthernet0/1.20
      40.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C        40.0.0.0/24 is directly connected, GigabitEthernet0/2
L        40.0.0.1/32 is directly connected, GigabitEthernet0/2
```
なぜか1.1.1.1のルートがない。。

OSPFのデータベースを見てみると
```
R4#sh ip ospf 2 database

            OSPF Router with ID (4.4.4.40) (Process ID 2)

                Router Link States (Area 0)

Link ID         ADV Router      Age         Seq#       Checksum Link count
2.2.2.20        2.2.2.20        44          0x800000AF 0x0019E1 1
3.3.3.30        3.3.3.30        44          0x800000AE 0x00F2DA 1
4.4.4.40        4.4.4.40        7           0x800000B2 0x0039DA 3

                Net Link States (Area 0)

Link ID         ADV Router      Age         Seq#       Checksum
20.0.20.1       2.2.2.20        43          0x800000AB 0x00718C
30.0.20.1       3.3.3.30        43          0x800000AA 0x0019C1

                Type-5 AS External Link States

Link ID         ADV Router      Age         Seq#       Checksum Tag
1.1.1.0         2.2.2.20        1317        0x800000A5 0x00D90D 3489725628
1.1.1.0         3.3.3.30        1274        0x800000A4 0x008753 3489725628
```
R4に1.1.1.1のLSAは渡っています。

### DN ビット
これはDN ビットが原因です。
DNビットとは、OSPF LSA オプション フィールドで、従来未使用だったビット([参照](https://www.cisco.com/c/ja_jp/support/docs/ip/open-shortest-path-first-ospf/118800-configure-ospf-00.html))のことを言います。
DNビットはMP-BGPのルートがOSPFに再配布される際に設定されます。
このDNビットがあると何が起こるかというと、タイプ 3、5、または 7 に DN ビットが設定された LSA を受信するとそのLSAの情報はOSPFルートの計算には使用されません。
そのためR4では1.1.1.1のLSAが届いているもののルーティングテーブルで見えないという状況になっていました。

ではどうすればいいのでしょう？
ここで出てくるのが
```capability vrf-lite```コマンドです。
このコマンドによりDNビットを無視してくれます。英語になりますが[こちら](https://community.cisco.com/t5/routing/where-to-configure-the-quot-capability-vrf-lite-quot-on-ce-or-pe/td-p/2812305)が参考になります。

### いざR1へ
それでは```capability vrf-lite```コマンドを打ってみます。
```
R4(config)#router ospf 2 vrf VRF2
R4(config-router)#capability vrf-lite
```
これで行けるはず！！UbuntuからR1へPingしてみると
```
cisco@ubuntu:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=253 time=2.21 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=253 time=2.46 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=253 time=2.30 ms
```

キターー！！！

### 余談
ちなみにですがRoute LeakしたルートをR2の```sh ip route vrf VRF2```で見てみると
```
B        1.1.1.0 [20/0] via 10.0.1.1 (VRF1), 00:10:48
```
(VRF1)のようにRoute Leak元のVRFがわかります。
directly connectedのルートをLeakした場合は違う見え方をするので気になる方はぜひやってみてください。

# まとめ
今回は Route Leak を試してみました。
Route Leakという概念自体は簡単そうに聞こえますが、実際にLeakするためにBGPを動かす必要があったり、
そこからVRFを使用してルートを交換するにもOSPFだとDNビットが設定されたりとVRFを動かしてみてわかることばかりでした。
ルーティングにはまだまだ見えていない技術がたくさんある、と実感しました。
これからも色々な技術を実際に手で動かして学んでいきます！

# 免責事項
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。