Nginx を利用して特定のユーザーエージェントをブロックする手順をまとめてみました。
- 無駄なトラフィックを削減ししたい
- サーバー負荷を落としたい
- 特定コンテンツを非表示にしたい
規模が大きくなったウェブサイトには様々なアクセスがあります。人間がページ閲覧するアクセス以外に、サイト分析するためのプログラムによる機械的アクセスもあります。
プログラムによる機械的アクセスは、メリットもありますがデメリットもあるのでサイト管理者が制御を行う必要があります。
クローラー(ボット)によるアクセスを分類
プログラムによる機械的アクセスは、さまざまな種類があるので理解しておく必要があります。検索エンジンからのクローリングは基本的にメリットになることが多いですがアクセスが多すぎて困ることもあります。不正アクセスや攻撃などは全てのアクセスはお断りです。
スクリプトや自動化ツールによるアクセス
一部のユーザーは、スクリプトや自動化ツールを使用してウェブサイトにアクセスすることがあります。これは、特定のタスクやデータの取得を自動化する目的で行われることがあります。
スクレイピング
ウェブスクレイピングは、ウェブページからデータを抽出するために行われるプロセスです。これは、特定の情報や統計データを収集するために行われることがあります。
ソーシャルメディアボット
ソーシャルメディアプラットフォームにおいて、自動で投稿やアクションを行うボットが存在します。これらのボットは、特定の目的でプログラムされ、ソーシャルメディア上で活動します。
アナリティクスやモニタリングツール
ウェブサイトオーナーや運営者は、サイトのパフォーマンスやトラフィックを追跡するためにアナリティクスツールを利用します。これらのツールは、トラフィックの分析や利用者行動のモニタリングに使用されます。
セキュリティスキャナー
セキュリティスキャナーは、ウェブサイトやアプリケーションの脆弱性を検出するために利用されます。セキュリティ専門のボットが定期的にサイトにアクセスし、セキュリティの問題を報告することがあります。
これらは一般的なカテゴリであり、ウェブ上でさまざまな活動や目的によって異なるタイプのアクセスがあります。ウェブサイト運営者は、これらの異なるアクセスパターンに対して適切な対策や制御を行うことが重要です。
特定のユーザーエージェントを拒否する
一番簡単な設定(if ディレクティブ)
Nginxを使用して特定のユーザーエージェントを拒否するには、nginx.conf
ファイルまたはサーバーブロック内に if
ディレクティブを使用して条件分岐を行うことが一般的です。
ただし、if
ディレクティブは注意が必要で、使用には注意が必要です。
server { listen 80; server_name your_domain.com; location / { # ユーザーエージェントが指定の文字列を含む場合にアクセスを拒否 if ($http_user_agent ~* ( bad_user_agent-A | bad_user_agent-B )) { # Forbidden return 403; } # 通常の設定 # ... } # その他の設定 # ... }
上記の例では、$http_user_agent
変数を使用してリクエストのヘッダーからユーザーエージェントを取得し、正規表現を使用して特定の文字列(この場合は “bad_user_agent”)を検出しています。
ユーザーエージェントが一致した場合、return 403;
によってアクセスが拒否されます。
実用的な設定(map ディレクティブ)
confファイル内の map ディレクティブ
if
ディレクティブは柔軟性に欠け、不適切な使用方法により予期せぬ問題を引き起こす可能性があります。
多くのエージェントを拒否したい場合、if
ディレクティブ内に全てを記述する必要があるので見づらくなります。結果、記載ミスの原因になります。
if
ディレクティブの代わりに map
ディレクティブを使用してユーザーエージェントの一致を確認する方法は見やすくなるので実用的な設定です。
map $http_user_agent $bad_user_agent { default 0; ~*bad_user_agent-A 1; ~*bad_user_agent-B 1; ~bad_user_agent-C 1; ~bad_user_agent-D 1; } server { listen 80; server_name your_domain.com; location / { if ($bad_user_agent) { return 403; } # 通常の設定 # ... } # その他の設定 # ... }
この例では、map
ディレクティブを使用してユーザーエージェントが “bad_user_agent” と一致する場合に $bad_user_agent
を 1 に設定し、それを利用してアクセスを拒否しています。
# systemctl reload nginx
外部ファイルの map ディレクティブ
conf
ファイル内に map
ディレクティブを記述すると一箇所で完結するので良いこともありますが、設定が長くなり読みづらくなります。不適切な記述になり問題を引き起こす場合があります。
拒否するユーザー エージェント のリストは非常に大きくなりますので、すべてを server
セクション内に置くことはお勧めできません。
ブロックするユーザー エージェントのリストを外部の別ファイルで作成できます。私の場合は、/etc/nginx/useragent.txt を作成します。
$ vi /etc/nginx/useragent.txt map $http_user_agent $bad_user_agent { default 0; ~*bad_user_agent-A 1; ~*bad_user_agent-B 1; ~bad_user_agent-C 1; ~bad_user_agent-D 1; }
作成した外部ファイルを読み込ませる設定を行います。http
セクションを含む設定ファイル nginx.conf
構成ファイルを開き、http
セクション内に次の行を追加します。
http { # 通常の設定 # ... include /etc/nginx/useragent.txt }
include
は server
セクションの前に記述する必要があります。
次に server
セクション内に if
ステートメントを追加し、外部ファイルの内容を参照させます。
を確認する方法は見やすくなるので実用的な設定です。
server { # 通常の設定 # ... if ($bad_user_agent) { return 403; } }
Nginxに設定を反映させてください。
# systemctl reload nginx
map ディレクティブ 設定内容の解説
map ディレクティブに設定した内容について解説します。
map ディレクティブにて設定した変数値を if
ステートメントの条件として利用するのboolean型の真偽値を持たせます。
map $http_user_agent $bad_user_agent { default 0; ~*bad_user_agent-A 1; ~*bad_user_agent-B 1; ~bad_user_agent-C 1; ~bad_user_agent-D 1; }
default 0
は初期設定値を指定したものになり、ディレクティブ内に記述されていないユーザーエージェントを許可することを意味します。
~*
演算子は大文字と小文字を区別しない方法でキーワードと一致
~
演算子は大文字と小文字を区別するキーワードと一致
あとはアクセス拒否したいユーザーエージェントを足していくだけです。
あとがき
規模が大きいウェブサイトには様々なアクセスがあります。サイト分析するためのプログラムによる機械的アクセスを制御しないと、サーバー負荷が高くなりサイト表示が遅くなることがよくあります。
クローラーのアクセス制御を行うだけで、劇的にサイト表示が早くなります。積極的に設定を行い健全なサイト運営を行いましょう。