💂

.onion ドメインでも Cloudflare Turnstile が使える

2024/12/15に公開

本記事は Cloudflare Advent Calender 2024 の 15 日目の記事です。

https://qiita.com/advent-calendar/2024/cloudflare

要約

  • Cloudflare Turnstile は実は所有していないドメインでも使える
    • なので .onion ドメインでも使える

Cloudflare Turnstile とは

Cloudflare Turnstile は Cloudflare の提供する CAPTCHA サービスで、他の CPATCHA と比較すると「パズルを解く必要がない」ことが大きな特徴です。

https://developers.cloudflare.com/turnstile/

詳しい解説は公式ドキュメントや他の記事に譲ります。

.onion ドメインとは

.onion ドメインは一般的なドメインと異なり、普通のブラウザからではアクセスできず、Tor を経由しないとアクセスできない特殊なドメインです。

https://ja.wikipedia.org/wiki/Onionドメインの一覧

.onion ドメインはレジストラで管理されているわけではなく、各自で鍵ペアから生成することになります。ドメイン生成ツールとして cathugger/mkp224o があります。

https://github.com/cathugger/mkp224o

このことから、.onion ドメインでを Cloudflare で管理したりということはできません。

しかし、Turnstile に関しては 自分の所有していないドメインに関してもキーを発行することができる ため、.onion ドメインだろうが関係なく使うことができます。今回の記事では実際に .onion ドメインのシンプルな Web サイトを作成し、 Turnstile の検証を行います。

成果物

記事中のコードは以下のリポジトリで公開されています。

https://github.com/p1atdev/turnstile-on-onion

作ってみる

Cloudflare アカウントは必要になりますが、所有しているドメインがなくても大丈夫だと思います。また、.onion ドメインでの確認用にTor ブラウザが必要になります。

以下の流れになります:

  1. .onion ドメイン生成
  2. Turnstile のサイトキーを取得
  3. Web ページを作成
  4. 公開

今回は Docker Compose を使ってお手軽に公開まで行います。

.onion ドメイン生成

成果物 のレポではドメイン生成用のスクリプトを用意しているので、それを実行するだけで一つドメインが取れます。使っている PC の性能にもよりますが、デフォルト設定なら 10 秒もかからないかと思います。好きな文字をドメインの先頭に付ける (デフォルトは neko) こともできますが、カスタマイズ方法は mkp224o のレポ を参照してください。

所有権の都合で sudo が必要です.

sudo bash ./scripts/get_domain.sh
get_domain.sh 中身
./scripts/get_domain.sh
#!/bin/bash

# https://github.com/cathugger/mkp224o
docker run \
  --platform linux/amd64 \
  --rm \
  -it \
  -v $PWD/keys:/keys ghcr.io/cathugger/mkp224o:master \
  -d /keys \
  -n 1 \
  neko 
# ↑ これが先頭の文字列

# Find the first directory that matches the pattern
first_dir=$(find ./keys -type d -name "*.onion" | head -n 1)

# Check if the directory exists
if [ -d "$first_dir" ]; then
  # Move all files from the first directory to the current directory
  mv "$first_dir"/* ./tor/hidden_service
  rm -r "$first_dir"
else
  echo "No directory found matching the pattern."
fi

chmod -R 775 ./tor/hidden_service

実行すると、 ./tor/hidden_service 内に

  • hostname: ドメイン名が中に書かれている
  • hs_ed25519_secret_key: ドメインの秘密鍵。絶対公開しないように
  • hs_ed25519_public_key: ドメインの公開鍵

が作成されます。hostname に書かれているドメイン名で Web サイトが公開されることになります。

Turnstile のサイトキーを取得

Cloudflare ダッシュボードにアクセスして Turnstile のキーを取得しましょう。多分左側にあるサイドバーの中に Turnstile の項目があります。


サイドバーにTurnstileがいる

「ウィジェットを追加」ボタンをおすとウィジェットを追加する画面になるので、「ホスト名を追加」から生成した .onion ドメインを追加します。


ドメインの追加画面


選択して追加する

今回はウィジェットモードを「管理対象」にします。管理対象にすることで、Turnstile のウィジェットを表示し、ユーザーにチェックボックスのクリックを求める形になります。

作成すると、次のようにサイトキーが表示されますが、サイトキーのみを後で使います。今回はシークレットキーは使いません。

これで Cloudflare 側の設定は終わりです。

Web ページを作成

今回は HTML 一枚の非常にシンプルなサイトにします。

./web/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Turnstile on Onion</title>
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>
</head>
<body>
    <main>
        <h1>Hello, World!</h1>
        <div id="turnstile" />
    </main>

    <script>
        turnstile.ready(function () {
            console.debug("Turnstile ready");
            turnstile.render("#turnstile", {
                // sitekey は取得したものに置き換える
                // (1x00000000000000000000AA はどこでも常に成功するキー)
                sitekey: "1x00000000000000000000AA", 
                callback: function (token) {
                    console.log(`Challenge Success ${token}`);
                },
            });
        });
    </script>
</body>
</html>

Hellow, World のテキストの下に Turnstile のウィジェットが表示されるようになっています。sitekey には取得したサイトキーを入れてください。

Web サイト側はこれだけです。

公開

さて、公開ですが、Tor 向けの公開は少し設定が必要です。今回は Docker を用いて簡単に公開します。

compose.yml は以下のようになります。

./compose.yml
services:
  # tor 用
  tor:
    build:
      context: .
  
  web: # ページ公開用
    image: httpd:2.4
    volumes:
      - type: bind
        source: ./web/
        target: /usr/local/apache2/htdocs/
    ports:
      - "8888:80" # 8888 で一般ネットワークでの確認用

tor 向けのサービスとして tor を作成、Web サーバとして httpd のイメージを用いています。tor で使う Dockerfile は以下のようになっています。

./Dockefile
FROM debian:trixie-slim

# Setting up Tor
RUN apt update
RUN apt install -y tor
COPY ./tor/torrc /etc/tor/torrc
COPY ./tor/hidden_service /app/tor/hidden_service

RUN chmod 700 /app/tor/hidden_service

CMD tor

debian のイメージで tor をインストールし、Tor の設定をしています。torrc は以下のようになっています。

./tor/torrc
HiddenServiceDir /app/tor/hidden_service/
HiddenServicePort 80 web:80

compose.yml のサービス web のポート番号 80 番を Tor の Hidden Service の 80 番ポートに転送しています。要は Tor 向けのポートフォーワーディングです。

tor では設定ファイルの権限も重要になるので、chmod で適切な権限を与えています。

これで準備が整いました。docker compose up で起動し、.onion ドメインにアクセスしてみましょう。

docker compose up
  • 一般ネットワークでの確認: http://localhost:8888
  • .onion ドメイン: hostname に書かれているドメイン名 (例: neko7t77s2jk4fuqpjhvt2rfyxs3nx4hqhkedioelc77hlmw3rxi4fqd.onion)

.onion ドメインでは https:// ではなく http:// であることに注意してください。(Tor な時点ですでに暗号化されているため HTTP でも問題がありません)

アクセスすると以下のようになります:

奥のブラウザが通常の Firefox でアクセスした localhost:8888、手間のブラウザが Tor ブラウザでアクセスした .onion ドメインになっています。普通のブラウザでは「ドメインが無効」と言われていますが、Tor ブラウザでアクセスした方では認証に成功しているのがわかります。(Tor ブラウザで Web ページの外側に変な空白ができることがありますが、Tor ブラウザの仕様です。)

実際の認証の様子は以下のようになります:


検証される様子。検証されるとトークンがログに出る。

GIF ではカットしているのですぐチェックが通っているように見えますが、実際は検証に 20 秒前後かかります。

まとめ

今回の記事では Cloudflare Turnstile を .onion ドメインのサイトで使ってみました。

同様の CAPTCHA サービスとして Google の reCAPTCHA も .onion ドメインで利用可能ですが、reCAPTCHA は個人的な経験として、 Tor 経由だと無駄にパズルを大量に解かないといけないことが多い上、正しいものを選んでも全然検証が通らないこともあるので、Cloudflare Turnstile を使うことで Tor 経由でもユーザー体験を確保できる、というのは覚えておくと今後どこかで役に立つ機会があるかもしれません。

身近な例を挙げるとするとすれば、Misskey を Tor 上でホスティングしたい場合は Bot プロテクション機能で Turnstile を選択できるので、その際に使うことができます。

記事中のコードは以下のレポで公開しているので、再現したい場合などにご利用ください。

https://github.com/p1atdev/turnstile-on-onion

関連情報

GitHubで編集を提案

Discussion