LGTM

Looks Good To Me

BGP Flowspec のバリデーション

BGP ルーターには,Flowspec という機能があります.2009年にRFC5575 として標準化されたもので,ざっくり言えば「遠くのルーターでパケットフィルターを発動させる」機能.

最近 注目されているこのFlowspec のうち,とくにバリデーションについて調べました.

2015-05-28 追記

@shtsuchi さんに指摘をもらい,IOS-XRv の実装が分かりましたので 追記しました.Flowspec ちゃんと動きます.コメントありがとうございました!

2023-01-31 追記

@a16tochjp さんに JUNOS 実装についてコメントをもらい,RFC9117 について追記しました.ありがとうございました!

ところで,使われてるの?

当初脚光を浴びましたが 大規模にデプロイする事業者がなく,その後しばらく下火でした.ここ数年でコンテンツプロバイダー中心にアーリーアダプターが使いはじめ,少しずつ注目されてきたのが現状です.

https://www.slideshare.net/Arbor_Networks/aol-flowspec-2015

BGP Flowspec とは

JANOG35 のセッション が詳しいです.

簡単に言えば

  1. トラフィックを特定するためのL3/L4 情報
  2. 特定したトラフィックの処理方法

をBGP に乗せて伝搬させます.

  1. 通常のBGP で言えば「10.0.0.0/8」が入っていたところに「dst prefix=172.16.0.0/16, src prefix=any, proto=1」のような情報が
  2. BGP community のところに「rate-limit させる」のような情報が

入っているイメージです.*1

show route すれば「ああ,素直に出力してるんだな」と分かる程度にそのまま表示されます.

バリデーション?

Flowspec は パケット操作方法をeBGP にも乗せられる強力な機能なので,標準にも厳しくバリデーション方法が指定されています.各ルーターでは,Flowspec 経路それぞれをバリデーションし,valid であればそこに記述されているパケットフィルターを発動させます.

A flow specification NLRI must be validated such that it is considered feasible if and only if:

a) The originator of the flow specification matches the originator of the best-match unicast route for the destination prefix embedded in the flow specification.

b) There are no more specific unicast routes, when compared with the flow destination prefix, that have been received from a different neighboring AS than the best-match unicast route, which has been determined in step a).

By originator of a BGP route, we mean either the BGP originator path attribute, as used by route reflection, or the transport address of the BGP peer, if this path attribute is not present.

けっこう重要そうな項目なのに,これだけだと意味がわかりませんね.メーカーサイトにもわかりやすいドキュメントがなかったので「いくつかの実装を試して確かめました」というのが今回の趣旨です.

試したのはJuniper vSRX (12.1X47-D15.4),Cisco IOS-XRv (5.2.2).ともにFlowspec をFIB にインストールする部分が実装されていないようで,今回はルーティングだけの確認です.

Flowspec のオリジネーターDestination Prefix

a) Flowspec のオリジネーターは,Flowspec 中のdestination prefix に対するベストマッチ経路のものと一致する必要がある

意味がわからない その1.

オリジネーターとは,BGP originator パスアトリビュートかBGP ピアのトランスポートアドレス

とあります.

BGP originator パスアトリビュートには,ORIGINATOR_ID のことですが,ルートリフレクターがクライアントのrouter ID を格納します.トランスポートアドレスは,ピアを張るIPアドレスそのものを指します.ですのでFlowspec ルーターは,RR 構成であれば経路のrouter ID を,そうでなければneighbor IP アドレスを使ってオリジネーターを識別していることになります.

なるほど.iBGP だけの世界なら単純そう.ところがiBGP とeBGP を混ぜて考えると少しわかりにくいかもしれません.

トランスポートアドレスが一致する,とは?

iBGP とeBGP がある構成を考えます.

上の構成では どこにも経路フィルターを設定していません.RTR1 から10.0.0.0/8 の経路を広告し,RTR3 まで伝えます.

この構成でRTR2 にstatic なFlowspec (dst=10.0.0.0/8) を設定したとすると,RTR3 にも伝搬しますが,そこでは該当のFlowspec 経路はvalid になります.通常の経路はRTR1 でオリジネートし,Flowspec はRTR2 でオリジネートしたにも関わらず,です.

これは経路の向きを逆にして,RTR1 上で考えたとしても同じです.

このような動作になるのは,Flowspec ルーターがトランスポートアドレスによってオリジネーターを識別しているからです.ようするに「オリジネーターが同じ」とは,「同じBGP セッションから受信した」と解釈して構いません.*2

ベストマッチ経路とは?

該当のprefix を含有する最小の経路のことです.

たとえばBGP テーブル上に10.0.0.0/8 と10.0.0.0/16 がある場合,dst=10.0.0.0/24 なFlowspec 経路に対するベストマッチ経路は10.0.0.0/16 です.

また,ベストマッチ経路が存在しない場合はFlowspec 経路はinvalid です.

逆に言うとBGP テーブル上に10.0.0.0/8 がある場合は,dst=10.0.0.0/8~/32 までのFlowspec 経路がベストマッチ経路を持ち,valid になる可能性があります.

Destination Prefix が指定されていなかった場合は?

「dst 条件がなかったらどうなんの?」と思った方はするどいですね.

  • Juniper vSRX の場合
    • dst=0.0.0.0/0 相当です.この場合のベストマッチ経路はデフォルトルート(0.0.0.0/0) です.なので,dst 条件のないFlowspec 経路をvalid にするには,デフォルトルートが必要になります.
  • Cisco IOS-XRv の場合
    • オリジネーターバリデーションしません.なので,dst 条件のないFlowspec 経路をvalid にするために,デフォルトルートは必要ありません.

ここまでのまとめ

a) Flowspec のオリジネーターは,Flowspec 中のdestination prefix に対するベストマッチ経路のものと一致する必要がある

というのは,言いかえると

Flowspec 経路と,そのdestination prefix を含む最小の経路は,同じBGP セッションから受信する必要がある

2015-05-28 追記

Cisco IOS-XRv は「iBGP からFlowspec 経路を受信した場合に限り,上のオリジネーターバリデーションをスキップする」という実装になっています.詳しくは後述しますが,Juniper vSRX と動作が違うので注意です.

More Specific な経路があってはいけない,とは?

b) 異なるAS から受信する,more specific な経路がないこと

意味がわからない その2.

こちらも経路フィルターがない構成で,RTR1 とRTR3 から経路を注入します.すると,RTR2 のBGP テーブルに10.0.0.0/8 と10.0.0.0/24 が乗ります.

この状態ではRTR2 上でdst=10.0.0.0/8 なFlowspec 経路はinvalid になり,Flowspec テーブルには乗りません.more specific な/24 の経路があるためです.

「割り当てられた/8 から/24 を他者に割り振る」ような状況も考慮すると,「/8 単位での制御は危険だからやめとくべき」という意図だと思われますが,ちょっと窮屈ですね.

また,今回のテストではなぜか「異なるAS かどうか」は評価されないように見えました.10.0.0.0/24 をiBGP から受信しようが,eBGP から受信しようが,static な経路だろうが,dst=10.0.0.0/8 なFlowspec 経路はinvalid になります.

RFC によると「異なるAS からmore specific 経路が広告された場合のみinvalid」になりそうですが,そのような動作はしません.*3

Destination Prefix が指定されていなかった場合は?
  • Juniper vSRX の場合
    • dst=0.0.0.0/0 相当なので,デフォルトルート以外の経路が存在しない場合に限り 該当のFlowspec 経路はvalid になります.通常そんなことはありえないので,destination prefix が指定されていないFlowspec は常にinvalid です.
  • Cisco IOS-XRv の場合
    • more specific バリデーションしません.destination prefix が指定されていないFlowspec もvalid になる可能性があります.

Flowspec をstatic に設定することができる

ここまでで,Flowspec のバリデーションは

  • Flowspec 経路と,そのdestination prefix を含む最小の経路は,同じBGP セッションから受信している
  • BGP テーブル上に,destination prefix よりmore specific な経路がない

ことを確認するものだ,と理解できます.

この動作に不都合を感じる場合は,Flowspec をstatic に設定することで,設定したルーター上に限りバリデーションをスキップすることができます.

たとえばJUNOS でdst prefix を指定せずFlowspec を有効にしたい場合,該当ルーターすべてにstatic 設定することで実現できます.ただ,「そこまでするならパケットフィルターを書いて回ったほうがいいんでは」と感じます.

ほかにstatic 設定はFlowspec をオリジネートするためにも使われますが,通常はこっちがメインだと思います.

Neighbor やピアグループ単位でバリデーションを無効にできる (2015-05-28 追記)

AS内だけでFlowspec を使う場合など,厳しいバリデーションが邪魔になることがあります.その場合はNeighbor やピアグループ単位でバリデーションをスキップすることができます.

Juniper vSRX:

protocols {
    bgp {
        group ibgp {
            family inet {
                flow {
                    no-validate skip-validation;
                }
            }
        }
    }
}

policy-options {
    policy-statement skip-validation {
        then accept;  # フィルター条件をいろいろ書ける
    }
}

Cisco IOS-XRv

router bgp 64600
 neighbor 192.168.1.20
  address-family ipv4 flowspec
   validation disable

Juniper vSRX とCisco IOS-XRv のちがい (2015-05-28 追記)

destination prefix 指定のないFlowspec の扱いなどに違いはありますが,一番大きな差は

です.Cisco IOS-XRv はdraft-ietf-idr-bgp-flowspec-oid-02 が実装されており,オリジネーターバリデーションが一部変更されています.

Step (a) of the validation procedure specified in RFC 5575, section 6 is redefined as follows:

        a) One of the following conditions MUST hold true:
           o The originator of the flow specification matches the
             originator of the best-match unicast route for the
             destination prefix embedded in the flow specification.
           o The AS_PATH and AS4_PATH attribute of the flow
             specification are empty.
           o The AS_PATH and AS4_PATH attribute of the flow
             specification does not contain AS_SET and AS_SEQUENCE
             segments.

簡単に言えば「iBGP からFlowspec 経路を受信した場合に限り,上のオリジネーターバリデーションをスキップする」です.オリジネーターがベストマッチ経路と一致しない場合や,ベストマッチ経路が存在しない場合でもvalid になる可能性があります.

RFC9117 (2023-01-31 追記)

現在👆のI-Dは RFC9117 になっています.

datatracker.ietf.org

未確認ですが,多くの実装で iBGP から受信したFlowspec 経路に関するバリデーションをスキップすると思われます。@a16tochjp さんのコメントによると「JUNOSもそうなっている」とのことです.

その他

どう使うか?

今回のIOS-XRv のように期待通り動かないことや,CloudFlare でのトラブル のような例もあります.議論の余地はありますが,現状だと まだ「コミュニティに知見が足りないため検証するしかないが,コストに対して得られるメリットが小さい」場合が多そうです.

一方で「用途を限ればすごく便利で,コスト問題も解決できるかも」と感じています.

たとえば,次のような使い方はよさそう.

  • DDoS 対策など,小さいdst prefix を守るために使う

    • dst prefix が広い場合,more specific バリデーションで落とされる可能性が高い
    • more specific 経路が無ければ大きいdst prefix でも動くが,いちいち確認するのが手間
  • exabgp のようなAPI 豊富なソフトウェアルーターを使い,Flowspec を注入する

    • 自動化のため
  • AS ボーダーでフィルターする目的で,ソフトウェアルーターは1段階だけ下流ルーターとピアする

    • 小さいdst prefix を守りたい場合,その経路はおそらく下流からくる
    • トランスポートアドレスバリデーションにより,AS ボーダーでのみFlowspec が動くと期待できる
  • 特定のルーターでのみ発動させたい場合は,BGP community で制御

強力なので,ハマれば便利そうですが…どうでしょうかね. 「こういう使い方できそう」「こうやってる」などなど,ぜひご意見ください!

*1:1. はMP_REACH_NLRI or MP_UNREACH_NLRI で,2. はExtended BGP community

*2:厳密に言えばこれは間違っていて,たとえばRR - RR client 間に複数BGP セッションがあった場合は,RR から見てどのセッションから受信してもオリジネーターは同じ

*3:仕様なのかバグなのか,未確認