スクレイピング・自動化対策について
はじめに
昔からサービスの運営者を困らせてきたものはいくつかあると思いますが、
特に代表的なのが “自動化による悪用” です。
スクレイピングによる無断データ収集や、予約システムを狙ったボット、さらには不正ログインを試みる自動化ツールなど、その形は時代とともに多様化してきました。
X (旧Twitter) には、今でも詐欺DMを送るボットが多いです。(自分は毎日来ます。)
また、大阪万博の予約を勝ち取るために、サーバーに過度の負荷をかける形で自動化が悪用された事例もあります。
そして、最近はAIを利用した巧妙なものも増えています。
この記事を読んで、そのような事態に対処できるように知識が少しでも増えれば良いな、と思っています。
ぜひ少しでも役に立てば、いいね・他SNSへの共有など、よろしくお願いします!!
実例
2025年現在、大阪万博なる物が開催されており、DX化の一環として予約をウェブサイトから取る形式になりました。
当然、様々な方法で自動化する人が現れます。
一番多かったのが、「Auto Clicker (aka Click Assistant)」を利用した物だと思います。
Auto Clicker は、画面に決められた操作を入力し、それをプログラムがエミュレート、再現してくれる物です。
参考画像
基本的にはゲームの周回などに利用されることが多いですが、万博の予約を取る手順がクリックなど単純な手順で再現でき、使っていた人も多い印象です。
実際にXなどで検索してみると、多く画像や動画が載っています。
同じような仕組みですが、PC等で行えるマクロもこの部類ですね。(pyautogui
などなど・・)
そして、もう一つは API を直叩きしているユーザーですね。
もちろん、そんな事をしているのは、エンジニア・プログラマーあたりの人でしょう。
この記事を読んでいる人の中にも、API を解析して自動化した人がいるのではないでしょうか。
Python や Node.js などを使用すれば、手軽に自動化出来ますね。
本質的には、Auto Clicker も API を利用した自動化もサーバーから見たら同じ自動化です。
対処する方法はいくつか考えられますが、一番簡単で効果的なのが "レートリミット" だと思います。
ちなみに、Zenn レベルのサービスでもこんなことになります・・
もう対処されましたが、一時期いいね 9677、コメント 10723 になるまで荒されていました。
話を戻します。
通常、自動化したいというニーズには、当然「同じ作業を何度もする」という問題を解決したいという事情があります。
問題の特性上、リクエストが通常より早く、多くなりがちな物に対してレートリミットは有効的です。
実際、万博のウェブサイトも自動化を回数/期間で検知をしていると考えられます。
その根拠に、自動化をしていないユーザーもX上でBAN報告をしています。
自動化していないユーザーも手動で何度も試行を行っているので、特定期間内に閾値を超えてしまい、BAN状態になっていると考えられます。
レートリミットは最低限自動化を防ぐ事ができ、実装も簡単ですが、一般ユーザーも被害を受けてしまうという問題点があります。また、効果が限定的になる事も多いです。
そこで、次の項では実際に多くのサイトで使われている対処法を紹介していきます!
対処法
1. レートリミット
前の項でも触れましたが、まず基本はリクエスト数を制御する レートリミット です。
「1秒に5回まで」や「1日毎に100回まで」といったルールを設定することで、短期間に集中したアクセスを検知して遮断できます。
IP単位での遮断が多いですが、アカウント単位との併用が現実的です。
なぜなら、一つのアカウントでもIPを変えれば、レートリミットを回避出来てしまうからです。
実装についてですが、
レートリミットは基本的に、多くのライブラリが存在するので実装が簡単な部類です。
また、自身でフルスクラッチしても問題ない量です。
ただし、レートリミットには複数のアルゴリズムがあるので、何を使うかは選定が必要です。
その中のいくつかを簡単に説明します。
1. トークンバケット
ユーザーごとにトークンを一定間隔で補充し、残っている間だけリクエストを許可する仕組みです。
リクエストごとにトークンを消費し、無くなったら制限を行います。
Twitch が採用しており、一時的にリクエスト量が増えるなどの状態でも対応できます。
2. リーキーバケット
空きが空いたらリクエストを流せるようにする方式で、水の入ったバケツがちょっとずつ漏れていくイメージです。
リクエストは一定の速度でしか流せません。
Shopify が採用しており、処理を一定に保ちたいときに便利です。
3. 固定ウィンドウカウンタ
1秒間にN回までと決める方法です。(期間は任意)
実装は簡単ですが、期間の切り替わる瞬間にリクエストが集中すると、2倍通ってしまう問題があります。
4. スライディングウィンドウ
最新のリクエストを基準に、過去一定範囲が閾値を超えないか判定する、というのが基本的なアプローチで、二つ種類があります。
一つ目は「スライディングウィンドウログ」と呼ばれ、
厳密ですが、タイムスタンプを大量に保持する必要がありメモリ効率が悪いです。
二つ目は「スライディングウィンドウカウンタ」と呼ばれ、
ざっくり言うと、直前の結果から間隔を推定するような方式です。
実装方法はインターネットにあるので、気になった方は検索してみてください。
2. CAPTCHA
言わずもがな、例のアレです。
画像認証やパズル、音声認証などを行い、人間とロボットを判別、区別するために使われます。
代表的な物に、reCAPTCHA, hCaptcha などがあります。
厳密には違いますが、Cloudflare turnstile も同じような使用感で導入できます。(JS Challenge)
かなり高い精度で Bot を弾ける一方、ユーザー体験を大きく損なうこともあります。
また、Driver や外部サービスを使った突破方法もあり、やろうと思えば突破できる。が、攻撃者目線コストがかかるという印象で良いと思います。
個人的に、hCaptcha は突破にかかる労力やコストが高いのでお勧めです。
一番ユーザー体験的に良いのは Cloudflare turnstile だと思いますが、突破が比較的簡単というデメリットもあります。
ちなみに、CAPTCHA は 「Completely Automated Public Turing test to tell Computers and Humans Apart」の略らしいです。
長すぎる。
ReCaptcha を使用したデモ: https://www.google.com/recaptcha/api2/demo
hCaptcha を使用したデモ: https://accounts.hcaptcha.com/demo
3. デバイスフィンガープリント
最近なうな方法と言えばこれです。
ブラウザや端末の環境情報(User-Agent、フォント、解像度、OSのバージョン、Canvasの動作などなど)を組み合わせて「同一環境からのアクセスかどうか」を推定します。
例: bcadc52670c11a5b8789853a6ef178ef
これらを保存しておき、比較することが出来ます。
ただし、Firefox ブラウザーや、AdBlocker などの拡張機能にはこれを防ぐ機能が存在することがあります。
また、プライバシー的にグレーと言われている現実もあるので、採用するには注意が必要です。
加えて、ユニークでは無いので被る事はあるので注意です。
FingerPrintJS: https://github.com/fingerprintjs/fingerprintjs
4. ローテーション
良いタイトルが思いつかないのでこうなっていますが、要はコードの難読化などを毎日変更したり、共通鍵をローテーションしようということです。
勿論イタチごっこにはなりますが、攻撃者のコストをかなり上げることができ、有効な手段です。
実際に、X (旧 Twitter) もこの方法を採用しています。
(気になる方は、x client transaction id
で検索)
5. ネットワークベースの制御
Cloudflare や Cloud を利用したことがあるなら、一回は触った事があると思います。
基本的に、攻撃者は海外IPを利用していることが多く、(VPNやProxyの都合上)
日本の住宅プロバイダーの串を利用しているという場合を除いて効果的です。
基本的に、以下の方法があります。
- 特定の国や地域からのアクセスを制限する
例: 中国のアクセスを遮断、もしくは CAPTCHA を表示するように変更する。
勿論、日本以外ということでも良いと思います。 - VPN やデータセンター経由のアクセスを判定してブロックする
基本的に、VPNは既知の物が多く、串はデータセンターを利用している場合が多いので、この二つが判定出来れば弾くことが出来ます。
例: https://ipinfo.io - Tor からの通信を制御する
Tor の串は無料で簡単に使えるので、利用している攻撃者も多いです。
そのため、Tor からのアクセスを遮断あるいは、CAPTCHA を行うことで、効果が出ると思います。
ただし、正規ユーザーが VPN を使っている場合もあるので誤検知のリスクは残ります。
Cloudflare を使っているなら、必ず使いましょう!
ちなみに、Cloudflare (Enterprise) は機械学習を利用した検知も提供しているみたいです。
例えば、Header "cf-bot-score" にどれだけ Bot の疑いがあるかの数値が、2-99 で入ってます。
6. アカウントレベルの制限
サービスによっては「アカウント単位」で制御する方法も有効だと思います。
例:
- 新規登録直後は利用制限をかける
- 信頼スコアが低いアカウントは厳しいチェックをする (通報などで、スコアを下げていく)
- 電話番号や二段階認証でハードルを上げる
SMS認証は大体、1通10円が定価です。破産した人も見たので、レートリミットは厳重に・・
加えて、「投稿時間が毎日一定である。」などなどサービスの特色によりけりですが、色々な方法は思いつけると思います。
7. 番外編
あまり表に出ない方法もあります。
例えば、「本物の入力フォームとは別に「偽フォーム」を置き、Bot だけが入力してしまうようにする」など。
ただし、これは無差別に攻撃を行っている Bot にのみ効果があるので注意です。
同じく、 HTML の hidden フィールドに「埋めるべきでない値」を仕込み、入力されたら Bot 判定のようなことも出来ます。
Shodan のような scanner を避けたいなら。 /wp-admin/*
などのスキャンをトリガーにし、アクセス禁止にするのも手だと思います。
もちろん、これらの方法は複数組み合わせてやっと効果が出ます。
例えば、レートリミットをかけても、怪しいIP (海外のProxyなど)を弾けなければ突破されます。
攻撃者をうんざりさせましょう!!
終わりに
この記事では、スクレイピング・自動化対策について、多くのサイトで採用されている対処法を紹介しました。
もし少しでも役に足ったり、面白かったら、いいねお願いします!
Discussion