2026年8月28日

2026年8月28日

WordPressでTorからのアクセスをブロックする方法|Cloudflare・ipset・ログイン画面だけの制限

Tor(The Onion Router)は、通信を複数の中継サーバーに通して接続元を隠すネットワークです。Webサイトから見ると、Tor の利用者は「出口ノード」と呼ばれる中継サーバーのIPアドレスから接続してきます。出口ノードのIPアドレスは Tor Project が一覧で公開しているため、それを使ってアクセスを止められます。

ただし、Tor は報道や人権活動、検閲のある国からの閲覧、プライバシーを重視する人にも使われています。サイト全体を止めるとそうした読者も締め出すため、ログイン画面やコメント投稿だけを止めることも検討してください。この記事では次の3つの方法を説明します(2026年10月時点)。

方法 向いている環境 止める範囲
Cloudflare のカスタムルール Cloudflare を通して配信しているサイト サイト全体、または特定のURLだけ
ipset と iptables root で操作できる VPS・専用サーバー 80/443 番ポートへの接続すべて
mu-plugin 共用サーバーなど、サーバーの設定を変えられない環境 ログイン画面とコメント投稿

出口ノードの一覧

Tor Project は、出口ノードのIPアドレスを次のURLで公開しています。

  • https://check.torproject.org/torbulkexitlist:1行に1つの IPv4 アドレスだけが並んだ一覧。2026年10月時点で約1,200件
  • https://check.torproject.org/exit-addresses:ノードの識別子や確認日時も含む詳しい形式
curl -fsS https://check.torproject.org/torbulkexitlist | head -n 3

出口ノードは入れ替わるため、一覧は定期的に取り直します。一度取り込んだだけでは、時間がたつと止められないIPアドレスが増えていきます。

方法1:Cloudflareのカスタムルールで止める

Cloudflare は、Tor の出口ノードからのアクセスを、国コード T1 として扱います。WAF のカスタムルールで、次の式を指定します。

(ip.src.country eq "T1")

ログイン画面と XML-RPC だけを対象にする場合は、URLのパスを組み合わせます。

(ip.src.country eq "T1" and (http.request.uri.path eq "/wp-login.php" or http.request.uri.path eq "/xmlrpc.php"))

アクションは、すぐに拒否する「Block」か、ブラウザーの確認を挟む「Managed Challenge」を選びます。Tor の利用者にも閲覧は許したい場合は、サイト全体には Managed Challenge、ログイン画面には Block、と分ける方法もあります。

Cloudflare を通している場合、オリジンのサーバーには Cloudflare のIPアドレスから接続されるため、次の方法2はそのままでは効きません。Cloudflare の設定全般はWordPress に Cloudflare を設定する手順を参照してください。

方法2:ipsetとiptablesでサーバーごと止める

VPS などで root 権限がある場合は、出口ノードの一覧を ipset(IPアドレスの集合を高速に照合する仕組み)に入れ、iptables で Web への接続を捨てます。数千件の IPアドレスでも、1件ずつルールを書くより軽く動きます。

準備

# Ubuntu / Debian
sudo apt install ipset iptables curl
# RHEL 系(AlmaLinux・Rocky Linux など)
sudo dnf install ipset iptables curl

一覧を取り込むスクリプト

/usr/local/sbin/tor-exit-block.sh として保存します。新しい集合に読み込んでから入れ替えるため、更新中に遮断が外れることはありません。

#!/bin/bash
# Tor の出口ノード一覧を取得し、ipset の tor-exit に入れ替える
set -euo pipefail

URL="https://check.torproject.org/torbulkexitlist"
TMP="$(mktemp)"
trap 'rm -f "$TMP"' EXIT

curl -fsS --max-time 30 "$URL" -o "$TMP"

# 取得結果が極端に少ないときは、一覧が壊れているとみなして何もしない
COUNT="$(grep -cE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' "$TMP" || true)"
if [ "$COUNT" -lt 100 ]; then
  echo "exit list looks wrong ($COUNT lines), skipped" >&2
  exit 1
fi

ipset create tor-exit hash:ip -exist
ipset create tor-exit-new hash:ip -exist
ipset flush tor-exit-new
grep -E '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' "$TMP" | sed 's/^/add tor-exit-new /' | ipset restore -exist
ipset swap tor-exit-new tor-exit
ipset destroy tor-exit-new

# 80/443 番ポートへの Tor からの接続を捨てるルール(無ければ追加)
RULE=(INPUT -p tcp -m multiport --dports 80,443 -m set --match-set tor-exit src -j DROP)
iptables -C "${RULE[@]}" 2>/dev/null || iptables -I "${RULE[@]}"
sudo chmod 700 /usr/local/sbin/tor-exit-block.sh
sudo /usr/local/sbin/tor-exit-block.sh
sudo ipset list tor-exit | grep 'Number of entries'
sudo iptables -S INPUT | grep tor-exit

Number of entries に件数が出て、--match-set tor-exit src -j DROP のルールが表示されれば有効になっています。スクリプトは何度実行しても、ルールが重複して増えることはありません。

定期的に更新する

ipset の内容と iptables のルールは、再起動すると消えます。root の crontab(sudo crontab -e)に、1時間ごとの更新と、起動時の実行を登録します。

15 * * * * /usr/local/sbin/tor-exit-block.sh >/dev/null 2>&1
@reboot sleep 60 && /usr/local/sbin/tor-exit-block.sh >/dev/null 2>&1

注意点

  • ufw や firewalld などのファイアウォール管理ツールを使っている場合、ツールが設定を作り直すとこのルールが消えることがあります。次の cron の実行で追加し直されますが、ツールの設定を変えた後は iptables -S INPUT で確かめます
  • 自分の管理用の接続(SSH)は止めないよう、ポートを 80/443 に限っています
  • 特定のIPアドレスを止める一般的な方法はWordPressで特定のIPアドレスをブロックする方法でも説明しています

方法3:ログイン画面とコメント投稿だけを拒否する(mu-plugin)

サーバーの設定を変えられない共用サーバーでも使える方法です。WordPress が出口ノードの一覧を取得して1時間キャッシュし、Tor からのログイン画面の表示とコメントの投稿を 403 で拒否します。閲覧はそのままできます。

wp-content/mu-plugins/tor-exit-block.php として保存します(mu-plugins フォルダーが無ければ作ります)。mu-plugin は有効化の操作が不要で、置くだけで動きます。

<?php
/**
 * Plugin Name: Tor Exit Block (login and comments)
 * Description: Tor の出口ノードからのログインとコメント投稿を拒否する。
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Tor Project が公開する出口ノードの一覧を取得し、1時間キャッシュする。
 *
 * @return array<string, bool> IPアドレスをキーにした配列
 */
function lsc_tor_exit_list() {
	$list = get_transient( 'lsc_tor_exit_list' );
	if ( is_array( $list ) ) {
		return $list;
	}

	$response = wp_remote_get( 'https://check.torproject.org/torbulkexitlist', array( 'timeout' => 10 ) );
	if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
		// 取得に失敗したら5分間は再取得しない(毎回の通信でページが遅くならないように)。
		set_transient( 'lsc_tor_exit_list', array(), 5 * MINUTE_IN_SECONDS );
		return array();
	}

	$list  = array();
	$lines = preg_split( '/\R/', trim( wp_remote_retrieve_body( $response ) ) );
	foreach ( $lines as $line ) {
		$ip = trim( $line );
		if ( false !== filter_var( $ip, FILTER_VALIDATE_IP ) ) {
			$list[ $ip ] = true;
		}
	}

	set_transient( 'lsc_tor_exit_list', $list, HOUR_IN_SECONDS );
	return $list;
}

/**
 * 接続元が Tor の出口ノードかどうか。
 */
function lsc_is_tor_exit() {
	$ip = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
	if ( '' === $ip ) {
		return false;
	}
	$list = lsc_tor_exit_list();
	return isset( $list[ $ip ] );
}

// ログイン画面(wp-login.php)
add_action(
	'login_init',
	function () {
		if ( lsc_is_tor_exit() ) {
			wp_die( 'このページは Tor ネットワークからは利用できません。', 'Forbidden', array( 'response' => 403 ) );
		}
	}
);

// コメントの投稿(wp-comments-post.php)
add_action(
	'pre_comment_on_post',
	function () {
		if ( lsc_is_tor_exit() ) {
			wp_die( 'Tor ネットワークからはコメントを投稿できません。', 'Forbidden', array( 'response' => 403 ) );
		}
	}
);
  • login_init は wp-login.php が処理を始めるときに、pre_comment_on_post はコメントが保存される前に実行されるフックです
  • 一覧の取得に失敗したときは何も止めず、5分後に取り直します
  • $_SERVER['REMOTE_ADDR'] を見ているため、Cloudflare などのプロキシの後ろでは、Webサーバー側で本当の接続元のIPアドレスに置き換える設定(Apache の mod_remoteip、Nginx の real_ip モジュール)が必要です。置き換えていないと一致せず、何も止まりません
  • XML-RPC(xmlrpc.php)や REST API 経由のログインは対象外です。XML-RPC を使っていなければxmlrpc.php を無効化する方法で止めます

止められているか確かめる

Tor Browser でサイトを開き、設定したとおりに拒否されること(方法1は Cloudflare のブロック画面かチャレンジ、方法2は接続できない、方法3はログイン画面で 403)を確かめます。Cloudflare では、セキュリティのイベント画面でルールに一致したアクセスを確認できます。

まとめ

  • Tor の出口ノードは Tor Project が torbulkexitlist で公開しており、入れ替わるため定期的に取り直す
  • Cloudflare を通しているなら、カスタムルールの ip.src.country eq "T1" が手軽
  • root がある VPS では、ipset に一覧を入れて iptables で 80/443 番ポートを止め、cron で更新する
  • 共用サーバーでは、mu-plugin でログイン画面とコメント投稿だけを拒否できる
  • Tor には正当な利用者もいるため、止める範囲はログインや投稿に絞ることも検討する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲