Torからのアクセスをnginxでブロックする

はじめに

Torは、プライバシー保護という観点で自身は決して悪いものだとは思っていません。サービスを運用する上で個人の特定ができない事で起こりうる問題の予防のためにこのような対応の選択をせざるを得ないというだけで、Torそのものを否定したいわけではない事だけ始めに書いておきます。

本題

Torは、ざっくり言うと複数のサーバーを経由することで秘匿性を実現しています。一番最後に経由したノードからインターネットに接続し、接続先へ通信します。一番最後に経由したノードはTor出口ノードと呼ばれています。接続先のサーバーのログに残るIPアドレスはこの出口ノードのIPアドレスであるので、現在出口ノードになっているサーバーのIPアドレスさえ分かればそれらをnginxでブロックするのは容易です。

Torの出口ノードはtorprojectで管理されているので、このエンドポイントをcurlで叩いてIPを取得、nginxのdenyディレクティブにIPを追加するようなファイルを動的に生成するスクリプトをcronで定期的に実行させれば、出口ノードに変動があったとしてもなるべくリアルタイムに更新させることができます。

以下で、動的にIPを取得し、block_tor_ip.confに追加、nginxをリロードさせます。

#!/bin/bash

result=`curl -s https://check.torproject.org/torbulkexitlist?ip=1.1.1.1`

if [ $? -ne 0 ]; then
    echo "Cannot get address."
    exit 1
fi

echo "${result}" | sed '/^#/ !s/^/deny  /g; s/$/;/g' >> block_tor_ip.conf

nginx -t
nginx -s reload

ファイルは以下のように生成され、/etc/nginx/conf.d/*.confはデフォルトでincludeされるので、リロードされれば適用されます。 実際は、数百行ありますが、長いので割愛してます。

$ head conf.d/block_tor_ip.conf
deny  54.37.16.241;
deny  46.182.106.190;
deny  109.70.100.32;
deny  51.15.43.205;
deny  51.75.64.23;
deny  185.205.210.245;
deny  94.32.66.48;
deny  82.221.128.191;
deny  109.70.100.35;

検証

AWSインスタンスを立てて、試しに上記のスクリプトを動作させTorからアクセスしてみます。 nginxをstartさせると、デフォルト画面がレンダリングされます。

f:id:keisuke_t:20200817185940p:plain
nginx_default

スクリプトを発火させ、denyのIPが追加されているnginxを起動します。

Tor起動し、アクセスすると

f:id:keisuke_t:20200817190055p:plain
tor

403を返し、ブロックされました。

f:id:keisuke_t:20200817190250p:plain
block_nginx

最後に

本番環境で運用するならば、locationディレクティブを使って特定のURLの時だけ(例えば、決済画面とかユーザーの問合せ画面とか)denyを適用させるとかもありかなと思いました。