Nginxで特定のUserAgentからのアクセスを制限する

2014-02-16

制限したいUserAgentが増えると管理が面倒。

Nginxの場合だと

if ($http_user_agent ~ (ZmEu|VeryBadBot|MaliciousBot) {
    return 403;
}

で出来るのは知っているのだけど、これだと制限したいUserAgentを増えてくると管理が面倒。

map

なんとかならんのかと思ったらmapディレクティブを使うとなんとかなった。

Module ngx_http_map_module

map $http_user_agent $bot {
    default                0;
    ~*(zmeu|verybadbot)    1;
    ~MaliciousBot          1;
    ~*(whatever|you|want)  2;
}

server {
    if ($bot = 1) {
        return 403;
    }

    if ($bot = 2) {
        return 500;
    }
}

とこんな感じで、UserAgentにzmeuやverybadbot(大文字小文字に関係なく)が含まれていると403を返す。UserAgentにMaliciousBotが含まれていると同じく403を返す。UserAgentにwhateverやyouやwantが含まれていると500を返すという設定ができるようだ。

ちなみに~はNginxにおける正規表現で、~*でcase-insensitive(大文字と小文字区別しない)、~だけだとcase-sensitive(大文字と小文字を区別する)になるのだそうな。

言うまでもなく設定ファイル編集後はNginxの再起動か設定のリロードを忘れずに。

$ sudo service nginx restart # またはreload

簡単なテストはcurl-AでUserAgentを変え、-IでHEADをリクエストすると便利。

$ curl -A "verybadbot" -I http://localhost
HTTP/1.1 403 Forbidden
Server: nginx/1.4.4
Date: Sun, 16 Feb 2014 06:03:29 GMT
Content-Type: text/html
Content-Length: 168
Connection: keep-alive

あるいはHTTPieを使うのもよいでしょう。

jkbr/httpie · GitHub

$ http HEAD localhost User-Agent:whatever
HTTP/1.1 500 Internal Server Error
Connection: close
Content-Length: 192
Content-Type: text/html
Date: Sun, 16 Feb 2014 06:07:14 GMT
Server: nginx/1.4.4

こういうやり方がNginx的に最適なのどうかは当方知りません。実運用は自己責任でお願いします。

tags: nginx