自前で構築しているWebサービスが複数あって、独自ドメインで運用しております。
実態としてはdocker+nginxリバースプロキシ+Let'sEncryptで1台のホストに対して複数のWebサービス、
DNSはAWSのRoute53を使っていました。
その時の記事はコチラ。
dockerのリバースプロキシ+Let's Encryptでお手軽に複数のWebサーバをSSL化
nginxはえんじんえっくすって言います
運用上は特に問題ないんだけど、不満点が以下。
- Route53の利用に月額$0.5かかる(完全無料ではない)
- Let's Encryptの仕様上、Webサービスのコンテナの再起動を繰り返すと暫くの間Webアクセス不可になる
1つ目は月100円もいかないので大したことないが、不満が2つ目。
Webサービスをコンテナでサクッと作ろうとしてもなかなかうまく動かないのが常。
あれこれと再起動を繰り返すたびにSSL証明書を再発行しようとするので、
いざコンテナで作ろうとしたときにLet'sEncryptの証明書発行制限にかかってしまい、5日間ほど証明書が発行できない=Webアクセスできない
というジレンマが発生する。
安定稼働するまでSSL証明書発行を止めたらいいやんって思うけど、証明書発行の部分もコンテナ化されてるので仕組みがよくわからんwwwwwwww
というわけで、"Cloudflare"というサービスが無料でDNS管理とSSL証明書発行を行ってくれる、ので乗り換えてみました。
しかもCloudflareだとDDoS、CDNも無料で使える、と。
個人利用だと、無料というのが非常に大きいので使わない手はない。
結果的に乗り換えて満足しているんだけど、新たなデメリットも出てきたのでのちほど説明します。
DNSレコードの移行
Cloudflare上でアカウント登録し、ドメインも登録する。
ドメインレジストラの方でネームサーバをAWSからCloudflareが指定するサーバに切り替えるだけ。
DNSレコードはある程度は自動で移行してくれるし、自動で移行してくれないものは手動で移行すればOK。
SSL証明書の発行、登録
次にSSL証明書。
Cloudflareの証明書を利用することで、サーバに直接アクセスされることがなく、Cloudflare側でリクエストを受け付けてくれる。
所謂、ロードバランサ的な役割。
これだけでブラウザ-Cloudflare間はHTTPS通信がされる。
Cloudflare-サーバ間はサーバ側にSSL証明書を組み込めばフルでHTTPS通信が可能。
サーバ側の証明書もCloudflareが提供してくれる。(自己証明書だが、Cloudflare経由だと問題なし)
ってなわけで、CloudflareのSSL設定を実際にやってみた。
Cloudflareの管理画面より、「SSL/TLS」の「概要」をクリックし、暗号化モードを「フル(厳密)」にする。
ちなみに各項目の説明は以下。
・フレキシブル:ブラウザ-Cloudflare間のみHTTPS化。Cloudflare-サーバ間は考慮しない
・フル:Cloudflare-サーバ間もHTTS化。オレオレ証明書でもOK。
・フル(厳密):上記に加えて、正規の証明書もしくはCloudflare証明書のみ。
最低限「フレキシブル」を設定しておけば、手っ取り早くHTTPS化は実現出来る。
ちゃんとやるならサーバに証明書を登録する必要があるけど、そこはお好みで。
次にサーバに登録する証明書の発行。
「オリジンサーバー」をクリックして、「証明書を作成」をクリックする。
「プライベートキーの種類」を選択し、「ホスト名」を指定。
これはワイルドカード指定もできる。
「証明書の有効期間」も指定。デフォルトで15年という太っ腹仕様w
以上で、証明書ファイルとプライベートキーが発行される。
この後、サーバにファイルを置くことになるんだけど、
ここでは証明書ファイルを「default.crt」、プライベートキーを「default.key」としてサーバに保存する。
サーバ側の設定
証明書ファイルの準備ができたので、サーバ側に設定する。
それぞれのWebサーバの設定次第なんだけど、
俺の環境ではdockerでnginxリバースプロキシ(jwilder/nginx-proxy)を立てているので、その前提で書きます。
nginx-proxyコンテナのdocker-compose.ymlを修正。
version: '3' services: nginx-proxy: image: jwilder/nginx-proxy container_name: nginx-proxy ports: # - 80:80 ←80/tcpポートを削除 - 443:443 volumes: - /docker/nginx-proxy/certs:/etc/nginx/certs # ←Cloudflareで発行した証明書を置く場所 - /docker/nginx-proxy/vhost:/etc/nginx/vhost.d - /docker/nginx-proxy/html:/usr/share/nginx/html - /var/run/docker.sock:/tmp/docker.sock:ro restart: always environment: - TZ=Asia/Tokyo labels: - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy" # letsencrypt-nginx-proxy-companion: # image: nginxproxy/acme-companion ←nginxproxy/acme-companionイメージは不要
次にWebサービス側のdocker-compose.yml。
(省略)
environment:
- TZ=Asia/Tokyo
- WEBUI_PORT=30000
- VIRTUAL_HOST=aaaa.hogehoge.com
- VIRTUAL_PORT=30000
- CERT_NAME=default # ←証明書のファイル部分
# - LETSENCRYPT_HOST=aaaa.hogehoge.com ←不要
CERT_NAMEという変数名に証明書のファイル名を指定することで、
nginx-proxyがその証明書ファイルを利用する、というわけ。
あとはコンテナを起動し直せば終わり。
ブラウザから確認
ブラウザから証明書が変わっていることを確認。
変更前。発行者がLet's Encryptとなっている。
変更後。Cloudflareに変わっている。
Cloudflareを利用することのメリット、デメリット
メリットは以下。
- DNSやSSL証明書が無料で利用できる
- 証明書の有効期間が15年なのでほぼ更新不要
- CDNやDDoS対策も使える
と、DNS管理だけでなくWebサーバ管理にとって非常に有用なツールだ。
一方でデメリットもそれなりにある。
- DNSレコードをCloudflareプロキシONにしておくと、ホスト名でSSH接続できなくなる
- 上記同様にWebアクセスできるポート番号が限定される
クラウド上のサーバにSSHログインする際に、そのホスト名でログインができなくなる。
さらには例えば"https://FQDN名:10000/"といった特定のポート番号でアクセスが出来なくなる。
理由としては、エッジとなるCloudflare側で特定のポートしか受け付けないようになっているから。
以下の主なWebアクセスで利用されるポートしか使えない。
https://blog.cloudflare.com/cloudflare-now-supporting-more-ports/
2番目のポート番号限定はnginx-proxyを使えば常に443/tcpアクセスにできるので大したことないが、
1番目のSSH接続ができなくなるのは結構めんどくさい。
回避策としてはIPアドレスを直接指定して接続するか、
別名のDNSレコードを登録して、Cloudflareプロキシを無効にすればOK。
上記のように「DNSのみ」となっていれば、DNSの名前解決のみ提供される。
「プロキシ済み」にすると、SSL機能が有効になる。
SSH接続するには他の方法もあるみたいなんだけど、
サーバ、クライアント両方に設定しないといけないので、ちょっとめんどくさいから
俺はDNS名を分けることで使ってる。
DNS以外の機能も充実しており、Cloudflareは無課金者に非常に強い味方
もはやhttps化は必須となっている世の中。
Let's Encryptでも十分なんだけど、
Webサーバの前にエッジサーバを置くことで、さらにWebセキュリティを強化することができる。
Cloudflareなら無料で実現できるので、非常にありがたい。
しばらくはこの状態で使ってみようと思う。
0 件のコメント:
コメントを投稿