池の上にも

平均以下の理解力で、色々アウトプットしてみるブログ

quagga + mininet で BGP 検証環境を作る その①

BGP を検証できる環境がほしかったので探したところ、quagga + mininet を使った環境が見つかったので、そちらを利用させてもらうことにしました。

BGP Path Hijacking Attack Demo · mininet/mininet Wiki · GitHub

mininet が namespace を使うことで routing table が個別に扱えるようになります。その上で quagga を動作させて、BGP peer をはれる NW 環境が構成できるとのことです。

環境

  • OS: Ubuntu 16.04.3 LTS
  • Memory: 4GB
  • Quagga: version 1.2.1

Installation

1. Git インストール
$ sudo apt install git
2. Mininet インストール
$ git clone git://github.com/mininet/mininet
$ cd mininet
$ git tag
$ git checkout -b 2.2.1 2.2.1
$ cd ..
$ mininet/util/install.sh -nfv

-nfv オプションで mininet とあわせて Open vSwitch もインストールします

3. Quagga インストール
$ sudo apt install libreadline-dev libc-ares-dev
$ wget http://download.savannah.gnu.org/releases/quagga/quagga-1.2.1.tar.gz
$ tar xvzf quagga-1.2.1.tar.gz
$ cd quagga-1.2.1
$ ./configure --enable-multipath=0
$ make
$ sudo make install

ECMP も動作確認したかったので、--enable-multipathのオプションもつけました。引数が0だと、ECMP の数を上限なしに設定できます。
quagga ユーザを作っておいて、ldconfiglibzebra.so.1を読み込んでおきます。

$ sudo adduser --system --no-create-home --group quagga
$ sudo ldconfig
$ ldconfig -p | grep -i zebra
4. BGP サンプル環境をインストール
$ git clone https://bitbucket.org/jvimal/bgp.git
$ sudo bash -c "curl -kL https://bootstrap.pypa.io/get-pip.py | python"
$ sudo pip install termcolor

これで、bgp/bgp.py を起動すれば、quagga が各 Switch で動作した mininet が起動するのですが、zebra/bgpd のパスが違っていたりするので修正しておきます。
(追記) 加えて、zebra/bgpd が使う Zserv API のソケットのパス(-z オプションで指定)を追加しておきます。

--- a/bgp.py
+++ b/bgp.py
@@ -140,9 +140,9 @@
-        router.cmd("/usr/lib/quagga/zebra -f conf/zebra-%s.conf -d -i /tmp/zebra-%s.pid  > logs/%s-zebra-stdout 2>&1" % (router.name, router.name, router.name))
+        router.cmd("/usr/local/sbin/zebra -f conf/zebra-%s.conf -d -i /tmp/zebra-%s.pid -z /tmp/zebra-%s.sock > logs/%s-zebra-stdout 2>&1" % (router.name, router.name, router.name, router.name))
         router.waitOutput()
-        router.cmd("/usr/lib/quagga/bgpd -f conf/bgpd-%s.conf -d -i /tmp/bgp-%s.pid > logs/%s-bgpd-stdout 2>&1" % (router.name, router.name, router.name), shell=True)
+        router.cmd("/usr/local/sbin/bgpd -f conf/bgpd-%s.conf -d -i /tmp/bgp-%s.pid -z /tmp/zebra-%s.sock > logs/%s-bgpd-stdout 2>&1" % (router.name, router.name, router.name, router.name), shell=True)
         router.waitOutput()


修正後に quagga + mininet を起動します。

$ cd bgp
$ sudo ./bgp.py

BGP ルータに接続

./connect.sh <Router名> で接続します。ですが、ps コマンドからノード名を取得するための正規表現が合っていなかったので、スクリプトを少し書き換えます。

--- a/run.py
+++ b/run.py
@@ -16,7 +16,7 @@
-node_pat = re.compile(r'.*bash ... mininet:(.*)')
+node_pat = re.compile(r'.*bash --norc -is mininet:(.*)')

その後に、./connect.sh <Router名> で接続します。telnet login/enable の password は、いずれも en です。

$ ./connect.sh R2
Connecting to R2 shell
Trying ::1...

Connected to localhost.
Escape character is '^]'.

Hello, this is Quagga (version 1.2.1).
Copyright 1996-2005 Kunihiro Ishiguro, et al.


User Access Verification

Password: 
bgpd-R2> en
Password: 
bgpd-R2# 


(追記) zebra に接続する際は、connect.sh の telnet localhost bgpdtelnet localhost zebra に書き換えて接続します。また、quagga から設定変更やログの書き込みができるように、設定/ログ用のディレクトリとファイルのパーミッションを変更しておく必要があります。

$ chown :quagga conf
$ chown :quagga conf/*
$ chown :quagga logs

トポロジを変更する

デフォルトのトポロジは、とてもシンプル(R1---R2---R3)なので、topology.py の中身を変更してトポロジを好きなように変更します。トポロジを変更してノード名を変えた場合は、conf/配下にノードに対応する設定ファイルを作る必要があります。特に zebra に対応する設定では loopback の設定を残しておかないと connect.sh で接続ができなくなるので注意が必要です。