banner
Vinking

Vinking

你写下的每一个BUG 都是人类反抗被人工智能统治的一颗子弹

禁止マーケティングクモによるウェブサイトのクロール

今日はウェブサイトのアクセスログを見ていたら、Mozilla/5.0 (compatible; SemrushBot/7~bl; +http://www.semrush.com/bot.html) というユーザーエージェントのクローラーが非常に頻繁にウェブサイトをクロールしていることに気付きました。20MB 以上のログを見れば、ウェブサイトをクロールしているのはかなりの時間だとわかります。

サイトログ

このクローラーがクロールしているウェブページを見ると、以前にクロールしたページのいくつかのパラメータをランダムに組み合わせて再度アクセスしているようです。そのため、クロールされるリンクは長い文字列になり、基本的に返されるのは 404 です。さらに、数秒ごとにクロールされるため、ログ内の正常なアクセス記録は数万行のゴミクローラーの記録に埋もれてしまっています。

最初は、クローラーなので robots.txt を遵守するはずだと思い、robots.txt にルールを追加すればいいだろうと思いました:

User-agent: SemrushBot
Disallow: /

しかし、ネットで調べてみると、このクローラーはどうやら robots.txt を遵守しないようです 😅(公式ページではクローラーが robots.txt を厳密に遵守すると主張していますが、ネットのフィードバックを見る限りそうではないようです)。しかも、この SemrushBot だけでなく、多くのマーケティングクローラーも robots.txt を遵守しません。仕方がないので、Nginx を使って遮断することにしました。宝塔の Nginx 無料ファイアウォールグローバル設定User-Agent フィルタルール をクリックし、以下の正規表現を追加しました(ネットから集めたもので、こんなに多いとは思いませんでした。ついでに、いくつかの無駄な UA も追加しましたので、使用前に必要な UA がないか確認してください):

(nmap|NMAP|HTTrack|sqlmap|Java|zgrab|Go-http-client|CensysInspect|leiki|webmeup|Python|python|curllCurl|wget|Wget|toutiao|Barkrowler|AhrefsBot|a Palo Alto|ltx71|censys|DotBot|MauiBot|MegaIndex.ru|BLEXBot|ZoominfoBot|ExtLinksBot|hubspot|FeedDemon|Indy Library|Alexa Toolbar|AskTbFXTV|CrawlDaddy|CoolpadWebkit|Java|Feedly|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|heritrix|Bytespider|Ezooms|JikeSpider|SemrushBot)

その後、数秒待つと、遮断されたデータが見えるようになります。

遮断データ

その後、常に増加する遮断数を見て、404 でも 444 でもリクエストを発信するだけで、サーバーリソースを消費することになることに気付きました。このように数秒ごとにリクエストを送るのは長続きしません。これらのクローラーの IP を調べると、すべて海外のノードであり、私のウェブサイトの海外回線も Cloudflare に解析されているので、Cloudflare に中間でブロックしてもらうことができ、ウェブサイトへのアクセスを防ぐことができます。

クローラー IP

Cloudflare の対応するドメインコンソールに入ったら、セキュリティWAF セクションに進み、ルールを追加をクリックします。式プレビューに以下の式を追加します(同様に、使用前に必要な UA がブロックされていないか確認してください):

(http.user_agent contains "SemrushBot") or (http.user_agent contains "FeedDemon") or (http.user_agent contains "Indy Library") or (http.user_agent contains "Alexa Toolbar") or (http.user_agent contains "AskTbFXTV") or (http.user_agent contains "AhrefsBot") or (http.user_agent contains "CrawlDaddy") or (http.user_agent contains "CoolpadWebkit") or (http.user_agent contains "Java") or (http.user_agent contains "Feedly") or (http.user_agent contains "UniversalFeedParser") or (http.user_agent contains "ApacheBench") or (http.user_agent contains "Microsoft URL Control") or (http.user_agent contains "Swiftbot") or (http.user_agent contains "ZmEu") or (http.user_agent contains "jaunty") or (http.user_agent contains "Python-urllib") or (http.user_agent contains "lightDeckReports Bot") or (http.user_agent contains "YYSpider") or (http.user_agent contains "DigExt") or (http.user_agent contains "HttpClient") or (http.user_agent contains "MJ12bot") or (http.user_agent contains "heritrix") or (http.user_agent contains "Bytespider") or (http.user_agent contains "Ezooms") or (http.user_agent contains "JikeSpider") or (http.user_agent contains "HTTrack") or (http.user_agent contains "Apache-HttpClient") or (http.user_agent contains "harvest") or (http.user_agent contains "audit") or (http.user_agent contains "dirbuster") or (http.user_agent contains "pangolin") or (http.user_agent contains "nmap") or (http.user_agent contains "sqln") or (http.user_agent contains "hydra") or (http.user_agent contains "libwww") or (http.user_agent contains "BBBike") or (http.user_agent contains "sqlmap") or (http.user_agent contains "w3af") or (http.user_agent contains "owasp") or (http.user_agent contains "Nikto") or (http.user_agent contains "fimap") or (http.user_agent contains "havij") or (http.user_agent contains "BabyKrokodil") or (http.user_agent contains "netsparker") or (http.user_agent contains "httperf") or (http.user_agent contains " SF/") or (http.user_agent contains "zgrab") or (http.user_agent contains "NMAP") or (http.user_agent contains "Go-http-client") or (http.user_agent contains "CensysInspect") or (http.user_agent contains "leiki") or (http.user_agent contains "webmeup") or (http.user_agent contains "Python") or (http.user_agent contains "python") or (http.user_agent contains "wget") or (http.user_agent contains "Wget") or (http.user_agent contains "toutiao") or (http.user_agent contains "Barkrowler") or (http.user_agent contains "a Palo Alto") or (http.user_agent contains "ltx71") or (http.user_agent contains "censys") or (http.user_agent contains "DotBot") or (http.user_agent contains "MauiBot") or (http.user_agent contains "MegaIndex.ru") or (http.user_agent contains "BLEXBot") or (http.user_agent contains "ZoominfoBot") or (http.user_agent contains "ExtLinksBot") or (http.user_agent contains "hubspot")

その後、操作を選択ブロックを選び、保存すれば完了です。

Cloudflare カスタムルール

これで、宝塔の Nginx 無料ファイアウォールのリスク遮断数が増えなくなりました。そして、Cloudflare のファイアウォールルールの遮断数が急増しているときは、Cloudflare がこれらのゴミクローラーのアクセスを成功裏に遮断したことを示しています。

目覚めて更新#

目が覚めると、すでに 2000 回以上遮断されていました。このクローラーは本当にしつこいですね😅。

Cloudflare カスタムルール

カスタム遮断ページ#

最近、Cloudflare のデフォルトの遮断ページを見たのですが、あまりにも醜いと感じました... カスタムの遮断ページに変更したいと思いました。

Cloudflare デフォルトの遮断ページ

結果、カスタムページを使用するには Pro プランにアップグレードする必要があることがわかりました。まあ、無料で使っている人がカスタムページのためにアップグレードすることは不可能なので、比較的単純な方法で実現することにしました。考え方は、上記の User-Agent に該当する訪問者をすべてカスタムページにリダイレクトすることです。

Note

🔔ご注意:Vercel にホスティングされたページは国内ではアクセスできません。なぜなら、当サイトの海外アクセスのみが Cloudflare を経由するため、国内でのアクセス可否は考慮する必要がありません。国内でもアクセス可能にしたい場合は、他のページホスティングプラットフォームを使用してください。

私たちは自分で静的な遮断ページを作成し、Vercelにホスティングする必要があります。

Vercel デプロイの詳細手順#

まず、Vercelに行き、新しいプロジェクトを作成します。

新しいプロジェクト

次に、左側で既存のリポジトリからカスタムページをインポートすることも、右側でテンプレートをクローンすることもできます。ここではまだカスタムページがないので、右側のテンプレートをクローンするリンクをクリックしてテンプレートを選択します。

テンプレートをクローン

ここでは React を使用してページを作成しているので、Create React App というテンプレートを使用します。デプロイボタンをクリックしてテンプレートを使用します。

次に、Create Git Repository 内で Github を接続し、カスタムリポジトリ名を入力し、デフォルトで Create private Git Repository を選択してプライベートリポジトリに設定し、Create をクリックすると自動的にデプロイされます。

デプロイ

Congratulations! のメッセージが表示されると、成功裏にデプロイされたことを示します。

成功裏にデプロイ

最後に、Github にコードを新しく作成したリポジトリにコミットします。コミットが完了すると、Vercel が自動的にページを更新します。

以下は、私が React で作成したカスタムページで、直接使用できます。

\src\App.js ファイル:

import React, { Component } from 'react'
import './App.css';

export default class App extends Component {
  state = {
    tran: {
      lang: 'en',
      title: 'このリクエストはブロックされました',
      contents_1: 'あなたのいくつかの特徴がブラックリストに存在し、このリクエストはブロックされました。',
      contents_2: 'これが誤報だと思う場合は、すぐに私に連絡してください。',
      footer: '@Vinking セキュリティセンター',
      tips: '詳細はセキュリティセンターの最適化に保存されました'
    }
  }
  handleTranslations = () => {
    const { lang } = this.state.tran
    const newState = (lang === 'en') ? {
      lang: 'zh',
      title: 'リクエストがブロックされました',
      contents_1: 'あなたのいくつかの特徴がブラックリストに存在し、このリクエストはブロックされました。',
      contents_2: 'これが誤報だと思う場合は、すぐに私に連絡してください。',
      symbols: '@ Vinking セキュリティセンター',
      tips: '詳細情報はセキュリティセンターの最適化に保存されました'
    } : {
      lang: 'en',
      title: 'このリクエストはブロックされました',
      contents_1: 'あなたのいくつかの特徴がブラックリストに存在し、このリクエストはブロックされました。',
      contents_2: 'これが誤報だと思う場合は、すぐに私に連絡してください。',
      symbols: '@Vinking セキュリティセンター',
      tips: '詳細はセキュリティセンターの最適化に保存されました'
    }
    document.title = newState.title
    this.setState({ tran: newState })
  }
  render() {
    const { title, contents_1, contents_2, symbols, tips } = this.state.tran
    return (
      <div className="content">
        <div className="card">
          <div className="cardHeader">
            <div>{title}</div>
            <div className='translation' onClick={this.handleTranslations}>
              <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 1024 1024"><path fill="#f8f9fa" d="M608 416h288c35.36 0 64 28.48 64 64v416c0 35.36-28.48 64-64 64H480c-35.36 0-64-28.48-64-64V608H128c-35.36 0-64-28.48-64-64V128c0-35.36 28.48-64 64-64h416c35.36 0 64 28.48 64 64v288zm0 64v64c0 35.36-28.48 64-64 64h-64v256.032C480 881.696 494.304 896 511.968 896H864a31.968 31.968 0 0 0 31.968-31.968V512A31.968 31.968 0 0 0 864 480.032H608zM128 159.968V512c0 17.664 14.304 31.968 31.968 31.968H512A31.968 31.968 0 0 0 543.968 512V160a31.968 31.968 0 0 0-31.936-32H160a31.968 31.968 0 0 0-32 31.968zm64 244.288V243.36h112.736V176h46.752c6.4.928 9.632 1.824 9.632 2.752a10.56 10.56 0 0 1-1.376 4.128c-2.752 7.328-4.128 16.032-4.128 26.112v34.368h119.648v156.768h-50.88v-20.64h-68.768V497.76h-49.504V379.488h-67.36v24.768H192zm46.72-122.368v60.48h67.392V281.92h-67.36zm185.664 60.48V281.92h-68.768v60.48h68.768zm203.84 488H576L668.128 576h64.64l89.344 254.4h-54.976l-19.264-53.664H647.488l-19.232 53.632zm33.024-96.256h72.864l-34.368-108.608h-1.376l-37.12 108.608zM896 320h-64a128 128 0 0 0-128-128v-64a192 192 0 0 1 192 192zM128 704h64a128 128 0 0 0 128 128v64a192 192 0 0 1-192-192z" /></svg>
            </div>
          </div>
          <div className="cardDesc">
            <span className="red">{contents_1}</span>
            <br />
            {contents_2}
          </div>
          <div className="cardSymbols">
            <div>{symbols}</div>
          </div>
        </div>
        <div className="tips">{tips}</div>
      </div>
    )
  }
}

\public\index.html ファイル:

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport"
    content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
  <meta name="theme-color" content="#07092f">
  <title>このリクエストはブロックされました</title>
  <meta name="description" content="このリクエストはブロックされました。">
</head>

<body>
  <div id="root"></div>
</body>

</html>

Cloudflare に戻り、ルールセクションのリダイレクトルールをクリックして、新しいルールを作成します。上記のマーケティングクローラーを遮断するための式を式編集ボックスに入力し、タイプ静的に選択し、URLに先ほどの Vercel ホスティングページのリンクを入力し、ステータスコード301に設定し、クエリ文字列を保持しないを選択すれば、カスタム遮断ページが作成されます。

Cloudflare リダイレクト

この記事は Mix Space によって xLog に同期更新されました。原文リンクは https://www.vinking.top/posts/codes/blocking-bots-with-cloudflare

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。