https://www.youtube.com/watch?v=nlt4XKhucS4
1 comment | 0 points | by WazanovaNews 約14時間前 edited
CloudFlareのWAF (Web Application Firewall)は、HTTPリクエストをフィルタリングし、
などの攻撃をネットワークのエッジで、つまりサーバに到達する前に守ってくれます。
適用するフィルタリングルールは、オープンソースのOWASPなどの共通ルール 5,682件 + CloudFlare内製のルール 102件 + 顧客企業がカスタムメイドしたルールの総計で、それが全てのリクエストに当てはめられます。その処理速度は平均1ms以下、概ね400μs程度。1日あたり12億リクエストを防御しているとのこと。
nginx.conf 2014の講演 [1] で、同社のJohn Graham-Cummingが、その処理速度を高速スクリプト言語Luaを活用して、当初の10msから1/10以下に短縮した取組みを紹介してくれています。
全体概要
当初は、Apache + nginxの構成で、オープンソースのmod_securityを利用していたが、mod_securityはApacheでうまくスケールしてくれなかったため、nginx上でLua(ngx_lua/OpenResty + LuaJIT)を使って改善。
コンパイルしたLuaファイルを動的に読込み、つまりLuaをアセンブリ言語のように使い、mod_securityもしくはCloudFlareで用意したルールを、Luaにコンパイルし、動的にnginxに読込んでいる。つまり再起動せずに新しいルールを柔軟に適用できる。
ルールコンパイラの最適化
- clauseの並びを工夫することで、サブclauseがマッチしなければすぐにスキップできる。
- 正規表現の最適化。
- オペレータをシンプルなstringマッチなど高速なものに置き換える。
- マクロ拡張が必要になりそうかどうかの情報をWAFランタイムに与える。
- 繰り返しでてくるstringや変数が必ず一度だけ計算されるようにグローバルに最適化する。
その他の最適化
- Luaの基本的なチューニング。
- ローカルはグローバルよりもかなり早い。
- コロンでなくドット構文を使う。
- クロージャの利用を極力控えた。最近までLuaJITにおいてクロージャはやや遅かった。
- PCRE JITとキャッシュオプションを適用。
- アクセス頻度の高いアイテムには、lua_shared_dict を使い、インメモリキャッシュの効果をだす。
- アレーを特別な使い方をしている。(?)
- JITに適用可能なコードであることの確認。
- コンパイルしたLuaはmemcachedに、読込んだ後には lua_shared_dict にという二段階でキャッシュ。
- メモイゼーション
正規表現を徹底的に磨く
- PCREツールを利用することで、本番環境のノードにおける正規表現の実行時間を計測。
- マッチングのスピードアップのために、独自バージョンのエイホ-コラシックアルゴリズムを実装。(Golan版とC++ with LUA版をオープンソースで提供。)[2]
ボトルネックの調査ツール
また、同社のYichun Zhang (@agentzh)の講演 [3] では、彼が中国大手オークションサイトTaobaoに勤務していた当時、データ分析インフラの改善のために、「Node.jsで経験したcallback hellを避けつつ、100%ノンブロッキングI/Oを享受するため。」にngx_luaに取組んだ経緯を紹介してくれています。
ngx_lua cosocketの前提として、Luaはネイティブでコアルーティンをサポートしている。同期させた状態でコードをマジックのように反映してくれる。Cレベルでノンブロッキング & 同期。それを元に、MySQL / memcached / Redis用のドライバを作成し、パフォーマンスを大幅に改善し、そこから開発コミュニティが盛り上がり、ライブラリが充実していった。その後、CloudFlareに入社し、Lua SSL / Lua CDN / Lua WAFの開発に関わった。
講演の後半では関連ライブラリの解説を順次してくれています。
[1] https://www.youtube.com/watch?v=nlt4XKhucS4
[2] http://www.scalescale.com/scaling-cloudflares-massive-waf/
[3] https://www.youtube.com/watch?v=Z0fQabvVhIk