drumato.com

about
contacts
免責事項
ライセンス
記事一覧
日記一覧
ENGLISH
GoBGPでipv4 unicast addressを広報してみる

GoBGPでipv4 unicast addressを広報してみる

bgpgobgp

この記事はBGPに入門したての時期に試行錯誤しながら書いたものであり, 情報の正確性については保証しかねますので,ご了承ください.

前回の続き.
まだ読んでない方はそちらを.

リーディング対象は,2021/3/25現在のmasterのHEAD
GoBGPのライセンスはApache License 2.0.
ライセンス表記をしておく.

1Copyright (C) 2014-2017 Nippon Telegraph and Telephone Corporation.

今回は実際にPeerに対して経路広報を行う.
BGP UPDATE Messageをキャプチャして,
各フィールドにどんな値が入っているのかを確認する.

本記事の目標

  • コードリーディングの前段階として,CLIアプリを使いつつコマンド体系を把握する
  • 最もシンプルなBGP UpdateメッセージをWiresharkでキャプチャして中身を見る

環境構築と仮説

前回はVMを2つ立ち上げてPeer Establishmentをやってみたが,
経路広報の検証となると,もうちょい大きいネットワークが欲しくなる.
本記事では,以下のようなVMネットワークを作ってみた.

img2

このネットワークで,
ASN001(実際には65001を割り当てている)から 192.168.33.11/32 を広報してみる.

私のBGP前知識が正しければ,
以下のようにAS_PATH attributeを含むUPDATEメッセージが流れるはずである.

img3

node5上でtcpdumpを実行しておき,
UPDATEメッセージの中身を実際に読んでみる.

GoBGPはSDNにおけるControl-Planeの機能のみを提供している.
各BGP Speakerが経路を覚える(=OSのFIBに経路を書き込む)ような機能は存在しない.
それを実現するには,GNU Zebra integration等の機能を利用する必要がある.
本記事はあくまでもBGP Updateの中身を理解するに留めるため,
FIBへの書き込みは行わない.

Vagrantfileの用意

ここでは,次のようなVagrantfileを用意した.

1# -*- mode: ruby -*- 2# vi: set ft=ruby : 3 4Vagrant.configure("2") do |config| 5 config.vm.box = "bento/ubuntu-18.04" 6 7 config.vm.provider :virtualbox do |vb| 8 vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/.","1"] 9 end 10 11 config.vm.define "node1" do |node| 12 node.vm.network "private_network", ip: "192.168.33.11" 13 end 14 15 config.vm.define "node2" do |node| 16 node.vm.network "private_network", ip: "192.168.33.12" 17 end 18 19 config.vm.define "node3" do |node| 20 node.vm.network "private_network", ip: "192.168.33.13" 21 end 22 23 config.vm.define "node4" do |node| 24 node.vm.network "private_network", ip: "192.168.33.14" 25 end 26 27 config.vm.define "node5" do |node| 28 node.vm.network "private_network", ip: "192.168.33.15" 29 end 30end

適当にvagrant upしておく.

Ansible playbookの用意

GoBGPはGitHub Releasesにバイナリが落ちていて,
それを拾ってくるだけで使える.便利.
ということで,それを5台に適用するplaybookを作る.
まずはinventory.
本当はAnsible resources内でパスワードを扱う際は,
適宜ansible-vault create等の機能を使う必要がある.
とはいえ,今回は検証後すぐに破壊するVMなので,特に気にしない.

1[ubuntu] 2192.168.33.11 3192.168.33.12 4192.168.33.13 5192.168.33.14 6192.168.33.15 7 8[all:vars] 9ansible_ssh_user=vagrant 10ansible_ssh_pass=<vm's password>

次にplaybook.

1--- 2- hosts: ubuntu 3 user: vagrant 4 vars: 5 gobgp_version: 2.25.0 6 tasks: 7 - name: download gobgp 8 get_url: 9 url: https://github.com/osrg/gobgp/releases/download/v{{ gobgp_version }}/gobgp_{{ gobgp_version }}_linux_amd64.tar.gz 10 dest: /home/vagrant/ 11 - name: extract gobgp from gz 12 unarchive: 13 src: /home/vagrant/gobgp_{{ gobgp_version }}_linux_amd64.tar.gz 14 dest: /home/vagrant 15 remote_src: yes
1ansible-playbook -i inventory gobgp.yaml

とかして,全VMにgobgpバイナリを落とす.
関係ないけど,私は bgp-testing-environmentなるprivate repositoryを作って,
そこにこのplaybookを置いておいた.
これで検証環境を建てるのは多少楽になったと思う.

経路広報してみる

Peer張る為に必要な設定は省略.
前記事を見てほしい.

それではnode1から経路を流す.

1./gobgp global rib add -a ipv4 192.168.33.11/32 # node1で実行

node1のRIBに経路を追加する,というコマンドそのままの意味.
GoBGPでは経路追加された時点でPeerを張っている他BGP Speakerに経路を流してくれるっぽい.

実際に流れているか確認してみよう.
node2で以下のコマンドを実行してみる.

1$ ./gobgp neighbor # node2で実行 2Peer AS Up/Down State |#Received Accepted 3192.168.33.11 65001 00:32:15 Establ | 1 1 4192.168.33.13 65003 00:32:12 Establ | 0 0 5$ ./gobgp neighbor 192.168.33.11 adj-in 6 ID Network Next Hop AS_PATH Age Attrs 7 0 192.168.33.11/32 192.168.33.11 65001 00:30:04 [{Origin: ?}]

node1から受け取った経路をAdj-RIB-inに格納している.
node3でも同様に確認.

1$ ./gobgp neighbor # node3で実行 2Peer AS Up/Down State |#Received Accepted 3192.168.33.12 65002 00:02:28 Establ | 1 1 4192.168.33.15 65005 00:01:47 Establ | 1 1 5$ ./gobgp neighbor 192.168.33.12 adj-in 6 ID Network Next Hop AS_PATH Age Attrs 7 0 192.168.33.11/32 192.168.33.12 65002 65001 00:00:28 [{Origin: ?}]

node2はAS_PATH属性に自身のASNを書き込んで,node3にadvertiseしてきたっぽい.
出力を見るとわかるけど,node5からもadvertisementが飛んできている.
最後に,node5でも確認してみる.

1$ ./gobgp neighbor 2Peer AS Up/Down State |#Received Accepted 3192.168.33.13 65003 00:34:31 Establ | 1 1 4192.168.33.14 65004 00:34:33 Establ | 1 1 5$ ./gobgp neighbor 192.168.33.13 adj-in 6 ID Network Next Hop AS_PATH Age Attrs 7 0 192.168.33.11/32 192.168.33.13 65003 65002 65001 00:32:51 [{Origin: ?}] 8$ ./gobgp neighbor 192.168.33.14 adj-in 9 ID Network Next Hop AS_PATH Age Attrs 10 0 192.168.33.11/32 192.168.33.14 65004 65001 00:32:53 [{Origin: ?}]

PeerごとのAdj-RIB-inを確認すると,
仮説通りにAS_PATH属性にASNが書き込まれているのが確認できた.
とりあえず,最低限やりたかったことは達成.

おそらくだけど,
同じ 192.168.33.11/32 というIPに対して得られた2つの経路をベストパス選択アルゴリズムに入力し,
最終的にAS_PATHが短い( 192.168.33.14 にホップさせる)経路を学習すると思う.

そして,もしnode5が新たに別のBGP SpeakerとPeerを張ったとき,
Adj-RIB-outにはベストパス選択アルゴリズムを"生き残った"最適経路が書き込まれ,
AS_PATH: [65005, 65004, 65001] の経路を送信すると思う.

Updateメッセージを覗いてみる

最後に,
node5でキャプチャしていたBGP Messageの中身を見てみる.
具体的には,node4から届いたUpdate.

  • BGP Message Header
    • 前回紹介したので省略
  • UPDATE Message
    • Unfeasible Routes Length/2octet ... Withdrawn Routesフィールドの長さ
      • 0ならWithdrawn Routesは未使用
    • Withdrawn Routes/variable ... 到達できなくなりネットワークから削除される経路のリスト
    • Total Path Attributes Length/2 ... Path Attributesフィールドの長さ
      • この値からNLRIの長さを計算することもできる
        • このフィールドが0ならNLRIは存在しない
    • Path Attributes/variable ... パス属性のリスト
      • <attribute type, attribute length, attribute value>という構成
      • ORIGIN ... 経路情報がどのようなプロトコルで生成されたものかを表す
      • AS_PATH ... UPDATEメッセージが経由したASのリスト
      • NEXT_HOP ... 経路情報の出口となる Border Router のアドレス
        • NLRIに到達するためにルーティングするルータアドレス
        • 前記事で省略した extended-nexthop はこのフィールドサイズを拡張するもの
          • おそらくipv6ネットワークの経路広報ではパス属性の extended-lengthビットが立つ?
    • Network Layer Reachability Information/variable ... ip-prefixで示される宛先

あくまで簡単にだけど,まとめるとこんな感じ.
各フィールド/パス属性について,まだまだ考えなきゃいけないことはたくさんあるけど,
まずはシンプルなケースを理解できた.

まとめ

今回はシンプルなケースでの経路広報を動かしてみて,
UPDATEメッセージの中身を覗いてみた.

次からはいよいよGoBGPの実装を読んでいく.
とても楽しみ.

参考資料