NginxでTLS1.3の0-RTTハンドシェイク (ssl_early_data)を試す

追記20180922
OpenSSLも対応しました
「support for TLSv1.3 early data with OpenSSL.」
http://hg.nginx.org/nginx/rev/548a63b354a2


昨日、NginxがTLS1.3の0-RTTハンドシェイクをサポートしたので試した。無事動作することが確認できた。

該当コミットはこの2つ

TLS1.3の0-RTTハンドシェイクは、一度ハンドシェイクをした相手とはClientHelloに続けてアプリケーションデータ(HTTPリクエスト)を送信することで、より早くデータのやりとりを開始する方法です。

f:id:ASnoKaze:20180808013052p:plain
(引用: https://blog.cloudflare.com/tls-1-3-overview-and-q-and-a/)

通常のResumptionよりも1-RTT分早くHTTPリクエストを送信されることになります。しかし、このデータは再送攻撃が可能ですので、冪等なリクエスト以外はearly_dataを拒否すべきです。詳しくは以前書いた記事を参照
asnokaze.hatenablog.com

BoringSSL

コミットログに書かれている通り、BoringSSLを使用する必要があります。
基本的には公式のビルド手順のとおりです

(ninjaの公式ページからninjaをダウンロードしておく)

git clone https://github.com/google/boringssl.git
cd ./boringssl

mkdir build
cd build
cmake -GNinja ..
ninja

nginxのビルド準備

#./boringsslのディレクトリ
mkdir -p .openssl/lib 
cd .openssl 
ln -s ../include . 
cd ../ 
cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib

nginxのビルド

wget http://hg.nginx.org/nginx/archive/tip.tar.gz
tar zxvf ./tip.tar.gz
cd ./nginx-ba971deb4b44 #解凍したディレクトリ

./auto/configure  --with-openssl=/PATHTO/boringssl/ --with-http_ssl_module
make

config

nginx.conf内で、ssl_early_data on と指定することで0-RTT early_dataが有効になります

    server {
        listen       443 ssl ;
        server_name  localhost;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        ssl_early_data on;
...

アクセスしてみる

nginxを起動する

sudo ./nginx-ba971deb4b44/objs/nginx

せっかくなので boringssl のtoolを使う

cat ./boringssl/build/request.txt //early_dataをtxtに書いておく
GET / HTTP/1.1
host:localhsot


./boringssl/build/tool/bssl client -tls13-variant draft28 -connect 127.0.0.1:443  -test-resumption -early-data @./request.txt
Connecting to 127.0.0.1:443
Connected.
  Version: TLSv1.3
  Resumed session: yes
(略)
  Early data: yes #★ Early data: yesとなる 

HTTP/1.1 200 OK
Date: Tue, 07 Aug 2018 16:25:00 GMT
Content-Type: text/html
(略)

nginx ログ

nginxのログでも、$ssl_early_data でearly_dataがあったか確認できる

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '$ssl_protocol $request_time early=$ssl_early_data';

こんな感じのログが出る

127.0.0.1 - - [07/Aug/2018:16:19:15 +0000] "GET / HTTP/1.1" 200 612 "-" TLSv1.3 0.000 early=1