WordPressでRSSやコメントページをVPN・PROXY・TORから取得できないようにする方法

WordPressでRSSやコメントページをVPN・PROXY・TORから取得できないようにする方法
WordPressでRSSやコメントページをVPN・PROXY・TORから取得できないようにする方法

 

 
読了目安:541

Are you want to translate this page to English? Please click this link to translate via ‘©Google Translate'!

ganohr.net favicon

みなさんこんにちは、ガノー(Twitter:Ganohr)です。

最近当サイトのアクセスが増加しており、全世界に数億あると言われるウェブサイトの中で、1万位以内のアクセス数を誇るようになりました。

 

そうなってくると増えてくるのが、数多くのコピーサイト

スプログ・スパムサイトの運営やブラックハットSEO等を目的として、他人のサイトのコンテンツを盗用し、検索エンジンへそのコンテンツを流し実際とは異なる内容で高評価を得ようとする不正行為です。

これによりどんなにゴミのようなサイトでも検索流入を期待できるようになります。

Google検索で当サイトのドメイン以外に「ganohr.net」が含まれるサイトを検索すると4万超のサイトが見つかる。
Google検索で当サイトのドメイン以外に「ganohr.net」が含まれるサイトを検索すると4万超のサイトが見つかる。

 

こうしたコピーサイトを作る上で使われるボット(不正にコンテンツの内容を収集するソフト)は、多くがVPNやPROXYの上で運用されています。

そこで、今回は特にWordPress

VPNやPROXYやTOR経由によるRSS取得が試みられた場合に、その接続元をシャットアウトするコード

を共有します。

更新履歴
2023/01/31 公開

対策結果例

WordPressでRSSを取得しようとするIPがVPNやPROXYやTORかを検出しブロックするコードで、実際にブロックされているアクセスログ
WordPressでRSSを取得しようとするIPがVPNやPROXYやTORかを検出しブロックするコードで、実際にブロックされているアクセスログ。ちなみにこのIPはホスティングサービス上にある。
サムネイル62.210.215.112 | proxycheck.ioThis address from France is believed to be a Hosting Provider with a risk score of 66%. ... 外部サイトへアクセスproxycheck.io

 

当サイトのコンテンツをホスティングサービスが取得しており、こうしたアクセスを高確率でブロックできます。

なお、今回公開するコードではログ出力は省略しているので、必要な方は以下の記事を参考にWordPressでアクセスを実装したり必要な情報を出力してください。

サムネイルWordPressに独自のアクセスログを追加する方法!不正アクセス防止ウェブサイトを運営するにあたり、重要な意味がある「アクセスログ」。しかし、レンタルサーバーによっては、アクセスログの機能が提供されていないことがあります。そこでワードプレス自体にアクセスログを出力させる方法を解説します。 ... 続きを読むganohr.net2019-01-06

VPN/PROXY/TOR検出のために利用するサービス

虫眼鏡を除きこむスーツ姿の女性
IPアドレスがProxyかVPNかTORかを判定するには、専用の判定サービスを活用します
サムネイルProxy & VPN Detection API | proxycheck.ioproxycheck.io is a premium Proxy detection API with a full featured free plan. Try us today! ... 外部サイトへアクセスproxycheck.io

今回利用するのは、当サイトの運営にほぼ5年近く利用している『proxycheck.io』です。

これはIPアドレスがVPN及びPROXYやTORかをチェックできるサービスです。

 

利用料がとても安いながら、高精度であると実感しているため、長年愛用しています。

またWordPressなら専用プラグインも提供されています。

 

簡単操作でAPI利用に必要なアクセストークンを発行できる上、なんと1日1,000チェックまで完全無料です。

それを超えると判定できなくなりますが、日をまたげばすぐに利用可能になります。

WordPressのログインURLを防御したり、今回のように特定のURL(≒RSS用URL)へのアクセスを防ぐような用途には必要十分です。

サムネイルProxy & VPN BlockerBlocks Proxies, VPN's, select Countries, IP's, Ranges & ASN's accessing your site login or commenting on pages & posts using th … ... 外部サイトへアクセスja.wordpress.org

 

そこで今回は、このプラグインを利用して発行したアクセストークンとAPIを利用します。

この記事を実践する前に、上掲のプラグインを導入しておいてください。

WordPressでRSSやコメントページへのVPN/PROXY/TORを利用したアクセスを禁止するコード

オシャレな部屋で読書をしている眼鏡の女性
RSSフィードを取得したりコメントを書こうとするのは人間だけでいい

proxycheck.io.php.function.phpの入手とカスタマイズ

まず、以下のURLへアクセスしproxycheck.io.php.function.phpをダウンロードしてください。

サムネイルGitHub - proxycheck/proxycheck.io: PHP function for the proxycheck.io API.PHP function for the proxycheck.io API. Contribute to proxycheck/proxycheck.io development by creating an account on GitHub. ... 外部サイトへアクセスgithub.com

 

そしてダウンロードしたコードを以下のように改造します。

<?php
if (!defined('ABSPATH')) {
    die();
}

    /*      * A PHP Function which checks if the IP Address specified is a Proxy Server utilising the API provided by https://proxycheck.io      * This function is covered under an MIT License.      */
    function proxycheck_function($Visitor_IP) {
        // ------------------------------         // SETTINGS         // ------------------------------
        $API_Key = "######-######-######-######"; // Supply your API key between the quotes if you have one         $VPN = "1"; // Change this to 1 if you wish to perform VPN Checks on your visitors         $TLS = "1"; // Change this to 1 to enable transport security, TLS is much slower though!         $TAG = "1"; // Change this to 1 to enable tagging of your queries (will show within your dashboard)
        // If you would like to tag this traffic with a specific description place it between the quotes.         // Without a custom tag entered below the domain and page url will be automatically used instead.         $Custom_Tag = "IP Late Check"; // Example: $Custom_Tag = "My Forum Signup Page";
        // ------------------------------         // END OF SETTINGS         // ------------------------------
        // Setup the correct querying string for the transport security selected.         if ( $TLS == 1 ) {             $Transport_Type_String = "https://";         } else {             $Transport_Type_String = "http://";         }
        // By default the tag used is your querying domain and the webpage being accessed         // However you can supply your own descriptive tag or disable tagging altogether above.         if ( $TAG == 1 && $Custom_Tag == "" ) {             $Post_Field = "tag=" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];         } else if ( $TAG == 1 && $Custom_Tag != "" ) {             $Post_Field = "tag=" . $Custom_Tag;         } else {             $Post_Field = "";         }
        // Performing the API query to proxycheck.io/v2/ using cURL         $ch = curl_init($Transport_Type_String . 'proxycheck.io/v2/' . $Visitor_IP . '?key=' . $API_Key . '&vpn=' . $VPN);
        $curl_options = array(             CURLOPT_CONNECTTIMEOUT => 30,             CURLOPT_POST => 1,             CURLOPT_POSTFIELDS => $Post_Field,             CURLOPT_RETURNTRANSFER => true         );
        curl_setopt_array($ch, $curl_options);         $API_JSON_Result = curl_exec($ch);         curl_close($ch);
        // Decode the JSON from our API         $Decoded_JSON = json_decode($API_JSON_Result);
        // Check if the IP we're testing is a proxy server         if ( isset($Decoded_JSON->$Visitor_IP->proxy) && $Decoded_JSON->$Visitor_IP->proxy == "yes" ) {
            // A proxy has been detected.             return true;
        } else {
            // No proxy has been detected.             return false;
        }
    }

 

2~4行目は、WordPressを経由せずに直接アクセスによる呼び出しを防止するコードです。

17行目に払い出したAPIのトークンを設定してください。

18~20行目は、全部"1"を指定することを推奨します。

 

24行目は、WordPressプラグイン画面への結果に影響しないよう識別用にタグを設定しています。

 

このカスタマイズが終わったら、あなたが利用しているテーマのfunctions.phpがあるディレクトリへFTP等を用いて転送してください。

functions.phpのカスタマイズ

以下のコードを追加してください。

/* CC BY-SA 4.0 Copyright ganohr.net */
add_action('get_header',        'gnr_ip_uri_vpnorproxy_check', 1);
add_action('rdf_header',        'gnr_ip_uri_vpnorproxy_check', 1);
add_action('rss_head',          'gnr_ip_uri_vpnorproxy_check', 1);
add_action('rss2_head',         'gnr_ip_uri_vpnorproxy_check', 1);
add_action('atom_head',         'gnr_ip_uri_vpnorproxy_check', 1);
add_action('commentsrss_head',  'gnr_ip_uri_vpnorproxy_check', 1);
add_action('commentsrss2_head', 'gnr_ip_uri_vpnorproxy_check', 1);
add_action('comments_atom_head','gnr_ip_uri_vpnorproxy_check', 1);

function gnr_aa_die() {     header('HTTP/1.1 403 Forbidden');     die(); }
function gnr_ip_uri_vpnorproxy_check() {     $OK_CACHE_DAYS = 14; // 問題ない場合のキャッシュ日数     $NG_CACHE_DAYS = 90; // VPN/PROXYだった場合のキャッシュ日数
    // IPアドレスを取得     $ip = @$_SERVER['REMOTE_ADDR'];
    // ログインユーザー及び自サーバからのアクセスは許可     if (is_user_logged_in() || $ip === $_SERVER['SERVER_ADDR']) {         return;     }
    // チェック結果のキャッシュを取得     $key = "gnr-banned-check-$ip";     $ret = get_transient($key);
    if ($ret === 'need-ban') {         // 403 Forbidden         gnr_aa_die();
    } elseif ($ret === 'ok') {         // 問題なし         return;     }
    // IPアドレスのチェックを行うURIの一部(strposで簡易チェックするため留意)     $check_uri_parts = ['/feed/', '/rdf/', '/comment-page-'];
    // 現在のURIを取得     $uri = get_permalink();
    // URIがチェック対象になっているか確認     $need_check = false; // チェック不要
    foreach ($check_uri_parts as $part) {         if (strpos($uri, $part) !== false) {             // チェック必要             $need_check = true;             break;         }     }
    // チェック不要なら抜ける     if ($need_check === false) {         return;     }
    // proxycheck.ioでIPアドレスをチェックする     require_once __DIR__ . '/proxycheck.io.php.function.php';
    if (proxycheck_function($ip)) {         // proxy・vpn・torなのでアクセス禁止         set_transient($key, 'need-ban', DAY_IN_SECONDS * $NG_CACHE_DAYS);
        // 403 Forbidden         gnr_aa_die();     }
    // 問題ないのでキャッシュ     set_transient($key, 'ok', DAY_IN_SECONDS * $OK_CACHE_DAYS); }

 

一応コードの解説をしておくと、

2~9行目はWordPressの各アクションフックへgnr_ip_uri_vpnorproxy_check関数を登録しています。

特にWordPressは様々なrssのタイプに対応しているため、それぞれに応じたアクションフックが大量にあります。

 

17行目はVPNでもPROXYでもTORでもない場合に、そのIPのチェック結果をキャッシュしておく日数を指定できます。
18行目はVPNやPROXYやTORだった場合に、そのIPからの接続をシャットアウトする日数を指定できます。

この値は運用するサイトの管理者と相談して決めてください。

 

21行目で接続元のIPを取得しています。通常はこのままで大丈夫です。

ただし、CDNを利用している場合などではexplode(',', $_SERVER['SERVER_ADDR'])[1]などのようにして、適切に接続元のIPが取得できるように変更してください。

 

24~26行目はログインユーザーやサーバー自体からのアクセスの場合、ブロックしないようにするコードです。

場合によっては、UAを元にGooglebot等の検索エンジンの場合もブロックしないようにする方が適切かもしれません。

 

28~39行目で既に判定結果がキャッシュされている場合の処理を記述しています。

'need-ban'となっていればVPN/PROXY/TORなので403 Forbiddenで遮断します。

'ok'となっていれば問題ないので処理を中断します。

 

42行目に、このチェックを行うURIの一部を指定し、42~61行目でチェックが必要か否かを判定しています。

このチェックはどうしても100ms~300msのラグが発生するため、チェックを行うべきURIを限定する必要があります。

 

ちなみに、RSSとしては「feed」と「rdf」の2種類しか定義していませんが、現状最新のWordPressは自動的にこの2つにリダイレクトします。

そのため、指定としてはこれだけで問題ありません。

※ 詳しくは以下のページを参照してください。

サムネイルWordPressで個別ページのRSS配信を禁止する方法著作権侵害系の不正アクセス(コピーサイトスパムサイトのコンテンツ水増しetc)のために有名サイトのRSSを悪用している馬鹿者共がいます.そうした他人のコンテンツを流用することしかできない無能集団を排除するためにRSS配信を禁止してきましたが当サイトを巡回してくださっているまっとうな利用者に不便を押し付けるのもどうかと思います.そこで折衷案として「トップページのRSSはタイトルと短い概要のみにする個別ページのRSS配信は禁止する」という対策を取りました.RSSを短い概要のみにす ... 続きを読むganohr.net2022-12-14

 

あとは64行目で先程アップロードしたproxycheck.io.php.function.phpを読み込んでいます。

実際の判定は66行目で行っており、ifが成り立つ場合はVPNやPROXYやTORと判定されているため、68行目で'need-ban'として判定結果を$NG_CACHE_DAYSで指定した日数分キャッシュし、403 Forbiddenで遮断します。

このifに入らなければ問題ないことがわかるため、判定結果を'ok'として$OK_CACHE_DAYSで指定した日数分キャッシュします。

実際に動作しているか確認する

お洒落なカフェで読書をしている眼鏡の女性
お使いのブラウザで「rss」や「feed」へアクセスし、トークンの利用数が上昇することを確認してください

 

実際に正しく動作しているか確認しましょう。

まず、「PVB Settings」→「API Key Statisticks」を開くと、現在のAPI利用数が「Queries Today」として表示されます。

PVB SettingsのQueries Todayが、API利用数を示す
PVB SettingsのQueries Todayが、API利用数を示す

 

その後、自分のブラウザでVPNやPROXYやTORなどを使わず「https://ドメイン名/feed/」などへアクセスしてください。

そして「API Key Statisticks」の画面をリロードし、「Queries Today」の値が増加することを確認できれば基本的に問題ありません。

 

実際にブロックできているかどうか確認したい場合は、PROXYやVPNにTORなどを用いてアクセスし、同様の手順で検証すると良いでしょう。

関連記事

サムネイルWordPressで個別ページのRSS配信を禁止する方法著作権侵害系の不正アクセス(コピーサイトスパムサイトのコンテンツ水増しetc)のために有名サイトのRSSを悪用している馬鹿者共がいます.そうした他人のコンテンツを流用することしかできない無能集団を排除するためにRSS配信を禁止してきましたが当サイトを巡回してくださっているまっとうな利用者に不便を押し付けるのもどうかと思います.そこで折衷案として「トップページのRSSはタイトルと短い概要のみにする個別ページのRSS配信は禁止する」という対策を取りました.RSSを短い概要のみにす ... 続きを読むganohr.net2022-12-14 サムネイルWordPressに独自のアクセスログを追加する方法!不正アクセス防止ウェブサイトを運営するにあたり、重要な意味がある「アクセスログ」。しかし、レンタルサーバーによっては、アクセスログの機能が提供されていないことがあります。そこでワードプレス自体にアクセスログを出力させる方法を解説します。 ... 続きを読むganohr.net2019-01-06

WordPressの不具合対応/カスタマイズ¥15,000~

PC歴25年超、SE歴10年超、WordPress運営歴7年超、WordPressエンジニア歴5年超のスキルとノウハウを提供します

当サイト管理人の「ガノー」(Ganohr)は、日本最大手且つ東証一部上場企業が運営するクラウドソーシングサイト『Lancers』にて、認定ランサーとして活動しています。


※ 認定ランサーとはLancersにより様々な能力 ( 高い仕事遂行率・高い顧客満足度・多くの実績、など ) を評価したプロフェッショナルを認定する制度です。

 

PHPカテゴリの最新記事