要件
特定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/