Help us understand the problem. What is going on with this article?

Go 言語最新ツールチェインをビルドして、Caddy で TLS 1.3 を試す

More than 1 year has passed since last update.

概要

TLS 1.3 は、2018 年 8 月 に RFC 8446 として、正式リリースとなりました。

OpenSSL 1.1.1 で、TLS 1.3 は正式サポートとなり、各種ソフトウェアでも実装が進むものと思われます。

Golang でも、最近 TLS 1.3 サポートが、master ブランチへマージされたようです。

Golang の次のリリースは、v1.12 が 2019 年 2 月 の見込みです。Golang では、ナイトリービルドを提供していないみたいですが、処理系のビルドはそれほど難しくないので、最新の master ブランチをビルドして、TLS 1.3 を試用してみましょう。

ビルドには、docker を使用し、試用するサーバーソフトウェアとしては、Golang で実装された HTTP サーバーである Caddy を用います。

Golang 最新版ビルド

通常であれば、Dockerfile を作成して、イメージを作成するところですが、お試しということで、volume を活用して、ビルド成果物を作成します。

docker を使用できる環境で、以下のようにコマンドを打ち込みます。

$ docker volume create --name v-go
$ docker run -it --rm -v v-go:/root/go -w /root/go -e GOROOT_BOOTSTRAP=/usr/local/go golang:1.11

# git clone https://go.googlesource.com/go .
# cd src
# ./all.bash
# exit

v-go という名前の volume に最新版の Golang がビルドされます。

Caddy ビルド

先ほどビルドした、ツールチェインを用いて、Caddy をビルドします。

$ docker volume create --name v-caddy
$ docker run -it --rm -v v-go:/usr/local/go -v v-caddy:/go golang:1.11

# go get github.com/caddyserver/builds
# cd src/github.com
# mkdir mholt
# cd mholt
# git clone https://github.com/mholt/caddy.git
# cd caddy
# git checkout -b v0.11.1 v0.11.1
# cd caddy
# go run build.go
# exit

v-caddy 内部に、Caddy がビルドされます。

次のようなコマンドで、ビルド済ファイルを取り出すことができます。

$ docker create --name v-caddy -v v-caddy:/go busybox
$ docker cp v-caddy:/go/src/github.com/mholt/caddy/caddy/caddy .

こちらのバイナリーは、TLS 1.2 までのサポートになるバージョンになりますので、caddy-tls1.2 等へリネームしておきます。

パッチあて

先ほどビルドした Caddy は、TLS 1.3 対応になっていませんので、対応させるパッチを実施します。

golang:1.11 のイメージに patch コマンドが入っていないので、buildpack-deps:stretch のイメージを使用します。

$ docker run -it --rm -v v-caddy:/go -w /go/src/github.com/mholt/caddy buildpack-deps:stretch

# curl -LO https://gist.github.com/noumia/ad9787f4c8094976221e0b3419ecafb2/raw/1f97a61215c0b31d829e4c102c420382b4c12149/caddy.patch
# patch -p1 < caddy.patch
# exit

再ビルド

パッチ後の再ビルドと、バイナリーファイル抽出は、以下のようになります。

$ docker run -it --rm -v v-go:/usr/local/go -v v-caddy:/go -w /go/src/github.com/mholt/caddy/caddy golang:1.11

# go run build.go
# exit

$ docker cp v-caddy:/go/src/github.com/mholt/caddy/caddy/caddy .

動作チェック

任意のディレクトリーへ、Caddyfile ファイル、秘密鍵、証明書ファイル等を配置します。

Caddyfile
https://loop.example.com {
  tls cert/server.crt cert/server.key
  root html
}

cert/server.crt へ証明書
cert/server.key へ秘密鍵
html/index.html へ配信ファイル

を展開します。

example.com は例示ドメインなので、ご自身で使用するドメインに読み替えてください。

ここでは、*.example.com に充当するワイルドカード証明書を用意しました。

ワイルドカード証明書は、有効なドメインをお持ちであれば、Let's Encrypt で無料で取得できます。

Caddyfile のあるディレクトリーをカレントディレクトリーとして、caddy コマンドを起動します。

$ sudo ./caddy

クライアントでの接続チェック

別ターミナルを立ち上げて、通信チェックを行います。ここでは、OpenSSL 1.1.1 をリンクした TLS 1.3 対応の curl を使います。

>curl --version
curl 7.62.0 (x86_64-pc-win32) libcurl/7.62.0 OpenSSL/1.1.1a (WinSSL) zlib/1.2.11 brotli/1.0.7 WinIDN libssh2/1.8.0 nghttp2/1.35.0
Release-Date: 2018-10-31
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz brotli TLS-SRP HTTP2 HTTPS-proxy MultiSSL

接続します。

>curl -v https://loop.example.com
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to loop.example.com (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: C:\Sirius\.bin\curl-ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=example.com
*  start date: Nov 20 05:17:39 2018 GMT
*  expire date: Feb 18 05:17:39 2019 GMT
*  subjectAltName: host "loop.example.com" matched cert's "*.example.com"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* Using Stream ID: 1 (easy handle 0x22452c620a0)
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> GET / HTTP/2
> Host: loop.example.com
> User-Agent: curl/7.62.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.3 (OUT), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/2 200
< accept-ranges: bytes
< content-type: text/html; charset=utf-8
< etag: "piucxp0"
< last-modified: Tue, 27 Nov 2018 07:32:13 GMT
< server: Caddy
< content-length: 0
< date: Tue, 27 Nov 2018 07:45:10 GMT
<
* Connection #0 to host loop.example.com left intact

TLSv1.3 というログが見えているので、うまくいったようです。

比較のために、TLS 1.3 対応パッチをあてる前のバイナリーを実行したときの接続ログは、次のようになります。

>curl -v https://loop.example.com
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to loop.example.com (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: C:\Sirius\.bin\curl-ca-bundle.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=example.com
*  start date: Nov 20 05:17:39 2018 GMT
*  expire date: Feb 18 05:17:39 2019 GMT
*  subjectAltName: host "loop.example.com" matched cert's "*.example.com"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x1c82c5d20a0)
> GET / HTTP/2
> Host: loop.example.com
> User-Agent: curl/7.62.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< accept-ranges: bytes
< content-type: text/html; charset=utf-8
< etag: "piucxp0"
< last-modified: Tue, 27 Nov 2018 07:32:13 GMT
< server: Caddy
< content-length: 0
< date: Tue, 27 Nov 2018 07:44:39 GMT
<
* Connection #0 to host loop.example.com left intact

TLS 1.2 にダウングレードして接続されています。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away