LGTM

Looks Good To Me

RIB / FIB コンバージェンスを可視化する方法論

高価なテスターを使わず、なんとかRIB / FIB コンバージェンスを計測することを考えています。

コンバージェンスとは

ネットワークにBGP イベントが到着してから、さまざまな計算を行い、イベントを送信し、定常状態に落ち着くまでのプロセスをコンバージェンスと呼びます。

インターネットルーティングではその所要時間 = コンバージェンスタイムに注目しながら、ネットワークや経路の設計、パラメーターチューニングをします。

RIB コンバージェンスという場合、多くはBGP Update を受信してからのコンバージェンスを指します。

ルーターバイス単体でみれば

1 . BGP Update を受信する
2 . Adj-RIB-In を更新する
3 . 受信フィルターを適用する
4 . Best Path を計算する
5 . Loc-RIB を更新する
6 . FIB を更新する

さらに、BGP Update を伝搬させるべき全てピアについて

7 . 送信フィルターを適用する
8 . Adj-RIB-Out を更新する
9 . BGP Update を送信する

このようなプロセスです。 1~6 を区別して「FIB コンバージェンス」と呼ぶことがあります。

原理的には 6 と 7~9 は並列処理可能ですが、パケットのループやブラックホールを避けるため、一般には 6 の完了を待って 7~9 を処理することが期待されます。

AS 単位 / インターネット全体でみると

一段マクロな視点では、AS にBGP イベントが到着してからAS 全体として処理するべきプロセスを完了することを BGP コンバージェンスと呼ぶことが多いです。インターネット全体でも同じです。

BGP イベント数について

RIB コンバージェンスという言葉のニュアンスには、イベント数の大小は含まれていません。「Prefix x.x.x.x/y のRIB コンバージェンス」「フルルートのRIB コンバージェンス」のように文脈によります。

「BGP コンバージェンス」の定義については、Informational なRFC4098RFC7747 などにまとまっています。

なぜコンバージェンスに注目するのか

ネットワークとしてのインターネットを制御するのに、AS 運用者はピアをし、経路フィルターを更新します。これによってBGP イベントを発生 / 伝搬させるわけですが、最近はコンバージェンスタイムが予測しづらくなってきました。

AS 内部においては

L3 スイッチに代表されるマーチャントシリコン製品が増え、ネットワークとしてカスタムシリコンのような機敏な動きが期待できない場合があります。

フルルートを食えない製品はもちろんのこと、RIB / FIB のハードウェアコンフィグレーションの個体差が大きくなっていると感じます。FIB のLPM (Longest Prefix Match) / LEM (Largest Exact Match) の塩梅まで制御するような取り組みも見られます。

正直なところ、やってみないとわからない。とくに「IPv4 unicast は128k routes までですっ」という製品に、ミスってフルルート入っちゃった場合のRIB / FIB のふるまいなどは予測できません。

また、VM ベースのルーター製品を使うことも増えました。思わぬボトルネックが存在することがあり、ネットワークに組み込む際にはコンバージェンスを気にしておく必要があります。

このような製品が悪というわけではなくて、利用可能な通信技術とハードウェアとソフトウェアをつかって、CAPEX + OPEX を最小化しつつ、要件を満たすネットワークをつくるのがネットワークエンジニアの腕の見せどころなので、避けて通るわけにはいきません。

頭の弱い製品を使ったとしても ネットワークとして安定すればいいわけです。

AS 外 / インターネット全体として

AS 内部のコンバージェンスがうまくいったとしても、インターネット全体として最適でない場合があります。コンバージェンスタイムは短いことが正義ではなく、お隣さんの処理速度に合わせてイベントをフロー制御することが理想です。

コンバージェンスが速すぎてNeighbor ルーターで無駄にCPU リソースを使い、かえって遅くなることもありますし、保守的に長く取りすぎてパケットロスを引き起こす こともあります。

ここでのフォーカス

うまくフィードバックをいれつつ インターネット全体で、特に自分のAS近辺で最適化することがゴールですが、まずはデバイス単体のRIB / FIB コンバージェンス観測を目的とします。

RIB / FIB コンバージェンスを計測する方法論

RFC7747 を参考にします。

eBGP の場合は

+------------+        +-----------+           +-----------+
|            |        |           |           |           |
|            |        |           |           |           |
|   HLP      |        |  DUT      |           | Emulator  |
|  (AS-X)    |--------| (AS-Y)    |-----------|  (AS-Z)   |
|            |        |           |           |           |
|            |        |           |           |           |
|            |        |           |           |           |
+------------+        +-----------+           +-----------+
        |                                            |
        |                                            |
        +--------------------------------------------+

Figure 2: Three-Node Setup for eBGP and iBGP Convergence

(https://tools.ietf.org/html/rfc7747)

このようなセットアップを使い、

5.1.2.  RIB-OUT Convergence

   Objective:

      This test measures the convergence time taken by an implementation
      to receive, install, and advertise a route using BGP.

(https://tools.ietf.org/html/rfc7747)

を計測します。

  1. Emulator から routeA 向けのパケットを HLP に流す
  2. Emulator から routeADUT に広告する
  3. DUTrouteAHLP に広告する
  4. (1 . のパケットが DUT に届き) DUTrouteA 向けのパケットを Emulator に転送する

3. - 2.routeA のRIB コンバージェンス、4. - 2.routeA のFIB コンバージェンスとします。

フルルートについて言えば、

最後の経路の 3. - 最初の経路の 2. がRIB コンバージェンス、最後の経路の 4. - 最初の経路の 2. がFIB コンバージェンスです。

処理するべき経路数によってふるまいが変わる場合があるため、コンバージェンスタイムの値だけで評価するのではなく、

  • 単位時間あたりに受信した経路数 (上の2. に対応)
  • 単位時間あたりに広告した経路数 (上の3. に対応)
  • 単位時間あたりにFIB インストールした経路数

の時間変化をプロットするのがよさそうです。

単位時間あたりにFIB インストールした経路数?

これを実現する妙案が浮かんでいません。ブラックボックステストで実現するべきなので「外部からパケットを入れて出てくるか確認する」アプローチなのは間違いありませんが、全アドレス空間宛てのパケットを常時生成するのは困難なため、

  1. BGP Update 直前か ほぼ同時に、該当Prefix に含まれるいくつかのアドレス宛てにパケットを送信
  2. DUT (Device Under Test) がフォワードするかを確認

おそらくこの形になります。

ただし、1. でどのアドレスを選択するべきかはLPM ベースなのか / LEM ベースなのかで異なりますし、100,000コ目の経路を処理した瞬間に1コ目の経路がRIB / FIB に存在するかも確認したほうがいいかもしれません。

今のところ、このあたりちょっとアイデアがありません。

バイスのstats を取っておきたい

計測中、デバイスのCPU 使用率、メモリ / RIB / FIB 使用量などを同時取得しておくとよさそう。

実装

機敏に動き、API を備えるgobgp を中心に実装してみます。

DUT で

  • 新しい経路を受信した場合
  • Best Path が変わった場合
  • 経路がなくなった場合

それぞれ ふるまいが違う可能性があるため、次のようなシナリオでテストします。

  1. gobgp 1 からフルルートを DUT に送信
  2. gobgp 2 からより強いフルルートを DUT に送信
  3. gobgp 2 から2. のWithdraw を DUT に送信
  4. gobgp 1 から1. のWithdraw を DUT に送信

2つのgobgp を制御して それぞれのシナリオに応じた経路を生成しつつ、それぞれの受信NLRI、送信NLRI を観測するプログラムを書きました。

経路は逐次生成ではなく、フルルートをロードしておいて送信ポリシーを reject → accept に変える、または accept → reject に変える、という方法で実装しています。

github.com

  • gobgp 制御はgRPC でやる
  • gobgp の動作を阻害したくないため、NLRI 観測にはlibpcap をつかう
  • なるべくリアルタイムに処理し、将来的にはFIB コンバージェンス計測にパケットを生成するため、go で実装
    • gobgp のgo APIとBGP パーサーを流用できるメリットもある

TCP を終端せず 観測者として動作させるためだけにTCP Reassemble を実装するのはアホらしいのですが、黙って実装します。

残念ながら、いまのところFIB コンバージェンスは計測できていません。

結果

このプログラムは上の4つのシナリオを順次実行し、結果をjson で保存します。

このチャートは あるVM ルーター製品のもので、毎秒の累積 送信/受信Prefix 数を描いています。テスト環境ではRIB コンバージェンスに7分かかることを示していて、経路数に対してほぼ線形であると予想できます。

コマンドラインオプションで経路数を指定できるので、実際に線形であるか確かめるシェルスクリプトも書けると思います。

余談ではありますが、この製品では、コンバージェンスまでの間CLI 上の送信経路数と実際の観測NLRI 数が大きく違っていました。

まとめ / これからやること

  • 昨今のルーター製品、とくにL3 スイッチ製品のRIB コンバージェンスが予測できないため、ブラックボックステストを行う必要があると考えています
  • その方法論について検討し、実装しました
  • FIB コンバージェンス計測のためのアイデアがありません…コメントお待ちします!!
  • gobgp がテストのボトルネックになる可能性があります。判断のヒントとなりそうな指標をチャートに載せるべきかもしれません

xlogin でコマンド自動投入→手動制御 を繰り返す

  1. コマンド群を入れる
  2. 手動制御
  3. 別のコマンド群を入れる
  4. 手動制御

を大量デバイス上でやりたい、ということがありました。

codeout.hatenablog.com

これを少しいじると便利になります。

# configure.tcl

source [file join [file dirname [info script]] juniper.tcl]

run "configure
set interfaces ge-0/0/0 description foo
show | compare
commit check
"

run "
set interfaces ge-0/0/1 description bar
show | compare
commit check
"

run "
exit
show chassis routing-engine
"

run の中身を入れ終わった後に手動制御になり、^n キーで自動制御に戻って次のrun に移ります。

configure.tcl の隣に juniper.tcl を置いておいてください。

実行例

codeout $ jlogin -s configure.tcl 192.168.0.81
192.168.0.81
set cli complete-on-space on
Enabling complete-on-space

codeout@vsrx> configure
Entering configuration mode

[edit]
codeout@vsrx# set interfaces ge-0/0/0 description foo

[edit]
codeout@vsrx# show | compare
[edit interfaces ge-0/0/0]
-   description "new 1";
+   description foo;

[edit]
codeout@vsrx# commit check
configuration check succeeds

[edit]
codeout@vsrx#                      <-- ここで手動制御に

[edit]
codeout@vsrx# commit
commit complete

[edit]
codeout@vsrx#                      <-- ^n で自動に戻す

[edit]
codeout@vsrx# set interfaces ge-0/0/1 description bar

[edit]
codeout@vsrx# show | compare
[edit interfaces ge-0/0/1]
-   description "new 2";
+   description bar;

[edit]
codeout@vsrx# commit check
configuration check succeeds

[edit]
codeout@vsrx#                      <-- ここで手動制御に

[edit]
codeout@vsrx# commit
commit complete

[edit]
codeout@vsrx#                      <-- ^n で自動に戻す

[edit]
codeout@vsrx# exit
Exiting configuration mode

codeout@vsrx> show chassis routing-engine
Routing Engine status:
    Total memory              2048 MB Max   635 MB used ( 31 percent)
      Control plane memory    1150 MB Max   449 MB used ( 39 percent)
      Data plane memory        898 MB Max   189 MB used ( 21 percent)
    CPU utilization:
      User                       0 percent
      Background                 0 percent
      Kernel                     0 percent
      Interrupt                  0 percent
      Idle                     100 percent
    Model                          FIREFLY-PERIMETER RE
    Start time                     2017-06-13 14:34:07 UTC
    Uptime                         5 minutes, 48 seconds
    Last reboot reason             Router rebooted after a normal shutdown.
    Load averages:                 1 minute   5 minute  15 minute
                                       0.01       0.10       0.07

codeout@vsrx>                      <-- ここで手動制御に

codeout@vsrx> %                                                                                                    codeout $

jlogin の例でした。

Routing protocols' seed metrics for redistributing

When routes are redistributed into another routing protocol, their metrics are also translated to different values depending on vendor implementation and routing protocol which the routes are being redistributed to. Tables below show what value will be chosen when redistributing between protocols with no default metric configured explicitly, that is called as “seed metric”.

The seed metrics listed below are picked from Juniper vSRX and Cisco IOS-XRv default behavior.

Juniper vSRX

from \ to ospf isis rip bgp (med)
direct 0 (E2) 0 (L1/L2) 0 none
static 0 (E2) 0 (L1/L2) 0 none
ospf ospf metric (L1/L2) 0 ospf metric
isis isis metric (E2) 0 none
rip rip metric (E2) rip metric (L1/L2) rip metric
aggregate 0 (E2) 10 (L1/L2) 0 none
bgp bgp med (E2) 10 (L1/L2) 0

Cisco IOS-XRv

from \ to eigrp ospf isis rip bgp (med)
connected variable (*1) 20 (E2) 0 (L2) (x) variable 0
static (x) 2^32-1 20 (E2) 0 (L2) (x) variable 0
eigrp 20 (E2) 0 (L2) (x) variable eigrp metric
ospf (x) 2^32-1 0 (L2) (x) variable ospf metric
isis (x) 2^32-1 20 (E2) (x) variable isis metric
rip (x) 2^32-1 20 (E2) 0 (L2) rip metric
bgp (x) 2^32-1 (*2) 1 (E2) (*2) 0 (L2) (*2) (x) variable
  • (x): default-metric must be configured to redistribute
    • (x) 2^32-1: Default metric is squashed by max value even when default-metric is configured. Note that redistribution cannot be done without default-metric.
    • (x) variable: Metric specified by default-metric is assigned.
  • (*1): Composite metric calculated from interface metrics
  • (*2): router bgp <ASN>; bgp redistribute-internal statement is required to restribute

inet-henge にいくつか機能を足した

inet-henge というネットワーク図生成ライブラリーに

  • リンク太さを変えられる
  • リンク両端に加え,中央にラベルを置ける

地味な機能を足した.

github.com

inet-henge とは?

JSON データを元にネットワーク図を生成してくれる js ライブラリー.オートレイアウトする.

このようなコンセプトで作っている.

  • 自動更新
    • 入力少なく
    • このくらいの外部データから生成したい.手動でレイアウトしたくない
{
  "nodes": [{ "name": "A" },{ "name": "B" }],
  "links": [{ "source": "A", "target": "B" }]
}
  • 美しくなくていい.見てわかる範囲でやってくれれば OK

  • 動かしたい

    • 運用しながら / 設計しながら見る.デバイスやPOP 単位でノードを動かしたい
    • レイアウトは保存しなくてもいい.再計算しても毎回結果が同じならOK
    • ズームしたい.ある程度拡大したときのみ細かい情報を表示したい
    • ブラウザでネットワーク図を表示したその画面で実現したい.ドキュメント内でもやりたい

デモ

youtu.be

Shownet 2016 Network

リンク太さを変える

こんな感じでメタデータを定義しておいて 👇

  "links": [
    { "source": "Node 1", "target": "Node 2", "meta": { "bandwidth": "1G" }},
    { "source": "Node 1", "target": "Node 3", "meta": { "bandwidth": "10G" }},
    { "source": "Node 2", "target": "Node 3", "meta": { "bandwidth": "100G" }}
  ]

こんな感じで描画する.👇 メタデータをもとにSVGstroke-width を返す関数を渡す.

var diagram = new Diagram('#diagram', 'index.json');
diagram.link_width(function (link) {
  if (!link)
    return 1;  // px
  else if (link.bandwidth === '100G')
    return 10; // px
  else if (link.bandwidth === '10G')
    return 3;  // px
});
diagram.init('bandwidth');

何も返さない場合はSVG のデフォルト = 1px になる.

リンクにラベルを置く

こんな感じのリンク情報があったとすると 👇

  "links": [
    {
      "source": "Node 1", "target": "Node 2",
      "meta": {
        "bandwidth": "10G",
        "intf-name": { "source": "interface A", "target": "interface B" }
      }
    }
  ]

こう書くことで 👇

new Diagram('#diagram', 'index.json').init('bandwidth', 'intf-name');

こうなる 👇

スタイルを変える

(追加機能ではないけれど) inet-henge はSVG を出力するので,CSS でスタイルを変えることができる.

.node rect {
  fill: #25271e !important;
  transform: scale(2) translate(-13px, -5px);
}

.node text {
  font-family: sans-serif;
  fill: #fff;
  font-size: 20px;
  transform: translate(0, 5px)
}

.link {
  stroke: #d0e799;
  stroke-opacity: 1;
}

今後

  • LAG をうまく表現できない.なんとかしたい
  • ノード / リンクが増えたときのパフォーマンスが問題.アルゴリズムの調整,計算結果の再利用など考えないといけない

もしご意見などありましたら…気軽にお声がけください!

Large BGP Community がやってくる前に,Community マッチをおさらいしよう

2017 / 02月,BGP Large Communities Attribute (RFC8092) がRFC 化された.

これは新たに 4Bytes:4Bytes:4Bytes のBGP Community を使えるようにするもので,既存の

  • BGP Community (RFC1997) - 2Bytes:2Bytes
  • Extended BGP Community (RFC4360) - 4Bytes:2Bytes もしくは 2Bytes:4Bytes

に比べて空間を広く使うことができる.BGP Community の先頭2バイト(もしくは4バイト) はGlobal Administrator と呼ばれ,ふつうは事業者のグローバルAS番号をあてる.加えて操作対象のAS番号,たとえば顧客のAS番号をBGP Community に含めたいケースがあり,これまでのBGP Community では空間が足りなかった.

近々BGP Community 空間が拡張されるにあたり「いま設定しているBGP Community 正規表現だいじょうぶなんだっけ?」と思って,いくつかの実装でマッチ方法を復習した.

Community マッチ方法

Juniper JUNOS

  • Community 表現(横) がマッチ対象(縦) にマッチするか
  • アルファベットはBGP Community を10進で表現したときの1ケタ.4ケタ = 2Bytes,6ケタ = 4Bytes
  • Large BGP Community 実装はなさそう
⬇️対象 \ 表現➡️ bbb:xxx bbb:xxx.* bbbL:xxx.*
bbb:xxx ⭕️ する ⭕️ する ❌ しない
abbb:xxx ❌ しない ⭕️ する ❌ しない
target:abbb:xxx ❌ しない ⭕️ する ❌ しない
target:aaabbb:xxx ❌ しない ❌ しない ⭕️ する
bbb:xxxy ❌ しない ⭕️ する ❌ しない

想像するに

  • L キーワードの有無で長さマッチ
  • \d+:\d+ パターンであれば^\d+:\d+$ と解釈.それ以外はそのまま

Cisco IOS-XR

  • 正規表現(横) がマッチ対象(縦) にマッチするか
  • アルファベットはBGP Community を10進で表現したときの1ケタ.4ケタ = 2Bytes
  • community-set の例.ほかにextcommunity-set キーワードがある
  • Large BGP Community 実装はなさそう
⬇️対象 \ 表現➡️ bbb:xxx bbb:* ios-regex ‘bbb:xxx’ ios-regex ‘bbb:xxx.*’
bbb:xxx ⭕️ する ⭕️ する ⭕️ する ⭕️ する
abbb:xxx ❌ しない ❌ しない ⭕️ する ⭕️ する
target:abbb:xxx ❌ しない ❌ しない ❌ しない ❌ しない
target:aaabbb:xxx ❌ しない ❌ しない ❌ しない ❌ しない
bbb:xxxy ❌ しない ⭕️ する ⭕️ する ⭕️ する

想像するに

  • community-set キーワード,extcommunity-set キーワードで分離.異なるものにマッチしない
  • ワイルドカードは 文頭 / 文末 を前提にしてマッチ
  • 正規表現は 文頭 / 文末 でなくてもマッチ

gobgp

  • 正規表現(横) がマッチ対象(縦) にマッチするか
  • アルファベットはBGP Community を10進で表現したときの1ケタ.4ケタ = 2Bytes,6ケタ = 4Bytes
  • community の例.ほかにext-communitylarge-community キーワードがある
  • Large BGP Community 対応バージョン
⬇️対象 \ 表現➡️ bbb:xxx bbb:xxx.*
bbb:xxx ⭕️ する ⭕️ する
abbb:xxx ❌ しない ⭕️ する
target:abbb:xxx ❌ しない ❌ しない
target:aaabbb:xxx ❌ しない ❌ しない
bbb:xxxy ❌ しない ⭕️ する
aaa:bbb:xxx ❌ しない ❌ しない
  • communityext-communitylarge-community キーワードで分離.異なるものにマッチしない
  • \d+:\d+ パターンであれば^\d+:\d+$ と解釈.それ以外はそのまま

Quagga

  • 正規表現(横) がマッチ対象(縦) にマッチするか
  • アルファベットはBGP Community を10進で表現したときの1ケタ.4ケタ = 2Bytes,6ケタ = 4Bytes
  • community-list の例.ほかにextcommunity-listlarge-community-list キーワードがある
  • Large BGP Community 対応バージョン
⬇️対象 \ 表現➡️ bbb:xxx bbb:xxx.*
bbb:xxx ⭕️ する ⭕️ する
abbb:xxx ⭕️ する ⭕️ する
target:abbb:xxx ❌ しない ❌ しない
target:aaabbb:xxx ❌ しない ❌ しない
bbb:xxxy ⭕️ する ⭕️ する
aaa:bbb:xxx ❌ しない ❌ しない
  • community-listextcommunity-listlarge-community-list キーワードで分離.異なるものにマッチしない
  • そのまま正規表現マッチ

Large BGP Community に対する懸念

2バイトの5ケタAS事業者が^ccccc:xxx$ と書くべきところを「ふつう2Bytes:2Bytes だし」とサボってccccc:xxx$ と書いてしまった場合に,意図しないLarge BGP Community にマッチして誤動作しないかを気にしていた.aaa:ccccc:xxxaaa:bccccc:xxx にマッチするかもなと.

4ケタ以下事業者は^ 忘れてないだろうし,4バイト事業者はうまくBGP Community を使えていないのでは と思われるので,問題になるとすれば2バイト5ケタかなと.

上記のようにまとめてみると,各実装とも既存の2Bytes:2Bytes Community と4Bytes:4Bytes:4Bytes のLarge BGP Community をキーワードで分離させる方針のようなので,杞憂かもしれない.

(JUNOS でExtended Community にマッチしてしまう細かな問題はあるかもしれない)

JUNOS のL キーワードはこれでいいんだっけ?

「4バイトの場合はL キーワードを使え」とドキュメントに書いているが,4Bytes:2Bytes もしくは 2Bytes:4Bytes だけであればこれでよかった.ところが4Bytes:4Bytes:4Bytes になると破綻するように思う.

aaa:bbb:ccc のうち,aaa はAS番号固定かもしれないが,bbb, ccc は2バイトレンジかもしれないし,4バイトレンジかもしれない.L の有無について4パターン併記しないといけない? それはつらい.

どういう実装で出してくるか楽しみだが,「L キーワードは捨てて,あらゆるCommunity について文頭~文末まで正規表現で文字列マッチします」というのがかえって分かりやすい気がする.

*1:手元に古いのしかなかった 😭

ステルスWiFi AP を駆逐した

macos がステルスWiFi AP に接続したときに脅してくるこれ,しばらく意味が分からなくて放置していた.

たぶんこういうことかな,というのを教えてもらって「なるほど,良くないかもしれん」と思い駆逐した.

ステルスAP が接続リストにいるリスク

アクティブにProbe Request を投げるため,接続可能なSSID の一部が漏れるから.せっかくMac Randomization してもSSID がリストで漏れており,個体識別されるリスクが高まる.ステルスじゃなくしたら漏れないかというと そうではないので「漏れやすさ」の問題.

ステルスAP が設定されているmacos 10.12.2 とIOS 10.2 の動き

ちゃんと調べたわけではありません.もし違っていたらご指摘ください.あれこれ操作したときの振る舞いを1時間くらい観察しました.

  • ステルスなSSID を探して,すべてのSSID についてProbe Request を投げまくる
  • ステルスAP に接続中のときも,そのSSID を含めて投げまくる

  • 違うAP がそのSSID を偽装したら

    • 正規のステルスAP がいない環境で,偽のステルスAP (SSID 同じ,認証なし) をつくる
    • 自動でそいつに接続することはなかった

ステルスAP が設定されていないmacos 10.12.2 とIOS 10.2 の動き

  • WiFi をON にした瞬間はActive Scan する = Probe Request を投げる
  • 放っておくとIOS 10.2 はActive Scan する
    • 端末がSleep しているのと関係あるかも (くわしく調べてない)
    • macos はそんな動きをしない (こちらはSleep していない)
  • それ以外SSID を投げていない.

かなりProbe Request が減った.

ステルスをやめる

そもそもステルスにしていたのは視界に入れたくなかったから.ほとんどメンテ不要なやつは消えていてほしい.とはいうものの,どこに持ち込むかわからない端末のほうのセキュリティリスクを下げたい.ステルスをやめることでAP のセキュリティリスクはさほど上がらない.

a/b/g/n/ac など広く802.11 を受けられる端末で

sudo tcpdump -I -ien0 -e -s0 type mgt subtype probe-req

を実行しつつ,一台ずつWiFI off/on してヘンなSSID を投げなくなるまで設定を削除した.

IOS はAP が存在しないと消せないので面倒だが,めちゃくちゃ古いSSID を探していて「おお…こいつ…こんなになっても〇〇を覚えてるのか…」って感傷的になれるのでオススメです.

BGP Community を透過する事業者がどれくらいいるか調べた

11月末にInternet Week 2016 というイベントで,「BGP Community の基本設計」について発表してきた.内容については 発表スライド をご覧いただければ良いかな と思うが,壇上から挙手アンケートを取ってみてびっくりした.

「顧客から受信したBGP Community を消さずに透過しているかた,どのくらいいますか?」の結果が 1%ほどだった.

該当するけど手を上げられなかった方もいると思うし,母数として全員がAS 運用者じゃなかったかもしれない.が,「えっ! 少なすぎる!」と思った.世の中そんなもんなのかな,と思ってざっと調査した内容を書いておく.

結果から書いておくと「割合的にはまあそんなもん」だった.

BGP Community は API なんですよ

BGP Community は「便利なタグ」だったり「他社ネットワーク内での自社経路のふるまいを定義できるノブ」だったりする.たとえば

  • 経路がネットワークに入ってきたのはどの国か,顧客に伝えるタグ
  • 他社ネットワーク内でLocal Preference を下げるためのノブ

のように,BGP プロトコルの範囲のなかで付加価値をつけることができる.「HTTP(S) でやれば?」という考えも頭をよぎるが,IP レイヤーの操作をさらに上のレイヤーに依存するのは危険かもしれないし,レイヤーをまたぎすぎている感がある.「HTTP(S) でもできる」が理想だけれど,IP ならではの柔軟性と拡張性を得るためにもBGP プロトコルでやりたいところ.

上のように AS65000 がBGP Community に乗せて便利情報を提供してくれている場合,AS65001 の立場からすると「自社に不利益がある」「AS65000 の利用規約に反する」ような場合を除いてAS65002 に透過しない理由はないはず.逆もしかりで,AS65002 が「AS65000 内での経路のふるまいを制御したい」と考えているとしてAS65001 がそれを遮断する理由はないように思う.

が,アンケート結果では「でも止めてる」だし,観測範囲内でも止めてる事業者がほとんどに見える.

特にAS65002 がAS65001 の顧客だった場合,情報を透過するほうがAS65001 サービスの付加価値につながりそうだし,ぜんぶ透過しなくても工夫してやればいいのに…と思う.

「将来,トランジット事業者(上の絵でいえばAS65000) を変えるかもしれない」という懸念はあるが,トランジット事業者が似たAPI を提供してさえすればAS65001 で変換するのがよさそう.他社のサービスや製品を組み合わせてうまいこと抽象化することは,サービスを作る側の手腕の見せ所かな と思う.

調査結果

AS間の関係を transit / peer / customer / unknown に分類し「X から受信したBGP Community をY に透過する事業者数」を数えた.調査の方法はあとで.

たとえば transit からcustomer に向かう矢印は93 だが,「transit から受信したBGP Community をcustomer に透過するAS は93 個あった」という意味.4バイトAS は除外してカウントしている.

BGPlay コレクターの配置的にすべてのAS をカバーしていないかもしれないが,フルルートの1/11 ほどのサンプル数.

  • customer から受信した経路を透過する事業者が比較的多そう
    • 送信先によって透過 / 不透過を区別してそう
    • 特にtransit 方向にはフィルターしてそう
  • 実際に使われている2バイトAS 約6万個に対して,透過しているAS はおよそ1% 程度しかない

ということがわかる.unknown が多いのは,参照したAS間の関係データベースが良くなかったかもしれない.

調査方法

BGPlayThe CAIDA UCSD as-relationships - 20161201 のデータを使った.

2バイトAS のすべてについて

  1. そのAS がoriginate している適当な1 prefix を選ぶ
  2. BGPlay でBGP Community が透過しているかどうか調べ,AS_PATH 上の各AS について transit / peer / customer のどれからどれに送信する際に透過するかをマークする
  3. AS 間の関係についてはCAIDA のas-relationships を参照する

仮定として

  • BGPlay コレクターはcustomer 相当と考える
  • BGP Community のGlobal Administrator がAS_PATH 上に現れるもののみをカウント
    • 現れない場合,BGP Community がどこでつけられたか判別できない
    • そのBGP Community は,AS_PATH 上のGlobal Administrator より右でつけられたものと考える

たとえば

  • AS_PATH: 65000 65001 65002 65003
  • BGP Community: 65002:100

の場合

  • Community は65002 か65003 でつけられたと仮定
    • → 65001 はCommunity を透過する
  • 65001 から見て65002 は transit で,65000 は customer
    • → 65001 は transit から受信したBGP Community を customer に透過する
  • 65000 から見て65001 は customer で,BGPlay コレクターも customer
    • → 65000 は customer から受信したBGP Community をcustomer に透過する

経路数でいえばフルルート68万経路に対して6万経路分,1/11 サンプルを調査した.BGPlay コレクターの配置から「透過しているんだけど観測できない」AS があることにも注意.

なお,今回は割合を概算したかったので 4バイトAS は除外してカウントしている.

Internet Week 2016 発表スライド

発表スライドをリンクしておきます.

  • AS 運用者向け
  • BGP Community 設計のコツ
  • API と思って設計しよう

のような内容です.よければご覧ください.

https://speakerdeck.com/codeout/bgp-communityfalse-ji-ben-she-ji