node-v0.12のtlsを256倍使いこなす方法

25
Node-v0.12TLS256倍使いこなす方法 大津 繁樹 (@jovi0608) 株式会社インターネットイニシアティブ(IIJ) 東京Node学園祭2014 20141115

Upload: shigekiohtsu

Post on 06-Jul-2015

17.546 views

Category:

Technology


2 download

DESCRIPTION

new TLS feature in Node-v0.12

TRANSCRIPT

Page 1: Node-v0.12のTLSを256倍使いこなす方法

Node-v0.12のTLSを256倍使いこなす方法

大津繁樹 (@jovi0608)

株式会社インターネットイニシアティブ(IIJ)

東京Node学園祭2014

2014年11月15日

Page 2: Node-v0.12のTLSを256倍使いこなす方法

自己紹介

• 名前:大津繁樹

• 所属: 株式会社インターネットイニシアティブ(IIJ) アプリケーション開発部

• Twitter: @jovi0608

• ブログ:ぼちぼち日記 http://d.hatena.ne.jp/jovi0608/

• GitHub: https://github.com/shigeki/

• 新技術の検証・評価を行ってます。 (Node.js, SPDY, HTTP/2,HTML5)

• iij-http2の開発を通じてIETFのHTTP/2標準化作業に参画中

• Node-v0.11.xへのパッチ提出はわずか。でもほとんどTLS関連です。

Page 3: Node-v0.12のTLSを256倍使いこなす方法

TLS (Transport Layer Security)の利用状況

TLS通信認証、暗号化、改ざん防止

図参照 https://plus.google.com/+IlyaGrigorik/posts/7VSuQ66qA3C

GoogleによるChromeの統計調査から、ここ2年間でhttpsサイトへのナビゲーションは28%から58%に増加

Page 4: Node-v0.12のTLSを256倍使いこなす方法

IAB(Internet Architecture Board)からインターネットの信頼性に関する声明

https://www.iab.org/2014/11/14/iab-statement-on-internet-confidentiality/

IABは、現在プロトコル設計者・開発者・運用者がインターネットトラフィックの標準として暗号化を行うことが重要であると信じている。できる限り認証と共に暗号を使うべきだが、認証なしの機密性を持つプロトコルでもRFC7258で記載された「広範囲な盗聴行為」に対して有用となりえる。

Page 5: Node-v0.12のTLSを256倍使いこなす方法

発表内容

• NodeのTLSモジュール大改造

• TLSSocket

• AES-NI

• PFS (Perfect Forward Secrecy)

• TLS False Start

• TLS Ticket

• OCSP Stapling

• TLS Dynamic Record

• SPDY, HTTP/2

• SPDYのメリットが一番よくわかるデモ

Node-v0.12でTLSを使うために有用な情報をお伝えします。(でも256個もないです)

(注1: Node-v0.12はまだ未リリースですが、2014/11/10時点のv0.12ブランチHEADを対象としています。)

(注2: Node-v0.11.xはまだPOODLE対策がされていません。SSLv3を無効化するために、secureOptions: require(‘constants’).SSL_OP_NO_SSLv3)をサーバオプションに追加しましょう。)

Page 6: Node-v0.12のTLSを256倍使いこなす方法

目指せ A+ のTLSサーバ

ソースはこちら

https://gist.github.com/shigeki/986c53242f5bd3d78609

https://www.ssllabs.com/ssltest/index.html

Page 7: Node-v0.12のTLSを256倍使いこなす方法

Node TLSモジュールの大改造

Node-v0.10の問題:パフォーマンスが悪い、APIが扱いづらい

•受信した暗号文をnetモジュールで受けてからSecurePairオブジェクトで復号化

•送信する平文もSecurePairオブジェクトで暗号化してからnetモジュールで送信

• C++ → JS → C++ → JSのオーバヘッドが大きい

•平文のCleartextStreamはnet.Socketと似て非なるもの。

Node-v0.10のTLS処理概要

C++

JS

C++

JS

SecurePair

openssl

暗号文

平文 平文

暗号文

暗号文

net module

libuv

CleartextStream

CryptoStream

Page 8: Node-v0.12のTLSを256倍使いこなす方法

Node TLSモジュールの大改造

C++C++

JS

tls_wrap

libuv openssl

Node_BIO

TLSSocket

平文 平文

暗号文

Node-v0.12のTLS処理概要

Node-v0.12でパフォーマンスを改善、APIを統一

• opensslとlibuvでデータと共有する Node_BIOを作成 → 両者の処理を一体化

• netモジュールのハンドルをtls_wrapが横取り → C++の処理だけで平文データを生成

• net.Socketを継承するTLSSocketを新設 → インターフェイスを統一 C++

Page 9: Node-v0.12のTLSを256倍使いこなす方法

TLSSocket

• Node-v0.10までの CleartextStreamの替わり

• CleartextStreamのAPIの互換保持

•ちゃんと net.Socketを継承し、APIを完備

• TLS周りの通信に関する新規機能のAPIを追加

より直観的でわかり易くなった。

EventEmitter

Stream

Readable Writable

Duplex

Socket

TLSSocket

Page 10: Node-v0.12のTLSを256倍使いこなす方法

AES-NI (Advanced Encryption Standard New Instructions)

• Intel, AMDのCPUに搭載されているAES暗号の処理機能

• 最近のモデルには多く搭載されている。/proc/cpuinfoで確認

• openssl-1.0系に実装済。Node-v0.10.x, v0.11.xでも使える

• 環境変数でAES-NIの有効・無効化してNodeのcryptoのベンチ比較AES-NI有効時 AES-NI無効時

22.8469

Gbit/sec

9.51245

Gbit/sec

AES-NI付きCPUのサーバを選んで使いましょう

AES-NIで2.4倍に性能向上!

Page 11: Node-v0.12のTLSを256倍使いこなす方法

PFS(Perfect Forward Secrecy)

•セッション毎に一時的に有効な公開鍵を交換して暗号鍵を共有する方式

•証明書の秘密鍵が危殆化しても過去の通信データを復号化できない。今後主流となる鍵交換方式。

• Node-v0.12から ECDHE, DHEの2種類が利用可能

• ECDHEの方が性能が良いのでそっちを優先指定(デフォルト)

• ECDHEはデフォルトで何もせず利用できる。(prime256v1)

• DHEの利用dhparamファイルを生成と指定が必要。現状十分な強度を持つには2048bit長以上で生成すること。

Page 12: Node-v0.12のTLSを256倍使いこなす方法

TLS False StartClientHello

ServerHello

Certificate

ServerHelloDone

ServerKeyExchange

ChangeCipherSpec

Finished

ハンドシェイク完了前に暗号化したアプリデータをフライングで送信

application data

ClientKeyExchange

ChangeCipherSpec

Finished

• TLS接続を高速化する技術 (2RTT→1RTT)

• TLSハンドシェイク完了直前に暗号化したアプリケーションデータをフライングで送信

• Chromeで2010年より先行実装、でも想定外の挙動のため問題頻発。

• TLSハンドシェイク完了前なのでダウングレード攻撃のリスクもあり一旦中止。

• NPNでプロトコル指定、PFS利用で利用可能に。

• IEやSafariなどは別の条件。

Page 13: Node-v0.12のTLSを256倍使いこなす方法

NodeでTLS False Startを使うにはNodeはデフォルトでNPN拡張を付与するのでPFSを利用すればクライアントはTLS False Startになる(*)

PFS利用していない時(AES128-GCM-SHA256)

PFS利用している時(ECDHE-RSA-AES128-SHA256)

TLS False Start によるTLSハンドシェイクの高速化

1RTT分

(*) IE, Safariは条件が違います

Page 14: Node-v0.12のTLSを256倍使いこなす方法

TLS Ticket•サーバからクライアントにTLS再接続時に利用する

CipherSuite/MasterSecretが含まれた設定データ(チケット)を暗号化して渡す。

•渡したチケット情報はサーバ側では保持しない。

•クライアントは再接続時にチケットをサーバに送信。サーバはチケットデータを復号化し、中のTLS設定情報を利用して通信を再開する。

•チケット鍵が複数のサーバ間で共有できていれば別サーバに行っても大丈夫。(ただし鍵管理が大変)

ClientHello

Sesstion Ticket Ext

ServerHello

SessionTicket Ext

Certificate

ServerHelloDone

ServerKeyExchange

NewSessionTicket

ChangeCipherSpec

Finished

ClientKeyExchange

ChangeCipherSpec

Finished

Page 15: Node-v0.12のTLSを256倍使いこなす方法

NodeでTLS Ticketを使う• Node-v0.10で既に使えるが、単一プロセスのみ。

• Node-v0.12ではクラスタの複数プロセス間でチケット鍵が共有可

• Cluster でTLSを使っている方は、今すぐNode-v0.12へ

Node-v0.10.33 のTLSクラスター

Node-v0.12-pre のTLSクラスター

Page 16: Node-v0.12のTLSを256倍使いこなす方法

OCSP Stapling• OCSP (Online Certificate Status Protocol):

• 証明書が失効していないか確認するプロトコル

• TLS初期接続時にクライアントが認証局サーバに確認。オーバヘッド

• OCSP Stapling:

• TLSサーバがOCSPレスポンスを証明書とともにクライアントに送信

• クライアントが認証局に確認する必要がない。Web表示の高速化

OCSP

Response

証明書+OCSP

Response

ClientHello +

status_request_v2 ext.

Page 17: Node-v0.12のTLSを256倍使いこなす方法

NodeでOCSP Staplingを使う• Node-v0.12では OCSPRequestイベントを新設

• コールバックの引数にOCSPレスポンスデータを渡し、クライアントに送信

• 認証局のOCSPサーバにリクエストするのは結構面倒なので、opensslで事前にリクエストデータを作成すると良い

• OSCPレスポンスデータのキャッシュ管理も必要。更新日時を取得するasn.1パーサも必要。エラー時の処理判断も大切。

• 別途cronでOCSPレスポンスデータを管理する手もある

server.on('OCSPRequest', function(cert, issuer, cb) {

var now = Date.now();

if (now > cache.nextUpdate && !cache.lock) {

cache.lock = true;

cache.der = null;

HandleOCSPrequest(cb);

} else {

var msg = cache.der ? 'cache hit!': 'terminated';

console.log( 'OCSP Response:', msg);

cb(null, cache.der);

}

});

ソースは、https://gist.github.com/shigeki/de5748cc0deb980bcb35

結果は openssl s_client –status –connect site:443 で確認

Page 18: Node-v0.12のTLSを256倍使いこなす方法

Dynamic TLS record (setMaxSendFragment)• GoogleのIlya Grigorik氏が推奨しているTLSパラメータのチューニング手法

• 通常TLSに書き込まれるデータ長は、レコードサイズ最大の16Kであることが多い。

• 最初のレスポンスデータの取得は、16Kバイトを受信してからになる。

• 最初のデータを復号化するには10個のTCPパケット(1.5K)を受信が必要。

• TLSのレコードサイズをTCPの1セグメントのサイズに収まるように小さくすれば受信した1個目からデータの復号化が可能になる。

• よって受信したデータの1バイト目が表示される時間の短縮が図られる。

1.5K 1.5K

16K

これ一つで復号可能よ

16K全部受信しないと復号できない

Page 19: Node-v0.12のTLSを256倍使いこなす方法

NodeでTLS Dynamic Recordをやるには• Googleサーバでのチューニング方法(ATSで採用済)

• 最初は 1.3Kのレコードサイズ (1500 - 40 (IP) - 20 (TCP) - 40 (TCP options) - TLS overhead (60-100))

• 1Mバイト送信したらデフォルトの16Kに変更。

• 書き込みのアイドルが1秒以上になったら1.3Kに戻す。

• Nodeでは自動的にレコードサイズをチューニングする方法は不採用に

• 替わりに固定的に変更するAPI(setMaxSendFragment)を新設

• 1.3Kで固定すると大きいデータで分割オーバヘッドが高くなる可能性も。

server.on('secureConnection', function(tlsSocket) {

tlsSocket.setMaxSendFragment(1300);

});

Page 20: Node-v0.12のTLSを256倍使いこなす方法

小さいTLS Record Sizeの効果(rtt=1000msec時)

MaxSendFragment 16K

default

MaxSendFragment 1.3K

Time To First Byteの高速化

requestStart responseStart

responseStartrequestStart

Page 21: Node-v0.12のTLSを256倍使いこなす方法

SPDY, HTTP/2• SPDY

• Googleが開発したWebの表示を高速化するプロトコル(TLSのみ)

• Google/Twitter/Facebook/Yahoo.comで使用中

• Chrome/Firefox/IE10/Safari 多数のブラウザでサポート中

• Nodeで使うなら node-spdyを使いましょう

• HTTP/2

• SPDYをベースとした次期HTTP仕様(TLS利用が中心)

• HTTP/1.1のセマンティクスを互換保持

• 現在仕様化作業の大詰め。来年前半には完了予定

• 現在Firefoxとのテストで利用中のnode-http2が使える

• 注意事項:

• node-v0.10で利用するとTLS要求仕様(AEAD+PFS)が合わず接続できない場合があります。node-v0.12を使いましょう。

• ただ開発は0.10系でやっているので未サポート

• ALPNはまだopensslのベータなためnodeでは使えません。

• 使う場合には私のfork版があります。 https://github.com/shigeki/node/tree/alpn_support

Ethernet

IP(v4/v6)

TCP

TLS

HTTP/2 Frame Layer

HTTP/1.1 Semantics

Page 22: Node-v0.12のTLSを256倍使いこなす方法

クライアント サーバ

1つのTCP接続

ストリーム(id:1)

フレーム

フレーム

ストリーム(id:3)

フレーム

フレーム

ストリーム(id:5)

フレーム

フレーム

HTTPリクエストレスポンス

HTTPリクエストレスポンス

HTTPリクエストレスポンス

SPDY, HTTP/2の全二重多重化通信

仮想的なストリームチャンネルを生成して多重化を実現

Page 23: Node-v0.12のTLSを256倍使いこなす方法

HTTP Head of Line Blockingを回避

HTTP/2クライアント

画像サーバA

画像サーバB

Reverse

Proxy

HTTP/2多重化通信

レスポンスが速い

レスポンスが遅い

HTTP/1.1クライアント

TCPを6本張れるけど、1本中に同時1リクエストの制限

1本のTCP

Page 24: Node-v0.12のTLSを256倍使いこなす方法

SPDYのメリットが一番よくわかるデモ多数の画像を表示して見え方に違いがあるのか? (SPDY vs HTTP/1.1)

1. 少数画像vs多数画像。

2. 3枚目の画像毎に3秒のレスポンス遅延を入れる。

Page 25: Node-v0.12のTLSを256倍使いこなす方法

まとめNode-v0.12でTLS通信を最適化する方法はいろいろあります。

用法用量を守って正しくお使いください。

(special thanks to http://www.irasutoya.com/)