Cloudflareの無料機能を使ってmTLSを試す
Cloudflareの無料機能を使って自宅のWebサーバをインターネットに公開しつつ、証明書をインストールした特定の端末からのみアクセスできるようにmTLSを設定してみたメモ
背景
ファイルサーバや家電のコントローラーなど、自宅の装置にインターネットからアクセスする方法を考えたとき、今までは以下のような方法を使っていた。
- VPNやZTNAを使う (L2/L3)
- SSHの公開鍵認証を通した後にポートフォワード (L7 + L3L4)
- パスワード, パスキー認証をする (L7)
しかし、どの方法も少しずつ面倒くさポイントがあり、たびたびちょっとしたストレスを感じていた。
そこで、今回はmTLS(mutual-TLS, 相互TLS)認証を利用して、証明書をインストールした特定の端末のみからアクセスできるようにすることでセキュリティを担保しながら、自宅の機器へインターネット経由HTTPSアクセスできるようにしてみた。
構成
今回はCloudflareの無料機能を組み合わせて構築していく。
-
Client certificates: https://developers.cloudflare.com/ssl/client-certificates/
- mTLS認証をするために利用
-
Cloudflare Web Application Firewall: https://developers.cloudflare.com/waf/
- mTLS認証が通っていないアクセスをブロックするために利用
- 試していないが、 API Shield で強制することもできそう
-
Cloudflare Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
- インターネットへサーバを公開するために利用 (ZTNA)
- 自宅側のファイアウォールでCloudflareのIPアドレスレンジのみを許可してサーバをインターネットに公開しても良い
手順
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を利用するホスト名を設定する。
WAFルールの作成
今回は上記画面のCreate mTLS Ruleボタンをクリックし、テンプレートを使ってmTLS認証が通っていないアクセスをブロックするWAFルールを作成する。
例として下記の画面では、
mTLS認証が成功していない かつ ホスト名が test.notr.app
の場合に アクセスを拒否する(Block)ルールを作成している
Cloudflare Tunnelを利用したサーバの公開
Cloudflare Zero Trustのダッシュボードで Networks -> Tunnels -> Create a tunnel の順に進み、cloudflared で案内に従いトンネルを作成する。
Route Traffic画面で、公開したいホスト名とアクセス先のスキーマ、URLを指定する。
テスト
証明書をインストールしていない端末の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のショートカットアプリでは端末にインストールされた証明書を使ってくれない仕様のようで、自動化には利用できなそうな雰囲気だった。良い方法があれば教えてください。