GoBGPの検証環境のセットアップ

GoBGPをいろいろ触ってみるにあたって、テンプレート的に使えるベーシックな BGPネットワーク検証環境を構築する。

目次

  1. 作成する環境
  2. VMを作る
  3. ネットワークを作る
  4. GoBGPの設定
  5. BGPセッションの確認
  6. まとめ

作成する環境

f:id:subaruf:20200719005209p:plain

VMを作る

KVM上で動作するこんな感じのVMを3台分作る。

f:id:subaruf:20201009002411p:plain

ubuntuをインストール

ubuntuのディスクイメージを下記から取得する。
bionic-server-cloudimg-amd64-disk.img

ubuntuを含む主要なディストリビューションのイメージのダウンロードリンクはOpenStackのDocサイトにリンクがまとめてあります。

パスワードを設定する。

$ cat >use-data <<EOF
> #cloud-config
> password: root
> chpasswd: {expire: False }
> ssh_pwauth: True
> EOF
$ cloud-localds user-data.img user-data
$ qemu-system-x86_64 \
> -drive file=bionic-server-cloudimg-amd64.img,format=qcow2 \
> -drive file=user-data.img,format=raw \
> -m 10G

VM上でGoをインストール

$ wget https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.14.4.linux-amd64.tar.gz
$ export PATH=$PATH:/usr/local/go/bin

VM上でGoBGPをインストール

GoBGPのREADMEにはバイナリのインストールリンクが貼ってあるが、GoBGPのコードはいじる予定なのでとりあえずgo getする。

$ sudo apt install gcc
$ go get github.com/osrg/gobgp/gobgpd
package github.com/osrg/gobgp/gobgpd: cannot find package "github.com/osrg/gobgp/gobgpd" in any of:
        /usr/local/go/src/github.com/osrg/gobgp/gobgpd (from $GOROOT)
        /home/ubuntu/go/src/github.com/osrg/gobgp/gobgpd (from $GOPATH)
$ go get github.com/osrg/gobgp/gobgp
package github.com/osrg/gobgp/gobgp: cannot find package "github.com/osrg/gobgp/gobgp" in any of:
        /usr/local/go/src/github.com/osrg/gobgp/gobgp (from $GOROOT)
        /home/ubuntu/go/src/github.com/osrg/gobgp/gobgp (from $GOPATH)

"GoBGP インストール"でヒットしたサイトにあったコマンドをコピペしてgo getしたがなんかエラーがでてる。
そして、バイナリも生成されてないようだ。
とりあえず、git cloneはできているようなので、手動でビルドしてしまう。

$ cd ~/go/src/github.com/osrg/gobgp/cmd/gobgp
$ go build
$ cd ~/go/src/github.com/osrg/gobgp/cmd/gobgpd
$ go build
$ mkdir ~/go/bin
$ mv ~/go/src/github.com/osrg/gobgp/cmd/gobgpd/gobgpd ~/go/bin
$ mv ~/go/src/github.com/osrg/gobgp/cmd/gobgp/gobgp ~/go/bin
$ export PATH=$PATH:~/go/bin

VM上でFRRをインストール

GoBGPとカーネルFIBとのインターフェースにはzebraを使用する。
そのためにFRRをインストールする。

$ curl -s https://deb.frrouting.org/frr/keys.asc | sudo apt-key add -
$ FRRVER="frr-stable"
$ echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) $FRRVER | sudo tee -a /etc/apt/sources.list.d/frr.list
$ sudo apt update && sudo apt install frr frr-pythontools

FRR7.3ではzebraとwatchfrrはデフォルトで有効になっているため、デーモンの有効化設定はデフォルトからいじる必要はない。

VMNICの設定

VMはデフォルトのNICを管理インターフェースとして使用し、それとは別に4つのデータ転送用インターフェース(NIC)を持つようにする。
そして下図のようにNICとL2SW(bridge)を1:1でを作成していく。
こうすることで下図の赤いケーブルを他のL2SWに付け替えて、自由にトポロジーが組めるようになる。

f:id:subaruf:20200719005409p:plain

VMにおけるNICの設定例

新たに作成するデータ転送用インターフェースはホストマシンからはvpcX_ethYという名前で見えるようにする。
また、vpcX_ethYというNICがデフォルトで接続されるL2 switchはvpcX_ethY_brと名付ける。

該当部分抜粋

    <interface type='bridge'>
      <source bridge='vpc3_eth1_br'/>
      <target dev='vpc3_eth1'/>
      <model type='virtio'/>
    </interface>
    <interface type='bridge'>
      <source bridge='vpc3_eth2_br'/>
      <target dev='vpc3_eth2'/>
      <model type='virtio'/>
    </interface>
    <interface type='bridge'>
      <source bridge='vpc3_eth3_br'/>
      <target dev='vpc3_eth3'/>
      <model type='virtio'/>
    </interface>
    <interface type='bridge'>
      <source bridge='vpc3_eth4_br'/>
      <target dev='vpc3_eth4'/>
      <model type='virtio'/>
    </interface>

ブリッジの作成

上述の図でいう所のL2SWをホストOSから作成する。 シェルスクリプトでやってもいいが、PCを再起動した後にいちいち実行するのも面倒なので、今回はubuntu18.04におけるデフォルトのネットワーク管理ツールであるnetplanで行った。

該当部分抜粋

  bridges:
    vpc1_eth1_br:
      dhcp4: false
    vpc1_eth2_br:
      dhcp4: false
    vpc1_eth3_br:
      dhcp4: false
    vpc1_eth4_br:
      dhcp4: false
    vpc2_eth1_br:
      dhcp4: false
    vpc2_eth2_br:
      dhcp4: false
    vpc2_eth3_br:
      dhcp4: false
    vpc2_eth4_br:
      dhcp4: false
    vpc3_eth1_br:
      dhcp4: false
    vpc3_eth2_br:
      dhcp4: false
    vpc3_eth3_br:
      dhcp4: false
    vpc3_eth4_br:
      dhcp4: false

ネットワークを作る

こんな感じのトポロジーを組む。

f:id:subaruf:20200719005213p:plain

黄緑色の部分(LAN)はvpc1とvpc2のVM上でnamespaceを作って実現する。 各VMのens3は管理インターフェースになる。これはFRRからマネージメント用のVRFに入れてやる。

ルータのディスクイメージ量産

共通の設定は前述の通りなので、VMのディスクイメージを必要な分だけ量産する。

$ cp bionic-server-cloudimg-amd64.img vpc1.qcow2
$ cp vpc1.qcow2 vpc2.qcow2
$ cp vpc1.qcow2 vpc3.qcow2
$ sudo cp vpc1.qcow2 vpc2.qcow2 vpc3.qcow2 /var/lib/libvirt/images/

management VRFの設定

management VRF用ネームスペースの作成

managementというネームスペースを作って上げて、それに管理インターフェースであるens3を入れてやる。
再起動毎にこの作業をするのはとても大変なので、initdで設定する。

cd /etc/init.d/
vi bgp-setup
chmod +x bgp-setup
ln -s /etc/init.d/bgp-setup /etc/rc3.d/S01bgp-setup

/etc/init.d/bgp-setupの内容は以下の通り。

#!/bin/sh

ip netns add management
ip link set ens3 netns management

FRR側の設定

デフォルト以外のVRFをFRRで使用するために/etc/frr/daemonsを編集してzebraの起動オプションを編集する。

zebra_options="  -A 127.0.0.1 -s 90000000 -n"

下のコンフィグはvpc1のものだが、vpc2およびvpc3についても同様に設定を行う。

!
vrf management
 netns /run/netns/management
 exit-vrf
!
interface ens3 vrf management
 ip address 192.168.122.101/24
!

アドレス設定

FRRのvtyshから以下を設定する。

vpc1の設定

interface ens9
 ip address 10.10.1.1/24
!
interface ens11
 ip address 192.168.1.254/24
!
interface lo
 ip address 1.1.1.1/32
!
router-id 1.1.1.1

vpc2の設定

interface ens10
 ip address 10.10.2.2/24
!
interface ens11
 ip address 192.168.2.254/24
!
interface lo
 ip address 2.2.2.2/32
!
router-id 2.2.2.2

vpc3の設定

interface ens9
 ip address 10.10.1.3/24
!
interface ens10
 ip address 10.10.2.3/24
!
interface lo
 ip address 3.3.3.3/32
!
router-id 3.3.3.3

LANの設定

vpc1における/etc/init.d/bgp-setupを次の通りアップデートする。

#!/bin/sh

ip netns add management
ip link set ens3 netns management

ip netns add lan
ip link set ens12 netns lan
ip netns exec lan ip addr add 192.168.1.1/24 dev ens12
ip netns exec lan ip link set ens12 up
ip netns exec lan ip link set lo up

vpc2における/etc/init.d/bgp-setupを次の通りアップデートする。

#!/bin/sh

ip netns add management
ip link set ens3 netns management

ip netns add lan
ip link set ens12 netns lan
ip netns exec lan ip addr add 192.168.2.1/24 dev ens12
ip netns exec lan ip link set ens12 up
ip netns exec lan ip link set lo up

配線

配線の設定をホスト側で行う。 ホストOSの再起動後でも同じ設定ができるようにスクリプトにしておく。

#!/bin/bash

ip link set dev vpc1_eth1 nomaster
ip link set dev vpc2_eth2 nomaster
ip link set dev vpc1_eth1 master vpc3_eth1_br
ip link set dev vpc2_eth2 master vpc3_eth2_br

ip link set dev vpc1_eth4 nomaster
ip link set dev vpc1_eth4 master vpc1_eth3_br
ip link set dev vpc2_eth4 nomaster
ip link set dev vpc2_eth4 master vpc2_eth3_br

配線はこんな感じになる。

virbr0          8000.525400dde315       yes             virbr0-nic
                                                        vpc1_eth0
                                                        vpc2_eth0
                                                        vpc3_eth0
vpc1_eth1_br            8000.000000000000       yes
vpc1_eth2_br            8000.fe540097466c       yes             vpc1_eth2
vpc1_eth3_br            8000.fe540010d4f6       yes             vpc1_eth3
                                                        vpc1_eth4
vpc1_eth4_br            8000.000000000000       yes
vpc2_eth1_br            8000.fe5400a690fa       yes             vpc2_eth1
vpc2_eth2_br            8000.000000000000       yes
vpc2_eth3_br            8000.fe54004206e7       yes             vpc2_eth3
                                                        vpc2_eth4
vpc2_eth4_br            8000.000000000000       yes
vpc3_eth1_br            8000.fe54004127a5       yes             vpc1_eth1
                                                        vpc3_eth1
vpc3_eth2_br            8000.fe540009460a       yes             vpc2_eth2
                                                        vpc3_eth2
vpc3_eth3_br            8000.fe54001559bf       yes             vpc3_eth3
vpc3_eth4_br            8000.fe5400843c38       yes             vpc3_eth4

GoBGPの設定

vpc1の設定ファイル

global:
    config:
        as: 100
        router-id: 1.1.1.1
neighbors:
    - config:
        neighbor-address: 10.10.1.3
        peer-as: 300

vpc2の設定ファイル

global:
    config:
        as: 200
        router-id: 2.2.2.2
neighbors:
    - config:
        neighbor-address: 10.10.2.3
        peer-as: 300

vpc3の設定ファイル

global:
    config:
        as: 300
        router-id: 3.3.3.3
neighbors:
    - config:
        neighbor-address: 10.10.1.1
        peer-as: 100
    - config:
        neighbor-address: 10.10.2.2
        peer-as: 200

BGPセッションの確認

vpc1, vpc2, vpc3それぞれでgobgpdを動かす。

/home/ubuntu/go/bin/gobgpd -t yaml -f /home/ubuntu/config/gobgpd.yml &

それぞれでneighbor statusをチェック
vpc1

# /home/ubuntu/go/bin/gobgp neighbor
Peer       AS  Up/Down State       |#Received  Accepted
10.10.1.3 300 00:58:55 Establ      |        0         0

vpc2

# /home/ubuntu/go/bin/gobgp neighbor
Peer       AS  Up/Down State       |#Received  Accepted
10.10.2.3 300 00:59:08 Establ      |        0         0

vpc3

# /home/ubuntu/go/bin/gobgp neighbor
Peer       AS  Up/Down State       |#Received  Accepted
10.10.1.1 100 00:59:01 Establ      |        0         0
10.10.2.2 200 00:59:09 Establ      |        0         0

まとめ

とりあえず、目的としていた環境ができた。
ちょっとした不満を言えば、コンフィグの問題なのかGoBGPの仕様なのか分からないが、BGP neighborとしてピアのrouter-idを指定した時、セッションを張ることができなかった。