drumato.com

about
contacts
免責事項
ライセンス
記事一覧
日記一覧
ENGLISH
GoBGPでpeer establishmentをやってみる

GoBGPでpeer establishmentをやってみる

bgpgobgp

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

BGPの勉強をする上で,しっかり実装まで追いたかったのでコードリーディングしつつメモを残す.
ざっと調べるだけでも,BGPを実装するOSSはいくつか存在する.

  • FRRouting ... IPv4/v6 routing protocol suite
    • BGP以外にもOSPF/RIPを含む多くのルーティングプロトコルを実装する巨大OSS
    • C実装
  • exabgp ... Python実装
  • GoBGP ... Go実装
  • RustyBGP ... Rust実装

今回は以下の理由により,GoBGPを対象とする.

  • Go言語で書かれていて読みやすい
  • BGP実装に特化している
    • 最初FRRoutingを読もうと思ったが,なるべくコンパクトに理解したかった

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

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

今回はその第一回として,まずはGoBGPを使ってみることにする.
BGPについての知識整理と,OPENメッセージを飛ばして,BGP Peerの確立を確認する.

本記事の目標

  • コードリーディングの前段階として,CLIアプリを使いつつコマンド体系を把握する
  • BGP Peerを張るときにどのようなメッセージが飛んでいるのか理解する
  • BGP OPENメッセージをWiresharkでキャプチャして中身を見る

GoBGP前提知識

GoBGPのリポジトリを覗いてみると,
Goにおけるプロジェクト構成のベストプラクティスに則っていることがわかる.
cmd/ にはビルドの成果物であるアプリが用意されている.
それぞれ,

  • gobgp ... 後述するgobgpdとinteractionするためのCLIアプリ
  • gobgpd ... BGP実装の本体であるデーモン.
    • gobgpやそれ以外のアプリケーションとは gRPC でやり取りする

という感じ.

ユーザはまずgobgpdを動かす.
gobgpdはconfig-fileに沿って基本的なプロトコル処理を実行する.
例えば,BGP Neighborやポリシーの設定など.
その後,対話的なBGPメッセージの送信/操作等をgobgpコマンドで行う.

BGP Peerの確立

一般的に,CLIアプリは(ライブラリによって異なるが)以下のような設計になる.

  • App 的な構造体がある
  • App にサブコマンドを追加していく
  • App.Run() 的な呼び出しをする

つまり,普通にmain関数から読んでいけば処理を理解できる,というわけではない.
Command.Handler 的なメンバから処理が始まることを考慮する必要がある.

ということで,まずは使ってみる.
それにより,"xx機能はaddコマンドで呼び出せる"みたいなことが把握できる.

環境構築と設定

まず,VMを2つ立てて,仮想ネットワークに接続させる.
このVMにそれぞれ 192.168.33.10192.168.33.11を割り当てる.
(以後node1,node2と呼称)

GoBGPのReleasesに行き,gobgp_2.25.0_linux_amd64.tar.gz のリンクを取得.
各VM上でwget,tarして,ビルド済みのバイナリをダウンロードする.

node1, node2にそれぞれ以下の bgp.toml を作成する.

1# node1の設定ファイル 2[global.config] 3 as = 65001 4 router-id = "192.168.33.10"
1# node2の設定ファイル 2[global.config] 3 as = 65002 4 router-id = "192.168.33.11"

gobgpを動かす

双方で sudo ./gobgpd -f bgp.toml としてデーモンを作成.
別シェルを立ち上げて,

1./gobgp neighbor add 192.168.33.11 as 65002 #node1で実行 2./gobgp neighbor add 192.168.33.10 as 65001 #node2で実行

を実行する.

1$ ./gobgp neighbor #node1で実行した場合 2Peer AS Up/Down State |#Received Accepted 3192.168.33.11 65002 00:12:43 Establ | 0 0

BGP Peerが確立できているのが確認できる.
このように,gobgpを使ってinteractiveにBGPメッセージの送受信が可能.

bgp.toml に設定を書いておくことで,
デーモン起動時にPeer確立させることもできる.
今回の場合,以下のようになる.

1# node1 2[global.config] 3 as = 65001 4 router-id = "192.168.33.10" 5 6[[neighbors]] 7 [neighbors.config] 8 neighbor-address = "192.168.33.11" 9 peer-as = 65002
1# node2 2[global.config] 3 as = 65002 4 router-id = "192.168.33.11" 5 6[[neighbors]] 7 [neighbors.config] 8 neighbor-address = "192.168.33.10" 9 peer-as = 65001

gobgp neighbor で確認

sudo ./gobgpd -f bgp.toml./gobgp neighbor すると,
同様にStateがEstablishedになっているのを確認できる.

より詳しくBGP Peerの情報を確認したい場合,
Peerを張った相手のIPアドレスを指定することで可能.

1$ ./gobgp neighbor 192.168.33.11 # node1で実行 2 3BGP neighbor is 192.168.33.11, remote AS 65002 4 BGP version 4, remote router ID 192.168.33.11 5 BGP state = ESTABLISHED, up for 00:16:21 6 BGP OutQ = 0, Flops = 0 7 Hold time is 90, keepalive interval is 30 seconds 8 Configured hold time is 90, keepalive interval is 30 seconds 9 10 Neighbor capabilities: 11 multiprotocol: 12 ipv4-unicast: advertised and received 13 route-refresh: advertised and received 14 extended-nexthop: advertised and received 15 Local: nlri: ipv4-unicast, nexthop: ipv6 16 Remote: nlri: ipv4-unicast, nexthop: ipv6 17 4-octet-as: advertised and received 18 Message statistics: 19 Sent Rcvd 20 Opens: 1 1 21 Notifications: 0 0 22 Updates: 0 0 23 Keepalives: 33 33 24 Route Refresh: 0 0 25 Discarded: 0 0 26 Total: 34 34 27 Route statistics: 28 Advertised: 0 29 Received: 0 30 Accepted: 0

この出力から多くの情報を得ることができる.

  • Hold Time ... Peerのライフタイム
    • BGP SpeakerはPeer先からUPDATEかKEEPALIVEが一定時間送信されなかった場合Peerを切断する
  • Neighbor Capabilities
    • BGP Speaker同士はOPENメッセージの送信時,"この機能に対応しています"というオプション列を送信する
      • この機能拡張の仕組みを BGP Capabilities という
      • これはOPENメッセージの Optional Parameters フィールドに載っける
    • multiprotocol ... MP-BGPに対応しているかどうか
      • BGP-4のコア仕様1では,IPv4の経路情報しか扱うことができない
      • IPv6に適用するためにMP-BGP2が策定
    • route-refresh ... RFC2918で追加されたBGPメッセージ
      • 経路情報の再送信を要求するメッセージ
    • extended-nexthop ... 次回の記事で取り扱う
    • 4-octet-as ... 4octetでAS numberを表現できるか
  • Message statistics ... ピア間をどのようなBGP Messageが流れたか
  • 経路広報について(広報したか/受け取ったか)

OPENメッセージのパケット解析

node1では sudo tcpdump tcp port bgp -n -w node1.pcap のようにしてパケットキャプチャも走らせておいた.
ということで,OPENメッセージをパケットレベルでも見てみることにする.

  • BGP Message Header
    • Marker/16octet ... BGP Peer間の同期を取るために用いられる領域
      • OPENメッセージの場合ビットはすべて1が立つ
      • Peer間で特別な認証を行う場合には認証情報が書き込まれる
    • Length/2 ... ヘッダを含むBGP Message全体の長さを表現
      • 19~4096の範囲を取る
    • Type/1 ... BGP Message Type
  • Open Message
    • Version/1 ... BGP-4の場合 4
    • My Autonomous System/2 ... 情報を送信するBGP SpeakerのAS number
    • HoldTime/2 ... BGP SpeakerがPeerを切断するまでの時間
      • KEEPALIVEかUPDATEを受け取るとタイマーリセット
    • BGP Identifier/4 ... BGP Speakerの識別子
      • 通常,BGPスピーカの持つIPアドレスのうち1つ
    • Option Parameter Length/1 ... Option Parameterの長さ
      • オプションが使われていなければ 0
    • Option Parameter/variable ... <Option Type, Option Length, Option Value> という形式に
      • 今回の場合 type=2(capabilities), length=22という感じになっていうr
        • capabilitiesのvalueは更に可変長リストになっている3

メッセージヘッダのフィールド数はそこまで多くないので,把握は難しくない.

BGP FSMにおけるOpen Message

BGP FSMを確認すると,
Openメッセージを送信したSpeakerは OpenSent という状態に遷移し,
Peer先からOpenメッセージが送信されてくるのを待つ.
BGP SpeakerどちらもがOpenを送る側と受け取る側を経験すると,
OpenConfirm 状態に遷移する.
この状態でKEEPALIVEの送受信が完了すると,Established状態に遷移して終了.

各状態ではNotificationメッセージが送信される可能性がある.
BGPネットワークでデバッグしたいときはこのNotificationを解析すれば良い.
とはいえ,本記事が対象とするようなミニマムで決め打たれたネットワークでピア確立は失敗しないと思うけど.

まとめ

今回はGoBGPを使って,サクッとPeer確立するまでをやってみた.
次回はVMネットワークをもう少し拡大して,
gobgp global rib add -a ipv4 <ip-prefix> のように経路広報を行い,
どのようにUPDATEメッセージが流れるのかを確認したい.

第三回からコードリーディングできたらいいな.

参考資料

おまけ: ブログの形式について

今までは解説するようなブログの形式が多かったんですが,
書く記事が対象とする技術のレベルが上ってくると,どうしても共有しなければならない事前知識が増えていったりして,
執筆コストが大きくなっちゃうんですよね.

そういった記事を書かなくなる,というわけではないんですが,
普段勉強したことをアウトプットするレベルの記事はメモっぽくしようと思います.
若干ハイコンテキストになってしまいますが,まずは自分にとって有用なものを心がける.

Footnotes

  1. RFC4271

  2. RFC4760

  3. RFC3392( Capabilities Advertisement with BGP-4 )を読むと良い.