Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
NginxとLuaを用いた動的
なリバースプロキシでデ
プロイを 100 倍速くした
サイボウズ株式会社
深谷敏邦
#devsumi [19-G-6]
1
自己紹介
• 深谷 敏邦
• 2012年サイボウズ株式会社入社
• インフラチーム Hazama 所属 (2012/09~)
• お仕事
• デプロイツールの作成
• MySQL HA 環境の構築
• Apache のデバッグ・パッチの作成
•...
1. イントロダクション
2. Apache から Nginx へ
3. 実装について
4. 結果とまとめ
3
cybozu.com とは
• サービスとして
• サイボウズが運営するクラウドサービス
• 2011 年 11 月サービスイン
• 開始から 4 年で導入社数 9000 社以上
4
クラウド基盤としての cybozu.com
• 1000 台規模の物理マシン、数倍の VM
• 物理機材から全て自社構築
• 1億リクエスト/日
• 契約ユーザーライセンス数29万人以上
5
サービス概要
• お客様ごとにサブドメインを発行
• 契約内容に従って複数のサービスが同ドメインで利用可能
6
fukaya-coop.cybozu.com
サブドメイン毎の処理
• アプリケーション振り分け
• IP 制限
• Basic 認証
• クライアント証明書
7
LB
APAP
fukaya-coop.cybozu.com
/o//k/12.34.5.6
サブドメイン毎の処理の裏側
• 1 サブドメインにつき 1 設定ファイルを用意
• 読み込みのたびに全ファイルのロードが必要
• サブドメインが増えるとロード処理にも時間がかかり….
8
サブドメイン数×設定変更にかかる時間
9
150
170
190
210
230
250
270
290
2/17/2014 3/17/2014 4/17/2014 5/17/2014 6/17/2014
Apache 再起動時間
設定変更に
...
ミッション
• サブドメインの設定変更を 1秒で完了させる
10
1. イントロダクション
2. Apache から Nginx へ
3. 実装について
4. 結果とまとめ
11
これまで
• LB として Apache 2.2 を利用
• Apache を普通に使うと
• サブドメイン毎に設定ファイルが必要
• 設定ファイルを安全にリロードするには再起動が必要
12
仕組みの転換
• 1サブドメインの変更のためにすべての設定を読み込む
13
• アクセス毎に対応するサブドメインの設定を動
的に読み込む
実際どうやるか?
• さすがに自力で全部作るのは厳しい
• 候補に挙がったのは以下の 2 つ
• Apache 2.4
• nginx
• 今の機能を実現できるのは最低ライン
• パッチを当てすぎると本家の変更に追随できなくなる
• そうだ L...
ということで比較してみる
機能 ◎
(当然)
○
(何とかいけそう)
Lua
△
(experimental)
◎
(実績十分)
性能
○
(event mpm)
◎
(完全イベント駆動)
15決定
nginx と lua-nginx-module
• nginx はイベント駆動型の HTTP サーバ
• 2015年1月現在シェア 14%
• 大量のリクエストの処理が得意
• lua-nginx-module は HTTP リクエスト処理を...
1. イントロダクション
2. Apache から Nginx へ
3. 実装について
4. 結果とまとめ
17
nginx の設定の基本
• location
• リクエスト URI に応じて設定を変えるためのディレクティブ
18
location / {
root /www/default;
}
location /hoge/ {
root /www/...
internal redirect
• location 間を移動する仕組み
• 処理が異なる複数の location を組み合わせる事ができる
19
location /
location /login/
location /proxy/
n...
lua-nginx-module
• HTTP 処理の様々なタイミングで lua で記述した任意のコード
を実行出来る
• https://github.com/openresty/lua-nginx-module
• 可能なこと
• HTTP...
データベースファイルの読み込み
• リクエスト毎にサブドメインに対応する設定をデータベース
ファイルから読み込む
• key: value の簡単なテキスト形式
• lua を使って Host ヘッダを元にローカルファイルを読む
21
ngin...
データベースファイルの読み込み実装例
22
location / {
rewrite_by_lua ‘
path = (“/settings/” .. ngx.var.host)
ret = ngx.location.capture(path)...
データベースファイルの読み込み実装例
23
location / {
rewrite_by_lua ‘
path = (“/settings/” .. ngx.var.host)
ret = ngx.location.capture(path)...
データベースファイルの読み込み実装例
24
location / {
rewrite_by_lua ‘
path = (“/settings/” .. ngx.var.host)
ret = ngx.location.capture(path)...
データベースファイルの読み込み実装例
25
location / {
rewrite_by_lua ‘
path = (“/settings/” .. ngx.var.host)
ret = ngx.location.capture(path)...
アクセス毎に変更すべき設定
1. 利用アプリケーション
2. IP アドレス制限
3. Basic 認証
4. クライアント証明書による認証
26
1. 利用アプリケーション
• 各サブドメイン毎に利用可能なアプリケーションが異なる
• 申込時に選択
• 後に追加・削除が可能
• lua から以下の制御を行う
• 利用不能なアプリケーションへのアクセスは拒否する
• 利用可能なアプリケーシ...
利用アプリケーション動的化実装例
28
location / {
rewrite_by_lua ‘
if use_garoon then
ngx.exec(“/proxy/garoon”)
end
if use_kintone the
ngx....
利用アプリケーション動的化実装例
29
location / {
rewrite_by_lua ‘
if use_garoon then
ngx.exec(“/proxy/garoon”)
end
if use_kintone the
ngx....
利用アプリケーション動的化実装例
30
location / {
rewrite_by_lua ‘
if use_garoon then
ngx.exec(“/proxy/garoon”)
end
if use_kintone the
ngx....
2. IP アドレス制限
• 標準モジュールではアクセス毎動的に設定を変更することが出
来ない
• lua で IP アドレス制限を実装した
31
• 192.168.0.1
• 192.168.0.2
• 172.16.0.1
fukaya-...
IP アドレス制限の実装
32
function authenticate_remote_addr(allows)
local bit = require("bit")
local remote_addr = ngx.var.binary_re...
IP アドレス制限の実装
33
function authenticate_remote_addr(allows)
local bit = require("bit")
local remote_addr = ngx.var.binary_re...
IP アドレス制限の実装
34
function authenticate_remote_addr(allows)
local bit = require("bit")
local remote_addr = ngx.var.binary_re...
3. Basic 認証
• 標準モジュールでリクエストごとにパスワードファイルを変更
することが出来る
• ただし認証自体は全ドメインにかかってしまう
• 一方認証自体を利用するか否かはサブドメイン毎に設定できる
• 認証を利用するかどうかを ...
nginx の リクエスト処理
• nginx ではリクエストはいくつかのフェイズを通って処理され
る
• Basic 認証は Access フェイズで実施される
36
rewrite フェイズ
access フェイズ
content フェイズ...
Basic 認証のスキップ
• Basic 認証を利用しない場合 lua を使って Access フェイズより
前に internal redirect する
• 後のフェイズが実行されないので Basic 認証が行われなくなる
37
rewr...
Basic 認証の実装例
38
location / {
rewrite_by_lua ‘
if not use_basic_auth then
ngx.exec(“/contents/”)
end
‘;
auth_basic “closed ...
Basic 認証の実装例
39
location / {
rewrite_by_lua ‘
if not use_basic_auth then
ngx.exec(“/contents/”)
end
‘;
auth_basic “closed ...
Basic 認証の実装例
40
location / {
rewrite_by_lua ‘
if not use_basic_auth then
ngx.exec(“/contents/”)
end
‘;
auth_basic “closed ...
Basic 認証の実装例
41
location / {
rewrite_by_lua ‘
if not use_basic_auth then
ngx.exec(“/contents/”)
end
‘;
auth_basic “closed ...
Basic 認証の実装例
42
location / {
rewrite_by_lua ‘
if not use_basic_auth then
ngx.exec(“/contents/”)
end
‘;
auth_basic “closed ...
4. クライアント証明書による認証
• クライアント証明書は SSL/TLS 接続で利用できる認証方法
• サーバ証明書とは逆に HTTP サーバがクライアントに証明書を
要求する
• クライアントはサーバが持つ CA が発行した証明書を送信す...
クライアント証明書認証の実装上の課題
• 標準モジュールではアクセス毎に CA を切り替えるという器用
なことは出来ない
• SSL/TLS プロトコルでの認証なので lua では実装できない
• lua-nginx-module は HTTP...
クライアント証明書認証の実装の概要
• サーバはクライアント証明書の発行者を動的に呼び出して証明
書を検証
• ただし他のサブドメインの証明書でも認証が通るためその証明
書がアクセス先のサブドメインのものかどうかチェックが必要
45
LB
クラ...
SNI について
• SNI は TLS 拡張の一つで TLS ハンドシェイク時にアクセスした
い FQDN をサーバに渡すこと
• 名前ベースバーチャルホストでも FQDN 毎に証明書を変えることが出
来る
• クライアント証明書認証ではサー...
SNI 対応
• パッチでは SNI で送信された FQDN に従って CA をルックアッ
プするようにした
• CA は FQDN をファイル名とした通常の PEM ファイルとして保存
47
LB
この CA が発行した証明書を送ってね
fu...
その他おこなったこと
• LB を複数サーバにした場合の問題
• 各 LB 毎に SSL ハンドシェイクを行うので、iOS だと証明書選択ダイ
アログ複数回でてしまう
• LB 全体で状態を共有できない
1. 複数サーバー間での SSL セッシ...
1. イントロダクション
2. Apache から Nginx へ
3. 実装について
4. 結果とまとめ
49
適用結果
•5分かかっていた設定の反映が1~2秒で終わるようになった
50
0
50
100
150
200
250
300
設定リロード時間
適用前 適用後
秒
100倍以上高速化
パフォーマンスについて
• リクエストごとに lua を実行するためパフォーマンスの劣化が
懸念されたが問題なかった
51
count count
log10(response time[μs]) log10(response time[μs]...
nginx 化のメリット
• 大量のコネクションを扱えるので keepalive 秒数を伸ばした
• 15秒から75秒に
• 送信トラフィックが顕著に落ちた
• 処理したリクエスト数は減っていない
• サーバ証明書の送信量が減ったことが理由
•...
まとめ
• 従来は LB への設定の反映に5分かかっていた
• nginx + lua を使いサブドメイン毎に設定を動的に読み込んだ
• アプリケーションの利用可否
• IP 制限
• Basic 認証
• クライアント証明書認証
• 新しい ...
Próxima SlideShare
Cargando en…5
×

NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした

40.173 visualizaciones

Publicado el

devsumi 2015 の発表資料

Publicado en: Software
  • Inicia sesión para ver los comentarios

NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした

  1. 1. NginxとLuaを用いた動的 なリバースプロキシでデ プロイを 100 倍速くした サイボウズ株式会社 深谷敏邦 #devsumi [19-G-6] 1
  2. 2. 自己紹介 • 深谷 敏邦 • 2012年サイボウズ株式会社入社 • インフラチーム Hazama 所属 (2012/09~) • お仕事 • デプロイツールの作成 • MySQL HA 環境の構築 • Apache のデバッグ・パッチの作成 • Nginx を使ったリバースプロキシの構築 2
  3. 3. 1. イントロダクション 2. Apache から Nginx へ 3. 実装について 4. 結果とまとめ 3
  4. 4. cybozu.com とは • サービスとして • サイボウズが運営するクラウドサービス • 2011 年 11 月サービスイン • 開始から 4 年で導入社数 9000 社以上 4
  5. 5. クラウド基盤としての cybozu.com • 1000 台規模の物理マシン、数倍の VM • 物理機材から全て自社構築 • 1億リクエスト/日 • 契約ユーザーライセンス数29万人以上 5
  6. 6. サービス概要 • お客様ごとにサブドメインを発行 • 契約内容に従って複数のサービスが同ドメインで利用可能 6 fukaya-coop.cybozu.com
  7. 7. サブドメイン毎の処理 • アプリケーション振り分け • IP 制限 • Basic 認証 • クライアント証明書 7 LB APAP fukaya-coop.cybozu.com /o//k/12.34.5.6
  8. 8. サブドメイン毎の処理の裏側 • 1 サブドメインにつき 1 設定ファイルを用意 • 読み込みのたびに全ファイルのロードが必要 • サブドメインが増えるとロード処理にも時間がかかり…. 8
  9. 9. サブドメイン数×設定変更にかかる時間 9 150 170 190 210 230 250 270 290 2/17/2014 3/17/2014 4/17/2014 5/17/2014 6/17/2014 Apache 再起動時間 設定変更に 時間かかり過ぎ 秒 日付~サブドメイン数 2.5分 5分
  10. 10. ミッション • サブドメインの設定変更を 1秒で完了させる 10
  11. 11. 1. イントロダクション 2. Apache から Nginx へ 3. 実装について 4. 結果とまとめ 11
  12. 12. これまで • LB として Apache 2.2 を利用 • Apache を普通に使うと • サブドメイン毎に設定ファイルが必要 • 設定ファイルを安全にリロードするには再起動が必要 12
  13. 13. 仕組みの転換 • 1サブドメインの変更のためにすべての設定を読み込む 13 • アクセス毎に対応するサブドメインの設定を動 的に読み込む
  14. 14. 実際どうやるか? • さすがに自力で全部作るのは厳しい • 候補に挙がったのは以下の 2 つ • Apache 2.4 • nginx • 今の機能を実現できるのは最低ライン • パッチを当てすぎると本家の変更に追随できなくなる • そうだ Luaがあるじゃないか! 14
  15. 15. ということで比較してみる 機能 ◎ (当然) ○ (何とかいけそう) Lua △ (experimental) ◎ (実績十分) 性能 ○ (event mpm) ◎ (完全イベント駆動) 15決定
  16. 16. nginx と lua-nginx-module • nginx はイベント駆動型の HTTP サーバ • 2015年1月現在シェア 14% • 大量のリクエストの処理が得意 • lua-nginx-module は HTTP リクエスト処理を lua で書ける拡張 モジュール • cybozu.com で必要な設定項目がおおよそ実現できる • 出来ないものは C で書く ☺ 16
  17. 17. 1. イントロダクション 2. Apache から Nginx へ 3. 実装について 4. 結果とまとめ 17
  18. 18. nginx の設定の基本 • location • リクエスト URI に応じて設定を変えるためのディレクティブ 18 location / { root /www/default; } location /hoge/ { root /www/hoge; } • / にアクセスした場合は、 /www/default からコン テンツを探す • /hoge/ にアクセスした 場合は、/www/hoge か ら探す
  19. 19. internal redirect • location 間を移動する仕組み • 処理が異なる複数の location を組み合わせる事ができる 19 location / location /login/ location /proxy/ nginx location /maintenance/ メンテナンス中 初回アクセス アプリケーションサーバへ ログイン後
  20. 20. lua-nginx-module • HTTP 処理の様々なタイミングで lua で記述した任意のコード を実行出来る • https://github.com/openresty/lua-nginx-module • 可能なこと • HTTP ヘッダの読み書き • location に対するリクエストの発行 • internal redirect の実行 20
  21. 21. データベースファイルの読み込み • リクエスト毎にサブドメインに対応する設定をデータベース ファイルから読み込む • key: value の簡単なテキスト形式 • lua を使って Host ヘッダを元にローカルファイルを読む 21 nginx hagi hagi.cybozu.com fukaya-coop.cybozu.com sato-shoji.cybozu.com fukaya -coop sato- shoji
  22. 22. データベースファイルの読み込み実装例 22 location / { rewrite_by_lua ‘ path = (“/settings/” .. ngx.var.host) ret = ngx.location.capture(path) ret.body... ‘; } location /settings/ { internal; root /var/settings; } lua による設定読 み込み用location DB ファイル配信 用location
  23. 23. データベースファイルの読み込み実装例 23 location / { rewrite_by_lua ‘ path = (“/settings/” .. ngx.var.host) ret = ngx.location.capture(path) ret.body... ‘; } location /settings/ { internal; root /var/settings; } • Host ヘッダを元に DB ファイルパスを 作成
  24. 24. データベースファイルの読み込み実装例 24 location / { rewrite_by_lua ‘ path = (“/settings/” .. ngx.var.host) ret = ngx.location.capture(path) ret.body... ‘; } location /settings/ { internal; root /var/settings; } • Host ヘッダを元に DB ファイルパスを 作成 • DB ファイルを取得 するリクエストを 投げる
  25. 25. データベースファイルの読み込み実装例 25 location / { rewrite_by_lua ‘ path = (“/settings/” .. ngx.var.host) ret = ngx.location.capture(path) ret.body... ‘; } location /settings/ { internal; root /var/settings; } • Host ヘッダを元に DB ファイルパスを 作成 • DB ファイルを取得 するリクエストを 投げる • レスポンスボディ から設定値を取得
  26. 26. アクセス毎に変更すべき設定 1. 利用アプリケーション 2. IP アドレス制限 3. Basic 認証 4. クライアント証明書による認証 26
  27. 27. 1. 利用アプリケーション • 各サブドメイン毎に利用可能なアプリケーションが異なる • 申込時に選択 • 後に追加・削除が可能 • lua から以下の制御を行う • 利用不能なアプリケーションへのアクセスは拒否する • 利用可能なアプリケーションへのアクセスは適切なアプリケーション サーバにリバースプロキシする 27 nginx hagi.cybozu.com fukaya-coop.cybozu.com garoon AP kinton eAP g k
  28. 28. 利用アプリケーション動的化実装例 28 location / { rewrite_by_lua ‘ if use_garoon then ngx.exec(“/proxy/garoon”) end if use_kintone the ngx.exec(“/proxy/kintone”) end ngx.exit(ngx.HTTP_NOT_FOUND) ‘; } location /proxy/garoon { proxy_pass http://garoon-ap/; } location /proxy/kintone { proxy_pass http://kintone-ap/; } lua によるアプリケー ション利用可否と振り分 けロジック リバースプロキシ用の location
  29. 29. 利用アプリケーション動的化実装例 29 location / { rewrite_by_lua ‘ if use_garoon then ngx.exec(“/proxy/garoon”) end if use_kintone the ngx.exec(“/proxy/kintone”) end ngx.exit(ngx.HTTP_NOT_FOUND) ‘; } location /proxy/garoon { proxy_pass http://garoon-ap/; } location /proxy/kintone { proxy_pass http://kintone-ap/; } • 予め DB ファイルの内容を lua の変数に読み込んでおく • アプリケーションが利用可能な らリバースプロキシ用の location に internal redirect す る
  30. 30. 利用アプリケーション動的化実装例 30 location / { rewrite_by_lua ‘ if use_garoon then ngx.exec(“/proxy/garoon”) end if use_kintone the ngx.exec(“/proxy/kintone”) end ngx.exit(ngx.HTTP_NOT_FOUND) ‘; } location /proxy/garoon { proxy_pass http://garoon-ap/; } location /proxy/kintone { proxy_pass http://kintone-ap/; } • 予め DB ファイルの内容を lua の変数に格納しておく • アプリケーションが利用可能な らリバースプロキシ用の location に internal redirect す る • 利用可能なアプリケーションが なければ 404 エラーをクライ アントに返す
  31. 31. 2. IP アドレス制限 • 標準モジュールではアクセス毎動的に設定を変更することが出 来ない • lua で IP アドレス制限を実装した 31 • 192.168.0.1 • 192.168.0.2 • 172.16.0.1 fukaya-coop 192.168.0.1 192.168.0.3
  32. 32. IP アドレス制限の実装 32 function authenticate_remote_addr(allows) local bit = require("bit") local remote_addr = ngx.var.binary_remote_addr local x0, x1, x2, x3 = string.byte(remote_addr, 1, 4) local ip ip = x0 * 16777216 ip = x1 * 65536 + ip ip = x2 * 256 + ip ip = x3 + ip for i, allow in ipairs(allows) do if bit.band(ip, allow[2]) == bit.tobit(allow[1]) then return true end end return false end
  33. 33. IP アドレス制限の実装 33 function authenticate_remote_addr(allows) local bit = require("bit") local remote_addr = ngx.var.binary_remote_addr local x0, x1, x2, x3 = string.byte(remote_addr, 1, 4) local ip ip = x0 * 16777216 ip = x1 * 65536 + ip ip = x2 * 256 + ip ip = x3 + ip for i, allow in ipairs(allows) do if bit.band(ip, allow[2]) == bit.tobit(allow[1]) then return true end end return false end nginx の内部変数からクライア ント IP アドレスを取得する
  34. 34. IP アドレス制限の実装 34 function authenticate_remote_addr(allows) local bit = require("bit") local remote_addr = ngx.var.binary_remote_addr local x0, x1, x2, x3 = string.byte(remote_addr, 1, 4) local ip ip = x0 * 16777216 ip = x1 * 65536 + ip ip = x2 * 256 + ip ip = x3 + ip for i, allow in ipairs(allows) do if bit.band(ip, allow[2]) == bit.tobit(allow[1]) then return true end end return false end データベースファイルから読み込んだ 許可リストと比較してアクセス可否を 判定
  35. 35. 3. Basic 認証 • 標準モジュールでリクエストごとにパスワードファイルを変更 することが出来る • ただし認証自体は全ドメインにかかってしまう • 一方認証自体を利用するか否かはサブドメイン毎に設定できる • 認証を利用するかどうかを lua で制御するようにした 35
  36. 36. nginx の リクエスト処理 • nginx ではリクエストはいくつかのフェイズを通って処理され る • Basic 認証は Access フェイズで実施される 36 rewrite フェイズ access フェイズ content フェイズ Basic 認証
  37. 37. Basic 認証のスキップ • Basic 認証を利用しない場合 lua を使って Access フェイズより 前に internal redirect する • 後のフェイズが実行されないので Basic 認証が行われなくなる 37 rewrite フェイズ access フェイズ content フェイズ lua でスキッ プ
  38. 38. Basic 認証の実装例 38 location / { rewrite_by_lua ‘ if not use_basic_auth then ngx.exec(“/contents/”) end ‘; auth_basic “closed site”; auth_basic_user_file /var/passwd/$host; content_by_lua ‘ ngx.exec(“/contents/”) ‘; } location /contents/ { internal; root /var/www; } basic 認証用 location 実コンテンツ用 location
  39. 39. Basic 認証の実装例 39 location / { rewrite_by_lua ‘ if not use_basic_auth then ngx.exec(“/contents/”) end ‘; auth_basic “closed site”; auth_basic_user_file /var/passwd/$host; content_by_lua ‘ ngx.exec(“/contents/”) ‘; } location /contents/ { internal; root /var/www; } rewrite フェイズ access フェイズ content フェイズ
  40. 40. Basic 認証の実装例 40 location / { rewrite_by_lua ‘ if not use_basic_auth then ngx.exec(“/contents/”) end ‘; auth_basic “closed site”; auth_basic_user_file /var/passwd/$host; content_by_lua ‘ ngx.exec(“/contents/”) ‘; } location /contents/ { internal; root /var/www; } • basic 認証を利用しない 場合は /content/ に直接 飛ばす
  41. 41. Basic 認証の実装例 41 location / { rewrite_by_lua ‘ if not use_basic_auth then ngx.exec(“/contents/”) end ‘; auth_basic “closed site”; auth_basic_user_file /var/passwd/$host; content_by_lua ‘ ngx.exec(“/contents/”) ‘; } location /contents/ { internal; root /var/www; } • basic 認証を利用する場 合は rewrite フェイズで は何もしない • access フェイズではサ ブドメイン毎にパス ワードファイルを切り 替える
  42. 42. Basic 認証の実装例 42 location / { rewrite_by_lua ‘ if not use_basic_auth then ngx.exec(“/contents/”) end ‘; auth_basic “closed site”; auth_basic_user_file /var/passwd/$host; content_by_lua ‘ ngx.exec(“/contents/”) ‘; } location /contents/ { internal; root /var/www; } • basic 認証を利用する場 合は rewrite フェイズで は何もしない • access フェイズではサ ブドメイン毎にパス ワードファイルを切り 替える • content フェイズで実コ ンテンツ用 location に 移動する
  43. 43. 4. クライアント証明書による認証 • クライアント証明書は SSL/TLS 接続で利用できる認証方法 • サーバ証明書とは逆に HTTP サーバがクライアントに証明書を 要求する • クライアントはサーバが持つ CA が発行した証明書を送信する 必要がある • cybozu.com ではサブドメイン毎に CA を作成 43 LB クライアント証明書を要求 証明書を送信 証明書を確認
  44. 44. クライアント証明書認証の実装上の課題 • 標準モジュールではアクセス毎に CA を切り替えるという器用 なことは出来ない • SSL/TLS プロトコルでの認証なので lua では実装できない • lua-nginx-module は HTTP レベルの処理しか書けない • nginx に直接パッチを行った 44
  45. 45. クライアント証明書認証の実装の概要 • サーバはクライアント証明書の発行者を動的に呼び出して証明 書を検証 • ただし他のサブドメインの証明書でも認証が通るためその証明 書がアクセス先のサブドメインのものかどうかチェックが必要 45 LB クライアント証明書を要求 証明書を送信 証明書を確認 CA クライアント証明書に 対応したCAを取得
  46. 46. SNI について • SNI は TLS 拡張の一つで TLS ハンドシェイク時にアクセスした い FQDN をサーバに渡すこと • 名前ベースバーチャルホストでも FQDN 毎に証明書を変えることが出 来る • クライアント証明書認証ではサーバは受け付けるクライアント 証明書の CA の DN を送信することが出来る • 複数のクライアント証明書を持っている場合ユーザーの証明書選択が 楽になる 46 LB この CA が発行した証明書を送ってね 証明書を送信 fukaya-coop.s.cybozu.com にアクセスしたいよ
  47. 47. SNI 対応 • パッチでは SNI で送信された FQDN に従って CA をルックアッ プするようにした • CA は FQDN をファイル名とした通常の PEM ファイルとして保存 47 LB この CA が発行した証明書を送ってね fukaya-coop.s.cybozu.com にアクセスしたいよ fukaya-coop.s.cybozu.com
  48. 48. その他おこなったこと • LB を複数サーバにした場合の問題 • 各 LB 毎に SSL ハンドシェイクを行うので、iOS だと証明書選択ダイ アログ複数回でてしまう • LB 全体で状態を共有できない 1. 複数サーバー間での SSL セッションキャッシュ共有パッチ 2. DoS 対策用同時リクエスト制限モジュールの開発 • yrmcds のセマフォを利用 • いずれも OSS として公開予定 48
  49. 49. 1. イントロダクション 2. Apache から Nginx へ 3. 実装について 4. 結果とまとめ 49
  50. 50. 適用結果 •5分かかっていた設定の反映が1~2秒で終わるようになった 50 0 50 100 150 200 250 300 設定リロード時間 適用前 適用後 秒 100倍以上高速化
  51. 51. パフォーマンスについて • リクエストごとに lua を実行するためパフォーマンスの劣化が 懸念されたが問題なかった 51 count count log10(response time[μs]) log10(response time[μs]) 適用前のレスポンスタイムの分布 適用後のレスポンスタイムの分布
  52. 52. nginx 化のメリット • 大量のコネクションを扱えるので keepalive 秒数を伸ばした • 15秒から75秒に • 送信トラフィックが顕著に落ちた • 処理したリクエスト数は減っていない • サーバ証明書の送信量が減ったことが理由 • 中間証明書を合わせると3~4KB 52 適用前トラフィック 適用後トラフィック
  53. 53. まとめ • 従来は LB への設定の反映に5分かかっていた • nginx + lua を使いサブドメイン毎に設定を動的に読み込んだ • アプリケーションの利用可否 • IP 制限 • Basic 認証 • クライアント証明書認証 • 新しい LB の実装は設定の反映が1秒になった 53

×