Ubuntu 20.04LTSでGoBGPを動かしてみた

# はじめに

GoBGP、`apt-get`してドキュメントどおりに設定書いて終わりだからとくにハマることないよなあ、と思いながらやってみたら、思ってたよりハマったのでメモを残します。試した環境はUbuntu 20.04LTSです。

# インストール

`sudo apt-get install -y frr gobgpd`

あとでちゃんと確認してみたら、バージョンは

- gobgpd: 2.12.0-1
- frr: 7.2.1-1

でした。

FRRを入れるのには理由があります。GoBGPは経路交換してくれますが、それをカーネルのFIBに反映してくれません。FIBへの反映にzebraを用いる場合、QuaggaあるいはFRRoutingが必要とのことでした。

参考: [FIB manipulation](https://github.com/osrg/gobgp/blob/master/docs/sources/zebra.md)

# FRRの設定

とくに必要ありません。何もしなくても`zebra`は動いていると思います。動いてなければ`sudo systemctl start frr.service`で。

# GoBGPの設定

最低限の設定を`/etc/gobgpd.conf`に記述し、残りは`gobgp`コマンドつまりCLIで設定していきます。下記が`/etc/gobgpd.conf`の中身になります。

```toml:/etc/gobgpd.conf
[global.config]
  as = 1000
  router-id = "10.10.10.1"

[zebra]
[zebra.config]
  enabled = true
  url = "unix:/var/run/frr/zserv.api"
  redistribute-route-type-list = ["connect"]
  software-name = "frr7.2"
  version = 6
```

`[global.config]`がないと`gobgpd`は動いてくれません。AS番号、router-idは適宜変更を。

この設定のポイントは`[zebra]`以降です。これを書いておくことで、GoBGPは経路交換して得た経路をカーネルに流し込む(FIBに反映する)ようになります。**書いておかないとカーネルには経路が流し込まれません。**

`redistiribute-route-type-list`はお好みで。重要なのは最後の2行。ドキュメントをしっかり読むと書いてあるのですが、少なくとも今回試している環境では、`version`だけでは動きません。プロセスは動作していて、設定もできているのに、経路が反映されません。**`version`と`software-name`両方指定する必要があります**。

ドキュメントに記載されている例をコピペして、中身を読まないでいるとハマる(そして、ソースコーを眺めて条件に気づく)というオチでしたorz

# FRRと連携するための変更

`/etc/systemd/system/multi-user.target.wants/gobgpd.service`を編集します。

- `DynamicUser=yes`行の削除
- 削除した箇所に`User=frr`行の追加

`/var/run/frr/zserv.api`はプロセス間通信のためのソケットファイルなのですが、アクセス権限を見るとユーザ`frr`でしかアクセスできないようになっています。

```
$ ls -l /var/run/frr/zserv.api 
srwx------ 1 frr frr 0 Feb 17 23:39 /var/run/frr/zserv.api
```

GoBGPがFRRと連携するには、`zserv.api`ファイルのアクセス権限を変更するか、`gobgpd`を許可されているユーザで動作させる必要があるのですが、ここでは後者を選択したということになります。

本当はどうやるのが正解なのかよくわからないままです。

# GoBGPの起動

システムごと再起動するもよし、`sudo systemctl start gobgpd.service` するもよし。

# 起動直後の状態

`172.21.0.2/24`と`192.168.0.2/24`の2本足ルータの想定です。

```
$ ip route
default via 192.168.122.1 dev ens3 proto dhcp src 192.168.122.7 metric 100 
172.21.0.0/24 dev ens5 proto kernel scope link src 172.21.0.2 
192.168.0.0/24 dev ens4 proto kernel scope link src 192.168.0.2 
192.168.122.0/24 dev ens3 proto kernel scope link src 192.168.122.7 
192.168.122.1 dev ens3 proto dhcp scope link src 192.168.122.7 metric 100 
```

なお、上記例での`192.168.122.7/24`はマネジメント用の足です。

# CLIでの設定

neighbor(BGPをおしゃべりするお隣さん)の情報と、広報する経路の追加をやってみます。

```
$ sudo gobgp neighbor add 172.21.0.1 as 2000
$ sudo gobgp global rib add 192.168.0.0/24
```

なお、`context deadline exceeded`と言われる場合、`gobgpd`は動いていません。`/etc/gobgpd.conf`の記述ミスがないかなどチェックしましょう。

コマンドを実行すると、GoBGP側は下記のようになりました。

```
$ gobgp global
AS:        1000
Router-ID: 10.10.10.1
Listening Port: 179, Addresses: 0.0.0.0, ::
$ gobgp neighbor
Peer         AS  Up/Down State       |#Received  Accepted
172.21.0.1 2000 00:00:45 Establ      |        4         1
$ gobgp global rib
   Network              Next Hop             AS_PATH              Age        Attrs
*> 10.0.0.0/24          172.21.0.1           2000                 00:00:47   [{Origin: i} {Med: 0}]
*> 172.21.0.0/24        0.0.0.0                                   00:05:11   [{Origin: i} {Med: 0}]
*> 192.168.0.0/24       0.0.0.0                                   00:00:49   [{Origin: i} {Med: 0}]
*> 192.168.122.0/24     0.0.0.0                                   00:05:11   [{Origin: i} {Med: 0}]

$ ip route
default via 192.168.122.1 dev ens3 proto dhcp src 192.168.122.7 metric 100 
10.0.0.0/24 via 172.21.0.1 dev ens5 proto bgp metric 20 
172.21.0.0/24 dev ens5 proto kernel scope link src 172.21.0.2 
192.168.0.0/24 dev ens4 proto kernel scope link src 192.168.0.2 
192.168.122.0/24 dev ens3 proto kernel scope link src 192.168.122.7 
192.168.122.1 dev ens3 proto dhcp scope link src 192.168.122.7 metric 100 
```

`10.0.0.0/24`が増えているのがわかるかと思います。AS番号2000のお隣さん(`172.21.0.1`)が広報している経路です。無事経路情報を受け取ってカーネルのFIBに反映させることができました。

# おわりに

ドキュメントをよく読みましょう。