LGTM

Looks Good To Me

Hubot にlongest match 機能をつける

ネットワーク運用をしていると,ホストアドレスから経路をルックアップしたいことが結構ある.

たとえばDDoS を受けたとき.いろいろな対処が考えられるが,網内のルーターでパケットフィルターする際に「src address → src prefix の変換をしてからガバッと止めたい」とか.

そんな面倒くさいことはBot にやってもらいたい.

実装のアイデア

ルーターにログインして変換してもいいし,ルーティングテーブルを別に持って検索してもいい.

ルーターにログインしてshow route するのはIO バウンドな処理なのでnode との相性はよさそうだが,「src address が100コ」みたいな場合では遅いと思われる.よくあるルーターだと「まとめて引数を渡して,まとめて結果を受け取る」みたいなことができないため「1コ引数を渡して,1コ結果を受け取る」を100回やらないといけない.

一方,ルーティングテーブルを別に持つのってどう実装しよう?とか自前でpatricia tree つくんの?という面倒くささがある.

MRT TABLE DUMP + patricia tree でやってみる

実は,後者の面倒くさいところを解決してくれるbgpdump2 というツールがある.「node バインディング書けばいいのでは」と思ってやってみたら,結構うまく動くっぽかった.(まだ最小限の実装しかできてないです)

github.com

これを使うとlongest match の結果を返してくれる.

var BGPDump = require('node-bgpdump2');
var bgpdump = new BGPDump('path_to_rib.bz2');
console.log(bgpdump.lookup('8.8.8.8'));

// =>
// { prefix: '8.8.8.0/24',
//   nexthop: '202.249.2.169',
//   origin_as: 15169,
//   as_path: '2497 15169' }

Hubot から使うのもカンタンで,

npm install node-bgpdump2 --save
npm install https://github.com/codeout/node-mrt.git --save

たとえばshow route モドキを返すやつ.

# scripts/route.coffee

BGPDump = require('node-bgpdump2')
MRT = require('node-mrt')
mrt = new MRT('wide')

module.exports = (robot) ->
  robot.respond /route (.*)/, (msg) ->
    mrt.get (text)->
      msg.send text
    , (path)->
      bgpdump = new BGPDump(path)
      msg.send JSON.stringify(bgpdump.lookup(msg.match[1]))

ちなみに node-mrt はarchive.routeviews.org からMRT アーカイブをダウンロードしてキャッシュしてくれるライブラリです.

もうちょい複雑なことを: DDoS 対策手順を作ってもらう

一例だけれど,たとえばDDoS を検知後に

  1. src address → src prefix に変換
  2. src prefix ベースで帯域制限する手順をつくり,GitHub Issue としてオープン

というところまでHubot にお願いしたい.
(今回は例としてsrc prefix だけの条件)

hubot-github-templated-issues というの流用すれば結構ラクにできて,8.8.8.8, 8.8.4.4, 64.6.64.6, 64.6.65.6 からのDDoS を検知したときに

hubot anti ddos packet_filter/ratelimit_2g DDoS対策
src: [
8.8.8.8,
8.8.8.8,
64.6.64.6,
64.6.65.6
]

とHubot にお願いすると,

手順書をIssue 化してくれる.
(↑ ではMRT アーカイブをダウンロードしているが,キャッシュがあればそれをつかう)

https://github.com/codeout/sandbox/issues/108

この手順書はテンプレート にパラメーターを埋めて作ったもので,hubot-github-templated-issues がよしなにやってくれます.

今回つかったスクリプト: scripts/anti_ddos.coffee

まとめ

node-bgpdump2 を使うと,Hubot にlongest match 機能をつけられてけっこう便利だと思う.

bgpdump2 自体,少しコンセプト実装っぽい側面があって完全にライブラリ化されていないため,できたら作者の方に今後のロードマップについて聞きたいところです.