Edited at

NginxのX-Forward-Forを利用して条件付きでBasic認証制御

More than 3 years have passed since last update.


要件

特定IPのみBasic認証しない

その他IPのすべてはBasic認証をかける


ELB配下ではないNginxの設定

基本的には以下の設定でうまくいくはずですが、

server {

#....
location / {
satisfy any; #下記の設定どちらか一致すればよい
allow xxx.xxx.xxx.xxx;
# basic認証をしないIPを追加していく
deny all;
auth_basic "basic authentication";
auth_basic_user_file /xxx/.htpasswd;
}
}


ELB配下のNginx設定

AWSのELB配下にNginxを置くとELBを経由してNginxにアクセスするのでまともなリモートIPが取得できません。

ので以下のようにif文を使うことで要件を満たすことができました。

server {

auth_basic_user_file /xxx/.htpasswd;
set_real_ip_from 10.0.0.0/8; # ELBのIPが複数あるのでまとめて指定
real_ip_header X-Forwarded-For;

location / {
set $allow "false";
if ($http_x_forwarded_for ~ " ?xx\.xx\.xx\.xx$" ) { set $allow "true"; } #Basic認証かけないIP指定
if ($http_x_forwarded_for ~ " ?xx\.xx\.xx\.xx$" ) { set $allow "true"; } #Basic認証かけないIP指定

if ($allow = "true"){
set $auth_basic off; #Basic認証off
}
if ($allow = "false"){
set $auth_basic "basic authentication"; #Basic認証を使う&文言指定
}

auth_basic $auth_basic;

}
}

※注意

if文中にauth_basicを入れるとエラーになるので変数を使って処理します。


その他(NginxでIFを使うのはまずい?)


Nginxにおいてifは鬼門です。できるだけ使わないようにしましょう。

ifは内部的にlocationを作って動作するため、動作が非常にわかりづらいことにトラブルの原因があります。

遷移をともなわない箇所(変数操作など)でifを使おうとすると、意図通りに動作しません。

変数操作にはmapディレクティブを使いましょう


私が見てる「Nginxポケットリファレンス」という本には上記のような文が書いてありました。

ifは鬼門ですね、、まだトラブってないですが、ifよりmapのほうがおススメのようです。

参考:

http://www.edwiget.name/2013/03/nginx-how-to-stop-requests-from-specific-ip-behind-aws-elb/