Linux環境のFRRoutingでBFDを設定する手順:OSPFとBGPで1秒未満の障害検知を実現

Network tutorial - IT technology blog
Network tutorial - IT technology blog

実際の現場で起きる問題:物理リンクはUpなのに通信が全滅するケース

深夜2時、バックエンドAPIクラスタ全体のタイムアウトによりPagerDutyのアラートが鳴り響きました。急いで飛び起き、データセンターにあるUbuntuゲートウェイへSSH接続しました。FRRouting上のBGPおよびOSPFセッションは、依然としてEstablishedやFullの正常ステータスを示しています。しかし、実際のトラフィックは完全に0 Mbpsへと急落していました。

原因は、中間スイッチにある光メディアコンバーターのマイクロコントローラーがフリーズしたことでした。サーバーのNICに接続されたポートには給電が続いており、リンクLEDも点灯したままです。そのためLinuxカーネルは背後の回線が途絶していることに全く気づけず、結果としてすべてのパケットがブラックホールへと吸い込まれ続けていました。

このボトルネックは、各ルーティングプロトコルにおけるデフォルトのキープアライブ機構に起因します。

  • OSPF: Helloタイマーが10秒、Deadタイマーは最大40秒。ネットワークの迂回切り替えに約1分近くかかります。
  • BGP: デフォルトのKeepaliveは60秒、Holdタイマーは180秒にも及びます。つまり、BGPルーターがneighborのダウンを認識するまでに丸々3分間トラフィックが失われ続けます。

OSPFのHelloタイマーを1秒まで短縮すればよいのでしょうか? 可能ではありますが、数十台のneighborが存在する場合、ルーターのCPU負荷が急増して動作が不安定になります。そもそもOSPFはミリ秒単位の検知を想定して設計されていません。そこで必要となるのがBFD(Bidirectional Forwarding Detection – RFC 5880)です。

BFDはUDP(single-hopはポート3784、echoはポート3785)経由でデータプレーン層において独立して動作します。BFDパケットは数十バイト程度と極めて軽量で、CPU消費も0.1%未満に抑えられます。その唯一の役割は、ミリ秒間隔で高頻度のハンドシェイクを行うことです。パケットを連続で3回ロストすると、BFDは即座にOSPF/BGPのneighborセッションを切断します。これにより、ルーティングテーブル全体が300ms未満で予備経路へと高速収束(コンバージェンス)します。

FRRoutingのインストールとBFDデーモンの有効化

FRRouting(FRR)は現在、Quaggaに代わるLinux向けの標準的なルーティングスイートです。bfddの全機能を利用するには、Ubuntuのデフォルトaptリポジトリではなく、FRR公式リポジトリからインストールすることを推奨します。

# 1. FRR公式リポジトリの追加
sudo apt update && sudo apt install -y curl gnupg2 lsb-release
curl -s https://deb.frrouting.org/frr/keys.asc | sudo gpg --dearmor -o /usr/share/keyrings/frrouting.gpg
echo "deb [signed-by=/usr/share/keyrings/frrouting.gpg] https://deb.frrouting.org/frr $(lsb_release -s -c) frr-stable" | sudo tee /etc/apt/sources.list.d/frr.list

# 2. FRRパッケージのインストール
sudo apt update
sudo apt install -y frr frr-pythontools

デフォルトでは、FRRの中核デーモンであるzebraのみが有効になっています。/etc/frr/daemonsファイルを開き、BFD、OSPF、BGPを有効化します。

sudo nano /etc/frr/daemons

対応するフラグを以下のように変更します。

zebra=yes
bgpd=yes
ospfd=yes
ospf6d=no
ripd=no
bfdd=yes

サービスを再起動し、システムの自動起動を有効にします。

sudo systemctl restart frr
sudo systemctl enable frr

OSPFおよびBGP向けのBFD設定手順

検証構成は2台のゲートウェイで構成されます。中間L2スイッチを経由して、Router-A(eth1: 10.10.10.1/30)とRouter-B(eth1: 10.10.10.2/30)が接続されています。

1. vtyshへのアクセス

FRRの統合設定シェルを起動します。

sudo vtysh

2. BFD peerの定義

Router-A側で、送受信間隔を100ms、ロスト検出倍率(detect-multiplier)を3に設定します。ルーターが3パケット連続でロスト(計300ms)した場合、リンク断と判定されます。

configure terminal
bfd
 peer 10.10.10.2 interface eth1
  detect-multiplier 3
  receive-interval 100
  transmit-interval 100
 exit
exit

3. OSPFインターフェースへのBFDの適用

neighborが接続されているインターフェースに直接ip ospf bfdコマンドを追加します。

configure terminal
interface eth1
 ip address 10.10.10.1/30
 ip ospf area 0
 ip ospf bfd
exit

router ospf
 router-id 1.1.1.1
 network 10.10.10.0/30 area 0
exit

ip ospf bfdを1行指定するだけで、OSPFプロセスが自動的にbfddへ登録し、eth1上のneighbor監視を開始します。

4. BGPへのBFDの統合

BGP(eBGPまたはiBGP)の場合、対象の各neighborに直接BFDを関連付けます。

configure terminal
router bgp 65001
 neighbor 10.10.10.2 remote-as 65002
 neighbor 10.10.10.2 bfd
exit

5. Router-B側での対向設定

双方向のBFDハンドシェイクを確立するため、Router-Bでも同様に設定を行います。

configure terminal
bfd
 peer 10.10.10.1 interface eth1
  detect-multiplier 3
  receive-interval 100
  transmit-interval 100
 exit
exit

interface eth1
 ip address 10.10.10.2/30
 ip ospf area 0
 ip ospf bfd
exit

router ospf
 router-id 2.2.2.2
 network 10.10.10.0/30 area 0
exit

router bgp 65002
 neighbor 10.10.10.1 remote-as 65001
 neighbor 10.10.10.1 bfd
exit

# 設定をディスクに保存することを忘れずに実行
write memory

注意: write memoryコマンドは、現在のランタイム設定を/etc/frr/frr.confファイルに書き込みます。この手順を省略すると、再起動時に設定内容がすべて失われます。

ステータス確認と擬似障害テスト

設定保存後、本番環境へ投入する前にBFDセッションが正常に確立されているか確認します。

1. BFDセッションの確認

vtyshでpeerステータスのサマリーを表示します。

show bfd peers

想定される出力結果:

FRR-Router-A# show bfd peers

BFD Peers:
	peer 10.10.10.2 interface eth1
		ID: 219481023
		Remote ID: 198302194
		Status: up
		Uptime: 0 hour(s), 12 minute(s), 18 second(s)
		Diagnostic: ok
		Remote diagnostics: ok
		Receive Interval: 100ms
		Transmit Interval: 100ms
		Remote Receive Interval: 100ms
		Remote Transmit Interval: 100ms

Status: upおよび100msの間隔設定が表示されていれば、両ルーター間でBFDパケットが正常に送受信されていることが確認できます。

2. OSPFおよびBGPがBFDと連携しているかの確認

OSPF neighborの詳細情報を確認します。

show ip ospf neighbor detail

出力内にBFD enabled: status is Upという行が表示されます。続けてBGPを確認します。

show ip bgp neighbors 10.10.10.2

BFD enabled: yes, status: Upが表示されていれば連携成功です。

3. 障害シミュレーションテスト(カオステスト)

中間ネットワークの光ファイバー障害時の挙動を検証するため、Router-B上でiptablesを用いてBFDのUDPポート3784を遮断し、通信途絶をシミュレートします。

# Router-B側で片方向のBFDパケットをドロップ
sudo iptables -I INPUT -p udp --dport 3784 -j DROP

直ちにRouter-Aでログ監視画面を開きます。

show log monitor

即座に以下のようなログが出力されます。

%BFD_PEER_DOWN: BFD peer 10.10.10.2 down
%OSPF-5-ADJCHANGE: Nbr 2.2.2.2 on eth1: Reset (BFD down)
%BGP-5-ADJCHANGE: neighbor 10.10.10.2 Down BFD session down

ドロップ実行から正確に300ms後、OSPFとBGPは即座にneighborを切断しました。ルーティングテーブルは自動的にバックアップ経路へ切り替わり、これまでのように40秒から3分間もトラフィックが停止することはなくなりました。iptablesルールを削除(sudo iptables -D INPUT 1)すると、数ミリ秒でBFDの再ハンドシェイクが行われ、ルーティングがスムーズに復旧します。

Share: