組織内サーバーをCloudflare Accessで保護してみた話

Twilogの亡骸を抱きしめながらおひとり様Mastodonを立てる

こんにちは。日々是発見が楽しみな西山です。

とある事情があって、自分用のおひとり様Mastodonサーバーを構築しました。
とある事情とはTwitter社のAPI規約改定で、今まで自分のTwitterアカウントの全ツイートを「Twilog」というサービスで残していたのが取れなくなってしまいました(Twilog運営の方、長い間大変お世話になりました……)。
仕方なく「自分がツイートすると「IFTTT」でアクションが起動し、おひとり様MastodonにAPIで投稿する」という代替手段でツイートのログを取ることにしました。

このMastodonインスタンスはAPIの連携投稿を受け付け、ツイートのログをためていくだけで、手動投稿もしないし他のユーザーを作る事もありません。
完全なプライベートインスタンスなので、自分以外アクセスできないようにしたいなと思いました。

オーソドックスなBasic認証を使えば楽ですが、今回は勉強も兼ねて「Cloudflare Access」を使ったアクセス制御を組んでみました。
Basic認証には「APIアクセスする場合、ヘッダに復号化可能なパスワードが乗ってしまう」とか「ポップアップダイアログが出るとパスワードマネージャの自動入力が効かない場合がある」みたいな不満もありましたし……。

今回の記事は「Cloudflare Access」がテーマなので、Mastodonの構築やIFTTTによる連携については割愛します。
また前提条件として、独自ドメインを所有し、ネームサーバーがCloudflareを向いている必要があります。

Cloudflare Accessの設定

今回、「Cloudflare Access」には以下のルールを実装しました。

  • 通常のインターネットからは「登録済みのメールアドレスにワンタイムパスワードを送信し、正しければサイトにアクセス可能」
  • IFTTTのAPIからは「Cloudflare Accessの認証ヘッダを送信するよう設定し、APIリクエストを通す」
  • 自宅のIPアドレスからは①②の規則をバイパスしてアクセス可能

こういったルールは、例えば「企業の社員専用サーバーをVPN内ではなくインターネット上に置いてアクセス制御したい」みたいなケースでも参考になるかと思います。

1.アプリケーションの定義

アクセスポリシーを設定していくアプリケーション(≒Webサービス)を定義します。
Cloudflareのコントロールパネルから「Zero Trust」を開き、「Access」の下にある「Applications」に定義を作成します。
Zero Trustのコントロールパネルは日本語化されてないですが頑張ってください……。

最初にアプリケーションのタイプを選択します。今回は、自分で構築したサーバーに対してCloudflare Accessを設定するので「Self-hosted」を選択します。
ちなみに「SaaS」は他社提供のWebサービスに、「Private network」はローカルIPしか持たないイントラサーバーに対して利用するようです。

スクリーンショット 2023-05-10 110734
そしてアプリケーションの名前と、アクセスURL(DNS名)を設定します。
今回はMastodonサーバー用なので分かりやすく「mastodon」と名付けました。

6-2
この中にアクセスポリシーを設定していきます。

1-May-10-2023-01-57-02-5392-AM

2.認証ルールポリシー(ブラウザログイン)の作成

今回は、「ログインを試みると指定メールアドレスへのワンタイムパスワードを送信する」というルールを作成します。
他に、Google AuthenticatorのようなOTPデバイスを使うことも可能です。

「mastodon」というルールポリシーを作成し、「Action」は「Allow」、「Session Duration」は「Same as application session timeout」を指定します。
「Configure rules」の中のIncludeルールで「Selector」にEmail」を指定します。
そして、「Value」にワンタイムパスワードを受信するメールアドレスを記述していきます。

2-4
このルールポリシーが有効な状態で自分用Mastodonインスタンスにアクセスすると、Cloudflare Accessの認証画面にリダイレクトされます。
認証画面でメールアドレスを入力すると、そのアドレスに数字6桁のワンタイムパスワードが送信されますので、それを入力します。
ワンタイムパスワードが合っていれば、内側のサーバーにアクセス可能となります。

cfaccess-1

3.認証ルールポリシー(APIアクセス)の作成

もしこのサーバーに外部からAPIアクセスした時、上記のリダイレクトするポリシーが効いてしまうとAPIのリクエスト・レスポンスが失敗してしまいます。
それを回避するため、Cloudflareの認証トークンを作成し、リクエストヘッダに認証トークンを持っているアクセスを許可するルールポリシーを作成します。

「Access」の下にある「Service Auth」を開き、分かりやすい名前を入力してトークンを生成します(私は「mastodon」にしました)。トークンの有効期間は「Non-expireing(期限なし)」でいいでしょう。
「CF-Access-Client-Id」と「CF-Access-Client-Secret」が生成されますが、「CF-Access-Client-Secret」は画面を閉じると二度と表示されないため、エディタの画面等にコピーするのをお忘れなく。

6-2

トークンを作った上で、「Applications」に戻り、「mastodon-api」というルールポリシーを作成します。
「Selector」で「Service Token」を選択して、先ほど作成したトークンの名前「mastodon」を入力します。Cloudflare側の設定はこれで終わりです。

スクリーンショット 2023-05-03 235247-1

APIアクセスをする側の設定ですが、MastodonにAPIアクセスする「IFTTT」の設定画面はこんな感じです。
「Additional Headers」に先ほど作成した「CF-Access-Client-Id」と「CF-Access-Client-Secret」を記載し、これを付けてアクセスするように設定します。
これでIFTTTのAPIアクセスはCloudflareを通過し、内部のMastodonサーバーに到達できます。

4-2

4.自宅(作業場所)のIPをパスするルールの作成

最後に、自宅や会社オフィスのようにユーザーが多く、また信頼できる環境からは認証なしでアクセスできるバイパスのルールポリシーを作成します。
「mastodon-home」というルールポリシーを作成、「Action」は「Bypass」を選択し、Includeルールで「IP ranges」を選択してIPアドレスを入力します。
IPv6が有効な環境ではブラウザがそれを使ってアクセスする場合も多いので、プロバイダから割り当てられたIPv6の/64アドレスレンジも忘れず登録しておきましょう。

3-4

ゼロトラスト

以上の設定で、インターネット公開サーバーに対し、

  • 通常のインターネットからは「登録済みのメールアドレスにワンタイムパスワードを送信し、正しければサイトにアクセス可能」
  • IFTTTのAPIからは「Cloudflare Accessの認証ヘッダを送信するよう設定し、APIリクエストを通す」
  • 自宅のIPアドレスからは①②の規則をバイパスしてアクセス可能

という挙動が実装できました。
かっこよく言えばゼロトラストセキュリティを実現できたわけです。

また、Cloudflare Tunnelと組み合わせると「これまで社内ネットワークのみに公開していたサーバーをインターネットからアクセス可能にする」ことも、比較的簡単な設定で出来ます。
もちろん、サーバー自体のセキュリティに問題がないかは十分検討が必要ですが「新しいシステムを作らずにスタッフの利便性を高める」ことが可能なので、こういった課題にお悩みの方は一度検討してみてはいかがでしょうか……!