- リバースプロキシを活用して、既存のWebページをQUICで配信したい。
- CaddyというWebサーバでは、引数に
-quic
をつけると、試験的にQUICで配信ができる。 - Amazon Linux 2016.09 では、 initを用いて、Caddyをサービス化させ、自動起動させるようにできる。
QUIC (Quick UDP Internet Connection)とは
Googleの開発しているトランスポート層のネットワークプロトコルです。 標準化されているものではなく、GoogleのサーバとChromeとの間での試験運用が行われている状況です。
技術的なことは、IIJ 大津さんのスライド(HTTP/2からQUICへ続くWebプロトコルの進化)がわかりやすいです。
QUICに対応しているWebサーバは少ない
※ほかにもあるとは思いますが、Caddyを見つけたあたりから探す気がなくなりました。
Caddy ってどんなWebサーバ?
QUICをサポートしているサーバとして、名前の知らないWebサーバが出てきました。 特徴はこんな感じです。
- Go言語で書かれている。
- 簡単にWebサーバが立てられる。
- FastCGIに対応している。
- リバースプロキシやロードバランサなどの機能も搭載している。
- Let’s Encryptのクライアントを内蔵していて、簡単に暗号化を有効にできる。
- HTTP/2 に既定で対応している。
- QUIC に試験的に対応している。(重要)
- 初期設定で、Qualys SSL Server TestでA判定が取れる。
うちの環境はASP.NETなので、IIS 10.0 のリバースプロキシとして利用してみます。
Caddy を使ってみる
前提条件
実験日: 2017/02/17 同一のセキュリティーグループ内に2台のサーバーを置いて実験しました。
リバースプロキシ
AWS EC2 上のインスタンス OS: Amazon Linux 2016.09 Caddy: 0.9.5
バックエンド(セットアップ済み)
AWS EC2 上のインスタンス OS: Windows Server 2016 Datacenter IIS: 10.0 (8080ポートで待ち受け)
Caddy をダウンロードする
ここからダウンロードします。 ソースコードではなく、バイナリが直接ダウンロードできます。
プラグインによって、さまざまな機能が追加できるようですが、リバースプロキシとして使う場合は、何もつけなくて大丈夫です。
このリンクは動的に作成されるようなので、直接wgetできません。一旦、端末側でダウンロードをしてから、SCPで送りましょう。今回は、Linux 64-bitを選びます。
ダウンロードしたファイルをSCPなどで転送したら、展開します。 (以下の例は、ec2-userのホームディレクトリに転送した場合)
mkdir caddy
cd caddy
tar zxvf ../caddy_linux_amd64_custom.tar.gz
ls -l
total 15416
-rwxrwxr-x 1 ec2-user ec2-user 15730207 Feb 6 13:52 caddy
-rw-rw-r-- 1 ec2-user ec2-user 14996 Jan 24 15:38 CHANGES.txt
drwxrwxr-x 7 ec2-user ec2-user 4096 Jan 24 15:38 init
-rw-rw-r-- 1 ec2-user ec2-user 25261 Jan 24 15:38 LICENSES.txt
-rw-rw-r-- 1 ec2-user ec2-user 994 Jan 24 15:38 README.txt
このように、実行可能ファイル”caddy”が既に含まれています。
Caddy を起動させてみる
Caddyの起動方法は、簡単です。
./caddy
Activating privacy features... done.
http://:2015
これで、2015番ポートでWebサーバが動作します。 なお、ルートディレクトリやポート番号などの指定は、引数かCaddyfileを用いて指定します。 今回は、ほとんどの設定(といってもほんの少しですが)をCaddyfileに記載します。
Caddyfile を作成する
Caddyfile とは、Caddyの設定を記載するファイルです。
実行時に以下の引数を指定することで、読み込ませることができます。 -conf=path/to/Caddyfile このファイルに記載できる内容については、公式サイトのdocsを見てください。 今回は、リバースプロキシとして必要な設定のみに触れていきます。
以下が、今回設定したCaddyfileです。
https://example.jp {
proxy / ip-xxx-xxx-xxx-xxx.aws-region.compute.internal:8080 {
header_upstream Host {host}
header_upstream X-Forwarded-For {remote}
}
tls admin@mail.example.jp {
}
Caddyfile は、{}で階層化されて表現される設定ファイルです。
一行目のhttps://example.jp
が、URLとなります。 Caddyでは、自動で証明書の取得が行われるので、特に間違えないようにする必要があります。 このバーチャルホストに関する設定を{}内に書いていきます。
二行目のproxy
は、リバースプロキシの設定です。 この設定では、/
へのアクセスが、http://ip-xxx-xxx-xxx-xxx.aws-region.compute.internal:8080/
へ転送される形になります。
proxy / web1:8080 web2:8080 web3:8080
のように記述すると、Caddyはロードバランサーとして機能します。 proxy
についての設定は、さらに{}内に記述します。 header_upstream Host {host}
– 元のhost
の情報をそのままバックエンドに送ります。 header_upstream X-Forwarded-For {remote}
– 元のIPアドレスをX-Forwarded-For
ヘッダでバックエンドに送ります。
六行目のtls
は、暗号化に関する設定ですが、非常にユニークです。 Caddyは、Let’s Encryptのクライアントを内蔵しているため、自動で証明書を取得します。 そのため、ここに証明書のパスを設定する必要はありません。(設定することもできる。) tls
には、次の4通りの設定ができます。
- off – HTTP通信を行う。(暗号化しない)
- self_signed – 自己署名証明書を作成して、それを使う。(暗号化する)
- email – ここにメールアドレスを入力すると、Let’s Encryptから証明書を取得し、それを使う。(暗号化する)
- /path/to/cert /path/to/private_key – 入力されたところにある証明書を使う。(暗号化する)
ここでも、細かくprotocolsやchiphersを設定できますが、初期設定のままで問題ないと思われます。 (TLS1.0が既定で無効となっているので、場合によっては注意が必要かもしれません。)
設定ファイルを読み込んでCaddyを起動する & QUIC を有効にする
ここまでQUICに関する設定はしていませんが、現在のところQUICの有効化は引数-quic
でのみできるようです。 ということで、設定ファイルを読み込みつつ、QUICを有効化して起動します。
./caddy -conf=/path/to/Caddyfile -quic
この状態で、Google Chrome などからアクセスを試行して、QUICが有効になっているか確認してみてください。 (Caddyでは、httpsのみが有効なバーチャルホストに対してhttpでアクセスすると自動的にhttpsに転送されますが、TLS1.2により接続されてしまいます。httpsに転送されたのちに更新するなどして再接続するとQUICで接続されるようになります。)
デーモン化させて自動起動するようにする
あまりやる人はいないと思いますが、Caddyをデーモン化させて自動起動させてみます。 これは、ディストリビューションにより変わってきますので、Amazon Linux 2016.09 での例となります。
Amazon Linux 2016.09 では、まだsystemdに移行していませんので、initを使うことになります。 まず、/etc/init.d/
以下にこのようなスクリプトを置きます。ファイル名は、caddy
などとしておくと良いでしょう。 (こちらを参考にさせていただきました。)
#!/bin/bash
# Caddy daemon
# chkconfig: 345 20 80
# description: Caddy daemon
# processname: caddy
DAEMON_PATH="/path/to/caddy/"
DAEMON='./caddy'
DAEMONOPTS="-quic -conf=/path/to/Caddyfile -log /var/log/caddy.log"
NAME=caddy
DESC="Caddy upstart"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
case "$1" in
start)
printf "%-50s" "Starting $NAME..."
cd $DAEMON_PATH
PID=`$DAEMON $DAEMONOPTS > /dev/null 2>&1 & echo $!`
echo "Saving PID" $PID " to " $PIDFILE
if [ -z $PID ]; then
printf "%s\n" "Fail"
else
echo $PID > $PIDFILE
printf "%s\n" "Ok"
fi
;;
status)
printf "%-50s" "Checking $NAME..."
if [ -f $PIDFILE ]; then
PID=`cat $PIDFILE`
if [ -z "`ps axf | grep ${PID} | grep -v grep`" ]; then
printf "%s\n" "Process dead but pidfile exists"
else
echo "Running"
fi
else
printf "%s\n" "Service not running"
fi
;;
stop)
printf "%-50s" "Stopping $NAME"
PID=`cat $PIDFILE`
cd $DAEMON_PATH
if [ -f $PIDFILE ]; then
kill -HUP $PID
printf "%s\n" "Ok"
rm -f $PIDFILE
else
printf "%s\n" "pidfile not found"
fi
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {status|start|stop|restart}"
exit 1
esac
このスクリプトファイルに実行権限を与えます。
chmod +x caddy
続いて、chkconfig
でサービス登録をすれば完了です。
chkconfig --add caddy
これで、起動時に自動起動されるようになります。 また、以下のようにサービスの制御も行えるようになります。
service caddy start
service caddy status
service caddy stop
まとめ
今回は、Caddyを使って既存のWebページを無理やりQUICで配信できるようにしてみました。 したがって、実際にQUICの持つ恩恵を受けられるのかは疑問が残ります。 ただ、周囲に先駆けてQUICをサポートしているのを見せつけて楽しむことくらいはできますね。 (HTTP/2 and SPDY indicatorが緑色に光ります。) 時間があったらベンチマークなどもしてみたいですが、条件を整えるのも難しそうなのであまり優先順位は高くないです。
ネイティブにASP.NET のアプリケーションをQUICで配信するには、IIS がQUICに対応する必要があると思いますが、 実際にMicrosoft社内ではQUICによるWebサーバが作られているという話も聞くので、楽しみに待っていたいと思います。 (そのまえに、規格化されなければなりませんが。)
参考文献・リンク
- Caddy – Official Site – Caddyの頒布元
- HTTP/2からQUICへ続くWebプロトコルの進化 – 非常に分かりやすいプレゼンです。(11/11 IIJ 大津さんのもの)
- caddy int.d script – slav123 – caddy用のinitスクリプトを参考にしました。
- (CentOS6まで)自作のサービスをchkconfigで登録する – chkconfigでのサービスの登録方法を参考にしました。