Cloudflareを使っておひとりさまサービスたちをHTTPS化する

この記事は [ドワンゴ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/dwango) 3日目の記事です。

# はじめに
こんにちは、@brp と申します。

普段は趣味でVPSや自宅サーバーで色々なプロダクトをセルフホスティングしておひとりさまサービスを運用しています。

個人サービスを運用するうえで、どうシステムをHTTPS化するか…？という悩みに当たったことがある方は多いのではないかと思います。

HTTPS化をすることは意外と手間で、しかし運用しようとするものは限られた範囲の人間や自分しか使わない。
ましてやいつ気分で落とすかもわからないサービスにそんなに手間やお金をかける…？

可能な限り楽に、気軽にプロダクトをホスティングして、あんまり使わなかったりリソース逼迫するようなら落として…と雑に運用したい…

でもやりとりする情報、特に認証情報らのためにある程度セキュアにはしたい…お金はあんまり無い…

そんな中、少しでも安く、楽に運用できる方法がないかなと考えた…そんな話を書いていきます。

## 想定構成
実現したい構成は以下のとおりです。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131298/758ad144-9abf-e6ec-c159-0c84d8432b01.png)

ポイントは、
- アプリケーションは気軽に落としたり上げたりしたい
- ~~お金がないので~~1台のホストに複数のアプリケーションを立ち上げて、複数のサブドメインを割り当てる
- SSL証明書はワイルドカード証明書を使用し、ドメインを包括したい
- クライアント-サーバー間は全面的にHTTPSとしたい

アプリケーションを上げるときのリリース以外の作業は、DNSでサブドメインを切ることと、nginxのバーチャルホスト設定[^1]のみで良い環境を実現します。

# Let's Encryptは？
Let's Encryptは世界最大の認証局であり、DV証明書を無償で発行することが可能です。
本当にありがたい限りです。

対話形式のコマンドラインで楽に証明書を発行することができ、更新作業もrenewコマンド一発叩くだけで完了することができます。
個人でホスティングするサービスをHTTPS化したい場合大きな選択肢となるのではないでしょうか。

Let's Encryptを利用する場合以下のデメリットがあります。
- 証明書の有効期限が短い（90日）
- ワイルドカード証明書の発行手順が面倒

Lets Encryptで発行したワイルドカード証明書はrenewコマンドによる更新はできず、毎度DNS認証が発生します。
そのため、更新作業が面倒になってしまう上、90日の短いスパンで実施することになってしまいます。

こういったオペレーションを自動化するところにモチベーションがあればよいのですが、関心は動かしてみたいプロダクトや作った個人サービスなので、なんとかこういった手間からは脱却したくなります。

# ここでCloudflare

https://www.cloudflare.com/

Cloudflareは主要サービスとして、DNSとリバースプロキシを提供してくれます。
採用した場合の構成図は以下のようになります

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131298/958cccfb-0847-5bbc-77bd-65732d0eeca5.png)

Clouflareがクライアントのリクエストを全て一度受け、それをオリジンサーバーに中継する形となります。

クライアントから見たエンドポイントはCloudflareのサーバーとなり、オリジンサーバーの情報は秘匿されることとなります。

このとき、クライアント～CloudflareとCloudflare～オリジンサーバの通信は完全に別物となり、個別のSSL設定が必要となります。

しかし、この中でクライアント～Cloudflare間のHTTPS化と証明書はCloudflareが管理してくれ、更新もCloudflareの機能が自動で行ってくれます。

そのため、考えるところはCloudflare～オリジンサーバのHTTPS化のみになるのですが、これまたこの間の経路の暗号化で必要な証明書はCloudflareが発行してくれます。

この証明書はデフォルトでワイルドカード証明書として発行でき、また期限も最長15年とかなり長く設定することができます。

そのため、通常通りこのワイルドカード証明書をオリジンサーバのnginxに適用するだけですべての経路をHTTPS化することができ、更新頻度をそれなりにする運用も実現することができます。

## デメリット
Cloudflareを挟むことによるいくつかの制限が発生します。

### Proxy modeが必須になる
CloudflareのDNSにはProxy modeとDNS modeがあるのですが、今回これをProxy modeにする必要があります。
こうなるとオリジンサーバの生IPは露出せず、必ずCloudflareによるリバースプロキシを通るようになりますが、次のデメリットと相まって制限が生まれます。

### HTTP/HTTPS以外の通信はプロキシできない
CloudflareのプロキシはHTTP/HTTPSのみです。
そのため、アドレスにFQDNを指定してホストにSSHするなどの運用はできなくなってしまいます。
有料サービスの[Cloudflare Spectrum](https://www.cloudflare.com/ja-jp/application-services/products/cloudflare-spectrum/)を利用することで、一部のプロトコルを追加でプロキシすることはできますが、Businessプランまで上げてもSSH/Minecraft/RDPのみとなる上、通信量に制限があり、導入にはハードルが高いです。

一部のサブドメインのみDNSモードを利用するような設定をすれば、そのサブドメインのFQDNを指定したときはオリジンサーバとの直接アクセスとなり制限はなくなります。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131298/6cd0b256-c1d8-8003-cfb5-b8a026da5c0a.png)

しかし、一部のサブドメインはCloudflareがエッジサーバーとして見えているのに、一部ではオリジンサーバが露出する、といった歪な構成となってしまいます。

* * *

デメリットは基本的にWebアプリケーションの提供を行う上では問題ないのですが、他にも色々やろうとするとき障害になる可能性があります。

また、デメリットではありませんが、オリジンサーバに適用したCloudflareが発行した証明書はCloudflare-オリジンサーバーの通信でしか使用できません。
そのため、事情があり一部のサブドメインでオリジンサーバとの直接通信を行う場合、別途証明書を発行する必要があります。

# おわりに
制約はありますが、Cloudflare経由でサービス提供を行うことは用途がWebシステムのみのホスティングであったりする場合にかなり保守のコストを削減できる手段となると思います。
Cloudflareはこれ以外にもアクセス分析など、セルフホスティング勢にはかなり嬉しいサービスがフリープラン内でも多く整っています。
もしご興味あれば一度導入を検討してみると、なにか面白いことが起こるかもしれません。

# 余談
12月はじめの火曜日！Cloudflareのことを書くならこの日しかねえな！
そんな思いでこの記事はこの日に公開されています。

[^1]:`server_name`ディレクティブを用いて単一のホストに複数のサブドメインを適用する設定を指しています。Apacheの用語みたいですが、nginxのときこの一連の設定を示す単語って何なのでしょう…