naoki86star

インターネットの片隅でなにかしら書いてみる

BIRDでremotely triggered blackhole(Linuxサーバで構成するネットワークモデル)

#最初に愚痴  今回はBIRD1.6での話、最初BIRD2.x(gitlab.labs.nic.cz版)で試みていたら挫折。*1*2

目的・動機

 Linuxサーバで、ルーティングソフトウェアのひとつであるBIRD*3を動かすときに、RTBH*4を実現できるのか。ふと思ったので試してみる。

予習事項
  • BIRDで経路にcommunityをつけるには:

filterの中でbgp_community.add()を呼ぶ、bgp_community.add( (XXX,YYY) )な感じ

  • blackholeの設定

BH条件を判別できたとき、その経路のアトリビュート(?) bgp_next_hopをblackholeアドレスに設定(for BGP)、destにRTD_BLACKHOLEを代入(for kernel)

アイデア

 今回は、デモ構成全部をLinuxにするのでトリガーもBIRDから。RTBHしたいリストをprotocol staticの設定を使ってファイルに書き出しておく。birdc configureで読み込ませたときに、protocol bgpでのexport filterでコミュニティを付加する処理をいれておく。

デモシナリオ

 今回はWindowsPC(16Gmemory)を借用して、VirtualBoxの仮想環境を使った。*5

  • VMを4台:スター型に接続
  • ゲストOSはUbuntu18.10

 A/B/C/Dの4ノード、Aでルーティングする。Aにスタティックで経路を書いて、B/C/Dにbgpで配る。
 C->Dにpingを通しながら、BからD宛てアドレスにRTBHして、pingが止まることを演じる。

        +---+
        | C |
        +---+
          |
+---+   +---+
| B |---| A |
+---+   +---+
          |
        +---+
        | D |
        +---+

node-Bでrtbh.confを編集して、birdc configureを呼び出すことでrtbh.confに書いたアドレスにコミュニティを付けて配布する。

  • config : node-A
router id 172.31.0.1;
# device/direct/kernelはお約束な感じの前奏
protocol device { scan time 10; }
protocol direct { }
protocol kernel {
  persist;
  scan time 20;
  import all;
  export all;
}

# モデルnetwork全体のルーティングテーブル
protocol static {
  route 172.31.1.0/24 via 172.31.1.1;
  route 172.31.2.0/24 via 172.31.2.1;
  route 172.31.3.0/24 via 172.31.3.1;
  route 192.168.255.1/32 blackhole;
}

# コミュニティの判定
filter bgp_receive_route {
  if (65000,666) ~ bgp_community then {
    bgp_next_hop = 192.168.255.1;
    dest = RTD_BLACKHOLE;
  }
  accept;
}

# それぞれのセグメントB/C/Dのpeer
protocol bgp B {
  local 172.31.1.1 as 65000;
  neighbor 172.31.1.2 as 65001;
  passive;
  import filter bgp_receive_route;
  export all;
  next hop self;
}

protocol bgp C {
  local 172.31.2.1 as 65000;
  neighbor 172.31.2.2 as 65002;
  passive;
  import filter bgp_receive_route;
  export all;
  next hop self;
}

protocol bgp D {
  local 172.31.3.1 as 65000;
  neighbor 172.31.3.2 as 65003;
  passive;
  import filter bgp_receive_route;
  export all;
  next hop self;
}
  • config : node-B/node-C/node-D (router id,ASNは適宜読み替え)(C/Dではexport all ;import allでいい)
router id 172.31.1.2;
include "rtbh.conf";

protocol device { scan time 10; }
protocol direct { }
protocol kernel {
  persist;
  scan time 20;
  import all;
  export all;
}

protocol bgp B {
  local 172.31.1.2 as 65001;
  neighbor 172.31.1.1 as 65000;
  multihop;
  export filter {
    if proto = "rtbh" then bgp_community.add((65000,666));
    accept;
  };
  import filter {
    if (65000,666) ~ bgp_community then {
      bgp_next_hop = 192.168.255.1;
    }
    accept;
  };
}
  • config:RTBH先リスト(rtbh.conf)
protocol static rtbh{
  #route 172.31.3.3/32 drop;
}
メモ1(ログ)

172.31.3.3宛てをBHしたときのroute -nとshow route(node-A)

root@node-A:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    100    0        0 enp0s3
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 enp0s3
10.0.2.2        0.0.0.0         255.255.255.255 UH    100    0        0 enp0s3
172.31.1.0      0.0.0.0         255.255.255.0   U     0      0        0 enp0s8
172.31.2.0      0.0.0.0         255.255.255.0   U     0      0        0 enp0s9
172.31.3.0      0.0.0.0         255.255.255.0   U     0      0        0 enp0s10
172.31.3.3      0.0.0.0         255.255.255.255 UH    0      0        0 *
root@node-A:~# birdc show route all for 172.31.3.3
BIRD 1.6.4 ready.
172.31.3.3/32      blackhole [B 01:20:17 from 172.31.1.2] * (100) [AS65001i]
        Type: BGP unicast univ
        BGP.origin: IGP
        BGP.as_path: 65001
        BGP.next_hop: 192.168.255.1
        BGP.local_pref: 100
        BGP.community: (65000,666)
root@node-A:~#
メモ2
  • ちょっと雑ながらも感じだけはわかったかな
  • BIRDのプロトコルのbgpとkernel(すなわち実際のルーティングテーブル)は独立しているから熟考を要する。わりに最後はすこし横着気味にfilterをまとめているけども、pipeを使ってもう少し独立性に気を使うべきかもしれない。
  • null経路になる192.168.255.1はこのデモだと実は不要。ん、なにか変かもしれない。192.168.255.1宛てをstaticでnullにしておいて、65000:666を受けたら、そのdestを192.168.255.1に振りたいんだけどもdestには代入できるものが限られている。。
  • BIRDのconfigureのattributeがなかなか頭に入ってこない*6
  • birdcコマンドラインから、トリガーするいい方法はないものだろうか。。。

*1:ubuntu18.10との組み合わせなのかプロトコルkernelの処理がうまくいかず、またactive-bgpがつながるとpassive側のVMがなにかのウエイトになったみたいになるとか切り分けしようにも意味不明現象が連発

*2:でもBIRD1.6だとflowspecできないみたいなのでいずれ2.0でさわっていきたい

*3:The BIRD Internet Routing Daemon Project

*4:遠隔でパケットをドロップする技

*5:routing tableをいじるのでcloud上で試す勇気はなかった、いや大量メモリのを借りてVMインスタンス作ればいいのでしょうけど。。。

*6:manualの字が小さくてきつい