WebサーバのSSL化対応
■WebサーバのSSL化
keitaircのSSL化を棚上げしていたものをようやくやったので、その話。
■Reverse Proxy(トンネリング)の構築に向けて
keitaircのssl化はマニュアルにある通り、mod_ssl等を利用することを想定している。
keitairc自体はApacheやNGINXに代表されるようなHTTPサーバ上で動いているわけじゃなく、keitairc自身が簡易サーバとして動作しているため、わざわざmod_sslモジュールを使うためだけにApacheを立ち上げるのもめんどくさい。
そこで、NGINXなどでReverse Proxyを立ち上げてトンネリングすることで、サーバの外はhttpsで動作し、サーバ内は今まで通りhttpで動作させることにした。
イメージとしてのReverse Proxyの導入イメージはこんな感じ。
HTTPS<-->HTTPをReverse Proxyで繋ぐ。
HTTPSの処理はReverse Proxyにて行うため、HTTPより奥では処理に変更がないことになる。
+--------------------------------------+ |Server | |+---------+ +----------+ +--------+|| || Reverse | | keitairc | | tiarra ||| Inter Net --|| Proxy |--| (HTTP) |--| (TCP) ||| || (HTTPS) | | | | ||| |+---------+ +----------+ +--------+|| +--------------------------------------+
■いろいろな選択肢
■選択肢 Apacheを使う(mod_proxy/mod_ssl)
Apacheのモジュールとして動作するため、基本的にApache+(mod_proxy or/and mod_ssl)として動作させる。 現状ではhttpdが必要な用途がReverse Proxyのみのため、正直面倒。
■選択肢 NGINXを使う
静的HTMLコンテンツの配信に長けているhttpdの一種。 一応モジュールの追加でCGIも動作させることもできるらしい。 とはいえ、Apache同様にhttpdが必要な用途がReverse Proxyのみのため、面倒なことに変わりはない。
■選択肢 other
■gost
go言語で書かれたgostっていう多機能プロトコル変換中継simple tunnelソフトウェアらしい。
# gost - GO Simple Tunnel がすごい
■stone
c言語で書かれたアプリケーションレベルの TCP & UDP リピーター。 ## Simple Repeater
■用途として一番しっくり来たstoneを使用する
sourceをDLしてmakeしないといけないのだが、だいたいeldorado-of.infoのWiki/stoneの通りにコマンドを打ち込むだけで苦も無く実行可能バイナリが出来上がる。
ただし、使用しているバージョンは正式版ではあるが、2008-02-05にリリースされたバージョンでもあるので、ここが厄介。
ということで、stoneのCVSを覗いてみるとOpenSSL 1.1.1に対応したソースが公開されているので、wgetコマンドにCVSのtarballリンクアドレスを指定して、ソースをまとめてダウンロードして使用する。
このバージョンだと先の説明にあったようなmakefileの書き換えや、ワーニング等は発生しなかった。
■stoneのmake完了後の動作確認
makeが終わったら動作確認のために適当に起動をしてみる。
以下例はstoneを外側ポート1000で待ち受けて、内側ポート1100とつなぐという感じ。
これで動作が確認出来たらひとまずよしとする。
stone localhost:1000 1100
■SSLサーバ証明書
Webサーバをhttps化するにあたって、SSLサーバ証明書が必要になる。
いろいろ発行機関はあるが、個人利用であるためLet’s Encryptを使用することにした。
■Let’s Encryptでの証明書発行準備
■certbot導入
Let’s Encryptの証明書発行においては、ホームページに記載のある通りcertbotを導入する方向にした。
参考サイトを見つつこれもインストールと証明書の発行を行っていく。
# CentOS7】Lets EncryptでSSL証明書を取得
■証明書自動更新設定
Let's Encryptの証明書については、期限が3か月なので、自動更新の設定も併せて実施する。
とりあえずは証明書更新コマンドの確認をしてみる。
sudo certbot renew --dry-run
コマンドが正常に動作することを確認したら、cronに設定を追加する。 証明書更新は1か月を切ったら新しいのが発行できるらしいのと、証明書更新コマンド自体は実行して空振りに終わるか更新できるかなので、月1回実行する形の例。 これで毎月1日の0時0分に実行される形になる。
00 00 01 * * sudo /usr/bin/certbot renew
■stone起動設定
confファイルを使用することでコマンドラインオプションを定義ファイルとして保存できるので、起動条件を変更する場合も簡単になる。
■定義ファイル作成
以下は証明書と秘密鍵の指定とTLS1.2の指定、HTTP<->HTTPSのトンネルを行うポート設定を指定する。
他の指定は用途毎に指定する。
-z key=/etc/letsencrypt/live/example.com/privkey.pem -z cert=/etc/letsencrypt/live/example.com/cert.pem -z verify,none -z CApath=/etc/letsencrypt/live/example.com -z tls1.2 stone localhost:1000 1100/ssl
■stone起動確認
証明書を起動時に読み込む必要があるので、証明書のシンボリックリンク等を専用の場所に作成するか、certbotに合わせてrootで起動してみる。
これでstoneの起動が確認できたらブラウザアクセスをして接続できることを確認する。
nohup sudo /usr/local/bin/stone -C target_conf &
■起動用シェル
stone起動用に以下のシェルを作成。
サーバリブート時の起動と、証明書更新時の自動再起動を想定した再起動を行うために最低限必要なことだけを行っている。
プロセスを再起動するため、ポート開放の可能性を考えて適当に10秒スリープさせている。
#!/bin/bash -l cd /Local/stone_home ## Kill if [ `ps -ef | egrep "stone.+conf" | egrep -v "grep|sudo|bash" | wc -l` -ne 0 ]; then for stone_proc in `ps -ef| egrep "stone.+conf" | egrep -v "grep|sudo|bash" | awk '{print $2}'` do sudo kill -9 $stone_proc done fi sleep 10 ## Start for target_conf in `ls stone*.conf` do if [ `ps -ef | egrep $target_conf | egrep -v "grep|sudo|bash" | wc -l` -eq 0 ]; then nohup sudo /usr/local/bin/stone -C $target_conf 1>/dev/null 2>&1 & fi done
このシェルをサーバ起動時及び、certbot起動後に動作するようにcronを設定して終わり。
@reboot /Local/stone_run.bash 1>/dev/null 2>&1 & 00 00 01 * * sudo /usr/bin/certbot renew && /Local/stone_run.bash 1>/dev/null 2>&1 &