今日はCloudflare Workers を使用して、TORネットワークのIP(リレーとブリッジ)を無料でブロックする方法を学びます。

本題に入る前に、Cloudflareが最近Managed Lists を導入し、ワンクリックでTORをブロックできるようになったことをお知らせします。唯一の欠点は、これらがEnterpriseのお客様のみに提供されていることです。

余裕があれば素晴らしいです。この投稿は無視してください。しかし、Enterpriseプランを購入できない場合は、読み続けてください。

TORネットワークのブロック

最初に、cronジョブとしてのみ使用されるworkerを作成しました。TOR IPを取得し、解析してCloudflare Listsに保存します。このリストはFirewall Rulesで任意のウェブサイトで使用されます。

Lists機能の主な問題は、すべてのリストで10,000項目に制限されていることでした。BusinessまたはEnterpriseプランであっても、ここ に記載されている通り、これが現在の制限です。

もう一つの問題は、ここ に記載されている通り、現在個別のIPv6アドレスを保存できないことでした。

これら2つの大きな問題により、リストの使用は実行可能なオプションではありませんでした。そこで代わりにWorkers KVに移行しました。多くのテストとCloudflareのDiscordチャンネルでの複数の人との議論の後、これらのTOR IPを保存してクエリする最良の方法を見つけました。

「スマート」なアプローチを使用して、すべてのTOR IPに対して1つのエントリ(key:value)のみを保存しています。これによりコストを大幅に削減できます。

これが機能するのは、Workers KVの値の制限が25 Mbであるのに対し、保存する多くのIPはわずか数Kbしか使用しないためです。

Workers KV 無料プランの制限は、これらのIPを常に読み書きするのに十分すぎるほどです。そして十分でない場合、worker内でキャッシュを適用できます(READに10分のキャッシュを既に適用しています)。また、プランはわずか5$/月でアップグレードできます。

もちろん、使用方法を工夫して、保護したい特定のエリア(ログインエリアなど)でのみユーザーIPをチェックすることもできます。

サービスワーカー

Github にすぐに使えるworkerを用意しました。

クローンして、要件を設定して公開するだけです。

設定

これを動作させるには、いくつかのものが必要です:

  • Wrangler
  • アカウントID
  • 1つのKV Namespace

アカウントIDを取得するには、Cloudflareでウェブサイトのいずれかを開き、「Overview」ページの右下を確認します。アカウントIDを取得したら、wrangler.tomlに保存します:

1account_id = "..."

Worker KV Namespaceを作成するには、次のコマンドを実行します:

sudo wrangler kv:namespace create storage

結果は次のようになります:

1🌀 Creating namespace with title "cloudflare-block-tor-worker-storage"
2✨ Success!
3Add the following to your configuration file:
4kv_namespaces = [
5{ binding = "storage", id = "cc309bd612d9476f8abdc43ec4f93fd6" }
6]

上記のIDを使用して、wrangler.tomlを編集しIDを保存します:

1[[kv_namespaces]]
2binding = "TOR_COMBINED_LIST"
3id = "cc309bd612d9476f8abdc43ec4f93fd6"

KV Namespaceを自分で作成しないでください。上記のコマンドを使用してください。KV Bindingは必須です。無視しないでください。

上記の手順が完了したら、workerを公開します:

sudo wrangler publish

workerは60分(1時間)ごとに実行するように設定されています。変更したい場合はwrangler.tomlを編集してください。APIは1時間ごとにしか更新されないため、短い間隔は役に立ちません。

リストの使用

これでTORネットワークIPのリストがあり、使用する時です。workersに既に慣れていれば非常に簡単ですし、慣れていなくても簡単です。

アイデアは、受信するユーザーIPをリストと照合し、一致があればリクエストをブロックすることです。以下は新しいworkerにコピー&ペーストできるシンプルなスターターscriptです:

 1const clientIP = request.headers.get('CF-Connecting-IP');
 2const ipset = await TOR_COMBINED_LIST.get("ipset", { type: "json", cacheTtl: 600 });
 3
 4if (ipset[clientIP])
 5{
 6return new Response("TOR is Forbidden", {
 7headers: {
 8'content-type': 'text/html;charset=UTF-8',
 9},
10status: 403
11});
12}

IPのリストは1つのオブジェクトとして保存されているため、ルックアップは非常に高速で、何も解析や検索する必要がありません。

キャッシュも適用されています(無効にすることもできます)。Workers KVキャッシュはCache API を使用して動作します。

値を取得したら、IPが存在するかチェックし、存在する場合は好きなものを返します。

上記のスニペットを新しいまたは既存のworker(さらにはCloudflare Pages)内のどこでも使用できます。requestオブジェクトが利用可能であれば問題ありません。

リストのテスト

前述の通り、Workersを使用したことがなくても、このリストの使用は非常に簡単です。

どのウェブサイトでもコピー&ペーストして使用できる小さな例を作成しました:

 1addEventListener("fetch", event => {
 2event.respondWith(handleRequest(event.request))
 3})
 4
 5const html = `<!doctype html>
 6
 7<html lang="en">
 8  <head>
 9    <title>Access Denied</title>
10    <meta charset="utf-8">
11    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
12    <meta name="robots" content="noindex, nofollow" />
13    <meta name="viewport" content="width=device-width, initial-scale=1">
14    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> 
15  </head>
16  <body>
17    <div class="container">
18      <h1 class="mt-5 text-center">Oops!</h1>
19      <h2 class="mt-2 text-center text-danger">TOR Network is not allowed.</h2>
20    </div>
21  </body>
22</html>`;
23
24async function handleRequest(request)
25{
26const clientIP = request.headers.get('CF-Connecting-IP');
27const ipset = await TOR_COMBINED_LIST.get("ipset", { type: "json", cacheTtl: 600 });
28
29if (ipset[clientIP])
30{
31return new Response(html, {
32headers: {
33'content-type': 'text/html;charset=UTF-8',
34},
35status: 403
36});
37}
38
39const response = await fetch(request);
40
41return response;
42}

このworkerにKV Bindingを追加することを忘れないでください。

上記のworkerをデプロイした状態で、TORブラウザ を起動してテストします:

Block TOR Result

ご覧の通り、期待通りに動作しています。TORネットワークIPがブロックされ、リレーとブリッジの両方が対象です。

自分のウェブサイトからこれを削除したことに注意してください。TOR経由でアクセスしても動作します(TORをブロックする理由がないためです)。

コストの計算

この投稿の冒頭で、無料のWorker制限はTORをブロックするのに十分であると述べました。実際その通りです。また、このプロジェクトの最良の方法を見つけるために多くのテストを行ったことも述べました。

テスト中、多くのREAD/WRITE/LIST/DELETEリクエストを使用し、結果的に月額約60-100$のコストがかかりました。理想的ではありませんよね?😳

そこで、1時間に1回だけWRITEを行う方法を見つけました。これは1日24回のWRITE、1ヶ月(31日)で744回のWRITEを意味します。

これはWorkers KVの無料枠内に収まり、TORをブロックできます。

便利なリンク

  • Wranglerを始めるには:https://developers.cloudflare.com/workers/wrangler/get-started/
  • Workersを始めるには:https://developers.cloudflare.com/workers/get-started/quickstarts/
  • KV Bindingsを設定するには:https://developers.cloudflare.com/workers/runtime-apis/kv/#kv-bindings

以上です。この記事とツールがお役に立てば幸いです。

ご意見をお聞かせください!