環境
- Nginx 1.31.1
やりたいこと
以下のようなNginx設定があったとする。
server { listen 443 ssl; server_name example.com; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-SSL-Cipher $ssl_cipher; location / { proxy_pass http://myserver; } }
がしかしBot攻撃が激しいのでNginxレベルでIPをブロックしたい。
その場合は以下のようになる。
location / { proxy_pass http://myserver; include /etc/nginx/block_ips.conf; deny all; }
ただ、このIP一覧にGoogleBot(本物)も含まれてしまっているのでユーザーエージェントに「Googlebot」の文字があれば許可したい。
コード
まず http ディレクティブの中に map ブロックを追加して、$is_googlebot という変数を定義する。User-Agentに「Googlebot」が含まれていれば1、それ以外は0になる。
# httpディレクティブ map $http_user_agent $is_googlebot { default 0; ~*Googlebot 1; }
次に server ブロック側でその変数を使う。if ($is_googlebot) でGooglebotと判定された場合は、内部ロケーション /_googlebot_proxy にリライトして通す。そうでない場合はIPブロックリストの評価に進み、deny all でブロックされる。
/_googlebot_proxy は internal を付けているので外部から直接アクセスはできない。
server { listen 443 ssl; server_name example.com; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-SSL-Cipher $ssl_cipher; location / { if ($is_googlebot) { rewrite ^ /_googlebot_proxy last; } proxy_pass http://myserver; include /etc/nginx/block_ips.conf; deny all; } location /_googlebot_proxy { internal; proxy_pass http://myserver$request_uri; } }