Nginx のIPアドレスアクセス制限とアクセスログ出力先変更

Nginx のIPアドレスアクセス制限とアクセスログ出力先変更 技術ネタ

最近、海外からの不正なアクセスが増えてきたため、IPアドレスによるアクセス制限を行いました。
Nginx 前提ですが、そのやり方について説明します。



IPアドレスでアクセス制限

IPアドレスのアクセス制限は geoモジュール を使って行いました。

allow / deny でもIPアドレスアクセス制限は可能ですが、今回は、IPアドレスでアクセスログの出力先も変更したかったため、 geo を使って行うことにしました。

まずは、nginx.conf に以下の記述を追加します。

include /etc/nginx/blockip.conf;

blockip.conf にIPアドレスの制限内容を記載します。
具体的な内容は以下の通りです。

geo $is_block {
    default        false;
    192.168.0.0/24 true;
}

map $is_block $blocklog {
    true     1;
    default  0;
}

map $is_block $non_blocklog {
    false    1;
    default  0;
}

3行目が制限(ブロックするIPアドレス)を記述します。
この例では仮に「192.168.0.0/24」としていますが、ここは制限したいIPアドレス(CIDRなど)に書き換えてください。

6行目以降の map については、後半で説明する アクセスログの出力先変更に使います。
最後に、設定した geo を使って、アクセス制限したい serverディレクティブに記述します。

server {
    listen       443 ssl http2;
    server_name return-favor.com www.return-favor.com;
    ・
    ・
    ・
    # 攻撃ブロック
    if ($is_block = "true") { return 444; }
    ・
    ・
    ・

8行目がアクセスブロックする記述です。
Nginxのステータスコード 444 を使って、レスポンスを返さずにコネクションを切断しています。

なお、全てのパスでブロックしたかったため、locationディレクティブではなく、serverディレクティブに書いています。

これで設定(IPアドレスによるブロック)完了です。

アクセスログの出力先を変更する

ブロックしたものが通常のアクセスログに記録されるとわかりにくくなるため、ブロックしたものはアクセスログに出力しないようにします。

ただし、ブロックした分の記録がなくなると困ることもあるため、ブロックした分のアクセスは別のログファイルに出力するようにしました。

具体的には、serverディレクティブに以下を記述します。

server {
        listen       443 ssl http2;
        server_name return-favor.com www.return-favor.com;

        access_log  パス名/ssl_access.log cmain if=$non_blocklog;
        access_log  パス名/block_ssl_access.log cmain if=$blocklog;
    ・
    ・
    ・

このように、アクセスログに if を追加することで、出力する条件をつけることができます。

この2つの変数「$non_blocklog」「$blocklog」は、最初に説明した blockip.conf 内の map は定義しています。それぞれ、
 ・$blocklog が通常アクセス
 ・$non_blocklog がIPアドレス制限対象
このような意味になります。

if には not 指定は出来ない?ようなので、別々の変数を用意しました。
この記述で、以下のようにログの出力先が変わります。
 ・6行目の通常のアクセスログ: ssl_access.log
 ・7行目のブロックされたアクセスログ: block_ssl_access.log

最後に

IPアドレスで制限しましたが、IPアドレスの指定が間違っていたり、本来ブロックすべきではないものを記述した時のことを考え、そのアクセスログを別ファイルとして残すような運用にしました。

同じようなことを考えている方がいたら、参考にしてください。