以前、こんな記事を書きました。
👉 Cloud RunとSupabaseで低コスト運用しようと思ったら無理だった話。
Cloud Run × Supabase という組み合わせを前提に検討していたが、実際に詰めていくとCloud Run以外のインフラも必要になり、低コストを実現できませんでした。そこで次に試したのが Cloudflare Workers × Supabase という構成です。
Workers は
- とにかく安い
- サーバー管理も不要
- スケールも自動
「これでいいじゃないか」と思えます。
しかし実際に構築してみると、セキュリティの都合上相性が悪いと感じました。
結論を書くと「Workersは固定IPを持たないのでSupabase側でIP制限をかけられないから」です。
この記事では
- なぜ相性が悪いか
- 解決策はないのか
- 代替となる選択肢
について解説していきます。
この記事は私がSupabaseを使用しようとしたため、Supabaseについて言及した記事となっています。ただしこの内容はCloudflare Workersと他のDBaaSを使う場合にも言えます。またCloudflare Workers、Supabaseが悪いという話ではなく、相性の問題です。
前提知識
Cloudflare Workersは固定IPアドレスをもたない
Cloudflare Workersは、世界中のエッジロケーションで実行される分散型のランタイムです。リクエストが来た場所に最も近いデータセンターでコードが実行されます。
この特性上、Workersは固定IPアドレスをもたないです。
正確にはWorkersは固定のIPアドレスはもたないが、完全にランダムというわけではなく、Cloudflareが公開しているIP範囲内から送信されます。
cloudflaredを活用した接続についてはQAセクションで触れています。結論を書くとSupabaseではcloudflaredをDB側にインストールすることが出来ないので、使うことが出来ません。
Supabaseからのデータ取得はDirect ConnectionまたはSession Poolerを活用した接続を行う
この記事ではSupabaseからのデータ取得はData APIを使わずにDirect ConnectionまたはSession Poolerを活用した接続を利用します。
Direct ConnectionとSession Poolerを利用した接続の違いについてはドキュメントに書いてあります。細かな違いはありますが、Data APIと対比したときのメリットについては同じと考えることが出来るため、以降ではDirect Connectionと表記します。
Direct ConnectionはSupabaseのData APIを使用せずに直接Postgressと接続することを指しています。Workersと接続するときは間にHyperdriveを使用しています。ただこれは接続を安定して確立するための仕組みと認識しており、相性が悪いと結論付けた要因とは関係ないため、以降では触れません。
その理由についてはSupabaseからサーバーサイドでデータを取得するなら、Supabase SDKを使うべきでない3つの理由で述べています。
簡単にいうとまとめると
- 好きなORMを使うことが出来て柔軟性に優れている
- パフォーマンスに優れている
という理由です。
Supabase SDKは接続が簡単であったりしてトレードオフが存在するのは事実です。なのでこの記事では私が上の理由からDirect Connectionをして使用すると判断した前提のものとして読んでいただきたいです。
Direct ConnectionにはIPアドレス制限を設けることが出来る
Direct ConnectionにはIPアドレス制限を設けることが出来ます。
その方法についてはこちらにかいてあります。
なぜ相性が悪いのか
Cloudflare Workersが固定IPをもたないのと、SupabaseにIPでの制限が相性が悪い
前提知識を読んでお気づきかもしれませんが、固定IPをもたないとIPアドレスで制限をかけることができません。
IPアドレス制限なしでの運用は可能か?
結論として、避けるべきと考えています。理由は攻撃(と呼ぶにはあまりに簡単すぎる)に対して無防備になり、解決策がないことです。以降で詳しく解説していきます。
Password以外の接続情報は容易に推測できる
SupabaseをDBとして利用する人は、一般的にSupabase Authを使う人が多いと思います。Supabase Authを使うにはフロントエンドから直接SupabaseのURLにアクセスすることになり、そこにproject idが含まれています。
そしてSupabaseのDirect Connectionのconnection stringは
という形で統一されています。つまりpassword以外の接続情報は容易に推測できるということです。
接続情報を利用して、サーバーに負荷をかけられる
十分に安全なパスワードを設定すれば、安全であるとお考えかもしれません。たしかにデータの流出という観点でみるとそうかもしれません。(それでも避けるべきと思います)
しかしサービスの安定した運営を考えたときに避けるべきです。パスワード以外の接続情報がわかるということはサーバー自体には到達可能ということです。
これによってコネクションを枯渇させたりなどの攻撃をすることができます。データは流出しなくても、運営に支障が出る可能性があります。
攻撃されたときに回避策がない
最大の問題は攻撃されたときに対処方法がないということです。サービスを止めて、大規模な改修を行ってインフラを移動させることになるでしょう。また代替案が存在します。それなら初めから避けておくのが無難です。
解決策
Cloudflare Workers×Cloudflare D1を使う
特徴
- SQlite
- とにかく安く始められる
- 単一のDBあたり10GBの制限
固定IPをもつサーバー×Supabaseを使う
特徴
- Postgres
- サーバー費用がかかる
Cloudflare Workers×Cloudflare D1を使うのが無難かなと思っています。無料で始められて、個人開発だとSqliteや10GBの制限に到達するに至るのは極少数だと思います。
よくある質問
Q: 安全に接続する選択肢は本当にないのか?
A: Cloudflareは privateな接続の選択肢としてCloudflare Tunnelという仕組みを用意しています。しかしこれらはcloudflaredをDB側のネットワークでインストールする必要があり、Supabaseはフルマネージドサービスなのでインストールをすることが出来ません。Neon,Cockroach DB、TursoなどはAWSやGCPを使ってセキュアに接続する方法を用意していて、それで行うことはできます。ただcloudflaredをインストールするためにEC2やGCEをDBの前に置く必要があり、運用面でも金銭的にも余計なコストになります。それよりは上で示した選択肢のほうが良いというのが私の考えです。
Q: CloudflareのIP範囲からのアクセスに制限したらどうか?
A: これによってなにも設定しない場合より攻撃範囲を限定出来ます。しかし自分のWorkerと他人のWorkerは区別することが出来ないため、Cloudflare Workersを踏み台にした攻撃に対して無防備です。
Q: 固定IPをもつサーバーの選択肢は?
A: Fly.ioが有力な選択肢のひとつです。RenderもDBをSupabaseをやめてRenderに統一するなら良い選択肢です。これについても詳しくまとめた記事を書く予定です。