Cloudflareの無料機能を使ってmTLSを試す

目次

Cloudflareの無料機能を使って自宅のWebサーバをインターネットに公開しつつ、証明書をインストールした特定の端末からのみアクセスできるようにmTLSを設定してみたメモ

背景

ファイルサーバや家電のコントローラーなど、自宅の装置にインターネットからアクセスする方法を考えたとき、今までは以下のような方法を使っていた。

  • VPNやZTNAを使う (L2/L3)
  • SSHの公開鍵認証を通した後にポートフォワード (L7 + L3L4)
  • パスワード, パスキー認証をする (L7)

しかし、どの方法も少しずつ面倒くさポイントがあり、たびたびちょっとしたストレスを感じていた。

そこで、今回はmTLS(mutual-TLS, 相互TLS)認証を利用して、証明書をインストールした特定の端末のみからアクセスできるようにすることでセキュリティを担保しながら、自宅の機器へインターネット経由HTTPSアクセスできるようにしてみた。

構成

今回はCloudflareの無料機能を組み合わせて構築していく。

手順

Client certificatesの作成と設定

Cloudflareのドメインの設定画面から以下のように辿り、クライアント側で使う証明書を作成する。
SSL/TLS -> Client Certificates -> [Create Certificate]

Private key typeはRSA(2048)とECCが選べる。最近の端末でのみ利用するのであればECCで問題ないはず。

クライアント証明書作成画面

作成された証明書と秘密鍵が表示されるので、それぞれメモ帳などに貼り付けて適当なファイル名で保存する。OKを押してしまうと再確認はできないため注意。
(例: Certificateはtest.notr.app.pem、Private Keyはtest.notr.app.key)

クライアント証明書作成完了後画面

無事に保存が終わったらOpenSSLなどを利用して証明書と秘密鍵を1つにまとめてPKCS#12に変換する。ここで適宜パスワードを設定して暗号化しておくと良いかもしれない。

openssl pkcs12 -export -in test.notr.app.pem -inkey test.notr.app.key -out test.notr.app.p12

作成されたp12ファイルを端末に送信してインストールする。パスワードを設定した場合はインストール時に入力する。

最後に、CloudflareのダッシュボードでmTLSを利用するホスト名を設定する。

mTLS利用ホスト名設定画面

WAFルールの作成

今回は上記画面のCreate mTLS Ruleボタンをクリックし、テンプレートを使ってmTLS認証が通っていないアクセスをブロックするWAFルールを作成する。
例として下記の画面では、
mTLS認証が成功していない かつ ホスト名が test.notr.app の場合に アクセスを拒否する(Block)ルールを作成している

WAF設定画面

Cloudflare Tunnelを利用したサーバの公開

Cloudflare Zero Trustのダッシュボードで Networks -> Tunnels -> Create a tunnel の順に進み、cloudflared で案内に従いトンネルを作成する。

Cloudflare Tunnel作成画面

Route Traffic画面で、公開したいホスト名とアクセス先のスキーマ、URLを指定する。

Route Traffic設定画面

テスト

証明書をインストールしていない端末のWebブラウザやcURLで設定したURLにアクセスし、接続がブロックされることを確認する。

cURLの例: curl -v https://test.notr.app/

HTTPのステータスコード403が返り、Cloudflareのブロックされましたページが出ればOK。

次に、証明書をインストールした端末のWebブラウザやcURLcURLで設定したURLにアクセスし、接続できることを確認する。

cURLの例: curl -v --cert ./test.notr.app.pem --key ./test.notr.app.key https://test.notr.app/

おわりに

mTLSは証明書の作成や管理が面倒くさいと思っており、なかなか手が出せないでいたが、調べてみるとCloudflareの無料サービスだけを使って簡単に実装できることが分かり驚いた。

この方法で実装すると(当然ながら)Cloudflareのネットワークに該当サーバへの全トラフィックを吸われてしまうし、他者に依存している状況がちょっと悲しいのでそのうち気が向いたら自分のサーバ内で完結するようにしてみたいが、ひとまずはこれで動かして遊んでみようと思う。

ちなみに、iOSのショートカットアプリでは端末にインストールされた証明書を使ってくれない仕様のようで、自動化には利用できなそうな雰囲気だった。良い方法があれば教えてください。