【nginx】特定のアクセスをログから除外する設定など

ログのスクリーンショットとnginxのロゴ画像

最近、Webサーバのアクセスログから、特定のアクセスを除外したいと思うことがありました。

そこでこの記事では、接続元IPアドレスやユーザーエージェントなどの特定の条件によって、アクセスログへの記録を除外する方法をまとめてみました。

この記事の内容を応用すれば、アクセス制限やその他の条件分岐にも利用できます。

前提知識

まず、アクセスのロギングを条件によって変更するうえで、便利な構文を紹介します。

これらの構文は設定ファイルの nginx.conf で使用できます。

access_log の if パラメータ

アクセスログの出力を制御するディレクティブであるaccess_logにはifパラメータが利用できます。

if=で指定された変数が非ゼロ(もしくは空文字列以外)である場合のみログが出力されます。

# $condition が非ゼロの場合のみログを出力する
access_log /var/log/nginx/access.log main if=$condition;

map ディレクティブ

mapディレクティブでは、指定した変数の値を元に、新しい変数に値をセットできます。

map $status $status_normal {
    #レスポンスのステータスコードが2xxか3xxの場合、変数 status_normal に1をセットする
    ~^[23] 1;

    #それ以外の場合、変数 status_normal に0をセットする
    default 0;
}

この設定例では、変数statusの値に応じて、変数status_normalに値をセットします。

変数statusは、組み込み変数(定義済み変数)と呼ばれる変数のひとつです。組み込み変数は、特に定義をしなくてもはじめから使える変数のことで、変数statusにはレスポンスのステータスコードが格納されています。

mapディレクティブの条件分岐には、正規表現※1nginxでは、正規表現ライブラリにPCREが使われているため、使用できるのはPerl互換の正規表現となります。も利用できます。正規表現を利用する場合、条件の先頭に ~(チルダ)を付けます。※2大文字小文字が区別されます。区別しない場合は ~* を条件の先頭に付けます。

 

mapディレクティブとaccess_logのifパラメータを組み合わせることで、ログ取得に柔軟な条件分岐を利用できます。

接続元IPアドレスによる除外設定

特定の接続元IPアドレスからのアクセスをログ対象から除外する設定です。

サイト管理者からのアクセスをログに記録したくない場合などに使えます。

特にWordPressを使用している場合、ダッシュボードへのアクセスや投稿の編集を行うと、結構な量のログを吐くので有効です。

#10.0.0.0/24 と 192.168.1.100 からのアクセスをログ対象から除外する
#geoディレクティブはサブネットマスクも解釈してくれる
geo $logging_addr {
    10.0.0.0/24 0;
    192.168.1.100 0;

    default 1;
}

access_log /var/log/nginx/access.log main if=$logging_addr

geoディレクティブを使うと、接続元IPアドレスを元に、変数に値をセットすることができます。使い方はmapディレクティブに似ています。

この設定例では、接続元IPアドレスが10.0.0.0/24 のネットワークと192.168.1.100の場合に、変数logging_addrに0をセットし、それ以外の場合は1をセットしています。

そして、変数logging_addrを先ほど紹介したaccess_log のifパラメータに設定することで、指定した接続元IPアドレスからのアクセスをログ対象から除外しています。

なお、geoディレクティブはngx_http_geo_moduleが有効になっていない場合使えません。(意図的に無効にしていない限りは使えるはず)

ちなみに、接続元IPアドレス以外の情報を元に変数をセットしたり、アドレス指定に任意の範囲(例えば、10.0.0.0-10.0.5.255)を使用することもできます。詳しくは、Module ngx_http_geo_module(公式ドキュメント)を参考にしてください。

ユーザーエージェントによる除外設定

特定のユーザーエージェントからのアクセスをログ対象から除外する設定です。

モバイルデバイスからのアクセスのみをログに記録したい場合などに使えます。

この表現はログの取得設定に限らず、デバイスの種類によって何らかの処理を分岐する場合にも応用できそうですね。

#モバイルデバイスからのアクセスのみをログ対象とする
map $http_user_agent $is_mobile {
    ~iPhone 1;
    ~(?=.*Android)(?=.*Mobile) 1;

    default 0;
}

access_log /var/log/nginx/mobile.log main if=$is_mobile;

コード例では、mapディレクティブと、ユーザーエージェントを格納している組み込み変数の http_user_agent を利用しています。

ユーザーエージェント一覧(モバイルデバイス)

ユーザーエージェント文字列は様々な理由から変更され、無限に存在するため、完全に判別するのは難しいです。

端末名 ユーザーエージェント正規表現
iPhone(iPod touch含む) iPhone
Android(スマートフォン)※3Windows 10 mobile のUA文字列に “Android” が含まれるため、”Windows Phone” が含まれるUAを除外 (?=.*Android)(?=.*Mobile)(?!.*Windows Phone)
iPad iPad
Android(タブレット) (?=.*Android)(?!.*Mobile)
Windows Phone(2017年開発終了? / Windows 10 mobile 含む) Windows Phone
BlackBerry(スマートフォン 2013年製以前 / 2013年OS開発終了) BlackBerry|BB10
Firefox OS(スマートフォン / 2016年開発終了) (?=.*Mobile)(?=.*Firefox)(?!.*Android)

ユーザーエージェント一覧(クローラー類)

名前 ユーザーエージェント正規表現
Googlebot(Googleのクローラー) Googlebot
Google Favicon Google Favicon
Google Adsense Mediapartners-Google
アドワーズボット(AdsBot) AdsBot-Google
Bingbot(Bingのクローラー) bingbot
Baiduspider(Baiduのクローラー) Baiduspider
YandexBot(ロシアの検索エンジンYandexのクローラー) Yandex.*Bot
GrapeshotCrawler GrapeshotCrawler

特定のファイル(URL)へのリクエストの除外設定

特定のファイル(URL)へのリクエストをログ対象から除外する設定です。

画像ファイルへのリクエストをログに記録したくない場合などに使えます。

#画像ファイルへのリクエストをログ対象から除外する
location ~* \.(png|jpg|jpeg|svg|gif|bmp|ico)$ {
    access_log off;
}

上記の設定例では、画像ファイルの拡張子にマッチするロケーションを作り、マッチしたリクエストをアクセスログから除外しています。

 

#<ドキュメントルート>/images 配下へのリクエストをログ対象から除外する
location /images {
    access_log off;
}

特定のディレクトリ配下へのリクエストをアクセスログから除外することも可能です。

やってはいけない設定例

locationディレクティブの中でifを使っても同じような設定ができるようにも思えますが、やめたほうが無難でしょう。

nginxのifは、プログラミング言語のifと違い、予想外の挙動をすることがあるためです。特にlocation内のifは危険度が高いです。(access_logのifパラメータは、ここで言うifとは別物なので問題ない)

公式ドキュメントでも注意喚起されています。→ If は邪悪l | NGINX 日本語訳

 

悪い設定例として、接続元IPアドレスによる除外設定を、locationとifで実装したものを挙げてみます。

location / {
    try_files /image @imagesrv;
    if ($remote_addr = 192.168.1.100) {
        access_log off;
    }
}

これで期待通りに動作するように思えますが、実際には、192.168.1.100からのアクセスに対してはlocation内のtry_filesは動作せず、404が返ってきます。

 

というわけで、nginxの設定では、安易にifを使わないようにし、使う場合はよくテストしてから使うようにしたほうが良いでしょう。

参考

 

マスタリングNginx

Dimitri Aivaliotis 著 高橋基信 訳

 

脚注   [ + ]

1. nginxでは、正規表現ライブラリにPCREが使われているため、使用できるのはPerl互換の正規表現となります。
2. 大文字小文字が区別されます。区別しない場合は ~* を条件の先頭に付けます。
3. Windows 10 mobile のUA文字列に “Android” が含まれるため、”Windows Phone” が含まれるUAを除外

あわせて読みたい

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です