Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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 認証
• クライアント証明書認証
• 新しい ...
Upcoming SlideShare
Loading in …5
×

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

31,699 views

Published on

devsumi 2015 の発表資料

Published in: Software
  • Be the first to comment

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

×