24時間365日フルマネージドホスティングサービスのデイーネット

  • HOME
  •  
  • 技術情報ブログ
  •  
  • nginxでIPフィルタを設定した上で無許可IPにはステータスコードを返さない

nginxでIPフィルタを設定した上で無許可IPにはステータスコードを返さない

こんにちは。構築担当の下地です。

現在稼動しているnginxのサーバで、お客様より

「IPフィルタをかけつつ無許可IPからのアクセスにはステータスコードを返さないようにしたい」

というご要望を頂きました。

この設定についてnginxで色々試した話をします。

nginxのステータスコード444について

nginxでは独自のステータスコードとして「444」があります。

444は nginx にコネクションを閉じさせる特別なコードで、

return 444;

が評価されるとNGINXは何のレスポンスも返さずにコネクションを閉じます。

試しに444を設定したnginxサーバにブラウザからアクセスすると、

20180910_pageerror.jpg

このような表示になりました。

allowとdenyを使うIP制限ですと403 Forbiddenが返りますが、444にするとステータスコード自体が返りません。

geoモジュールについて

nginxでは、geoモジュールを使用することで、クライアントのIPアドレスに応じた値を持つ変数を作成します。

文章だけでは分かりにくいので、設定例を記載すると以下のようになります。

http {
    ...
    geo  $geo {
        192.168.10.100 NG;
        default  OK;
    }
    ...
    server {
        listen 80;
        server_name denet.co.jp;
        ...
        if ($geo = 'NG') {
            return 403;
        }
        ...
    }
    ...
}
...

このように書くと、「192.168.10.100」からアクセスがあると、変数geoにNGが代入されます。

するとserverコンテキスト内のif文でgeoに格納されている値が判定されて、NGの場合は403が返されます。

つまりこれはブラックリスト形式のIPフィルタとして機能します。

なお、geoモジュールはhttpコンテキスト内でしか使用できないのでご注意下さい。

シンプルに組み合わせて使う

この444ステータスコードとgeoモジュールを組み合わせることで、IPフィルタリングと無許可IPに対するステータスコード無応答の設定が行えます。

検証としてnginxで簡単なリバースプロキシを設定してみましょう。

自分のIPから対象サーバにアクセスするとyahoo.co.jpにリクエストが送られるようにします。

合わせて無応答版のIPフィルタを設定し、自分以外のIPからアクセスが来るとステータスコードを返さず接続を切るようにします。

[root@testserver ~]# cat /etc/nginx/conf.d/reverse_proxy.conf 
geo $access_filter {
    default NG;
    xxx.xxx.xxx.xxx OK;
}

server {
    listen       80;
    server_name  denet.sample;

    location / {
        if ($access_filter = "NG")
        { 
             return 444;
        }
        proxy_pass   http://yahoo.co.jp;
    }
}
[root@testserver ~]#

この設定で$access_filterの「xxx.xxx.xxx.xxx」部分に自分のIPを入れます。

すると指定したIPからアクセスがあった場合のみ変数access_filterにOKが代入されて、serverコンテキストで評価されます。

値がOKだとif文がスルーされて、yahoo.co.jpにプロキシします。

指定IP以外だとNGが入るため、ifに引っかかり444が返されます。

また、この設定だとホワイトリストとして機能します。

許可IPリストを外だしする

先ほどの書き方でも設定は問題ありませんが、許可したいIPが数十~数百個ある場合、全て同じファイルに書くと可読性が悪くなってしまいます。

そこで許可IPリスト部分を外だしファイルにしてみます。

まず先ほどと同じ設定ファイルreverse_proxy.confにincludeを使って読み込むファイルを指定します。

[root@testserver ~]# cat /etc/nginx/conf.d/reverse_proxy.conf 
geo $access_filter {
    default NG;
    include /etc/nginx/extra/ip_allow_list.conf;
}

server {
    listen       80;
    server_name  denet.sample;

    location / {
        if ($access_filter = "NG")
        { 
             return 444;
        }
        proxy_pass   http://yahoo.co.jp;
    }
}
[root@testserver ~]#

そして外だしファイルを新規作成して、許可したいIPを列記します。

[root@testserver ~]# cat /etc/nginx/extra/ip_allow_list.conf                                                                                     
111.111.111.111 OK;
222.222.222.222 OK;
333.333.333.333 OK;
[root@testserver ~]#

こんな感じにすると、reverse_proxy.confは可読性が保てますし、将来許可したいIPが増えた場合もip_allow_list.confに追記するだけで済みます。

まとめ

普段IPフィルタを設定する場合は、クラウド側のサービス(awsならセキュリティグループなど)で行うことが多いですが、今回は事情がありnginx側でフィルタ設定を行いました。

geoモジュールなどは今回初めて触ったので、依頼作業は余り知らない分野を触るいいきっかけになります。

今回もお読み頂きありがとうございました。

  • このページの先頭へ

  • 東京本社
    〒105-0001東京都港区虎ノ門2-3-22 第一秋山ビル5F
    TEL:03-3591-8887 FAX:03-3591-8886
  • 大阪本社
    〒541-0041 大阪市中央区北浜2-6-11北浜エクセルビル5F
    TEL:06-6231-8887 FAX:06-6231-8897

  • 認証範囲はこちらをご覧ください。

Denet logo

クラウドサービス・データセンタ・高機能専有サーバ・共有サーバホスティングサービス 株式会社ディーネット
dot_bar