検証ページや社内向けの静的ページを、決まった接続元や利用者だけに見せたいことがあります。Nginxでは、接続元のIPアドレスを使う制限と、ユーザー名・パスワードを使うBasic認証を、URLの範囲ごとに設定できます。UbuntuのNginxで両方を試し、許可と拒否の応答を確認します。
1. 保護するURLと検証用ファイルを用意する
ここでは、Ubuntuのパッケージで導入したNginxが、HTTPSで静的サイトを配信している構成を使います。導入や設定ファイルのバックアップはNginx入門、証明書とHTTPからの転送はNginxのHTTPS化を参照してください。Basic認証では通信上のユーザー名とパスワードを保護するため、HTTPSを使います。
example.com は自分のドメインに置き換えます。HTTPS用の server ブロックに root /var/www/nginx-demo; と index index.html; がある構成で、/private/ を保護します。別の公開ディレクトリを使っている場合は、検証用ファイルの保存先も合わせます。
制限が効くまでの確認には、公開しても問題のない検証用ファイルを使います。private/index.html が既にある場合は、別のパスを選び、以降の例もそのパスに合わせてください。
sudo install -d -m 0755 /var/www/nginx-demo/private &&
printf '%s\n' 'Nginx access test' | sudo tee /var/www/nginx-demo/private/index.html >/dev/null
次の設定をHTTPS用の server ブロックに一度だけ追加すると、末尾のスラッシュを省いた /private も /private/ に案内できます。以降の location ^~ /private/ の例は、試す方式に合わせて同じブロックを編集します。
location = /private {
return 302 /private/;
}
2. IPアドレスでアクセスを制限する
固定IPの拠点など、接続元を絞れる場合は allow と deny を使います。次の 192.0.2.10 は説明用です。許可する接続元のIPアドレスに置き換えてください。
location ^~ /private/ {
allow 192.0.2.10;
deny all;
try_files $uri $uri/ =404;
}
Nginxはルールを上から見て、最初に一致したルールを適用します。個別の許可を deny all より前に置きます。ネットワークをまとめて許可する場合は 198.51.100.0/24 のようなCIDR表記も使えます。IPv6経由で利用する端末がある場合は、その接続元も確認します。Nginx公式のアクセス制限モジュール
設定を変更したら、次のコマンドで構文を検査し、成功した場合だけ再読み込みします。以降の設定例でも同じ手順を使います。
sudo nginx -t && sudo systemctl reload nginx
許可した回線と、スマートフォンのモバイル回線など許可していない回線の両方から、同じURLを確認します。検証用ファイルが表示できる許可側は 200、IP制限で拒否する側は 403 が目安です。接続元は端末のLAN内IPではなく、Nginxのアクセスログで確認したアドレスを使います。
curl -sSI https://example.com/private/index.html
3. Basic認証でユーザー名とパスワードを求める
利用者の接続元が変わる場合は、Basic認証で利用者を確認できます。Ubuntuの apache2-utils に含まれる htpasswd でパスワードのハッシュを作り、公開ディレクトリの外へ保存します。
sudo apt update && sudo apt install apache2-utils
次は認証ファイルを初めて作る例です。-B はbcryptを指定します。-c は既存ファイルを上書きするため、新規作成時だけ指定します。Nginxのワーカーが www-data で動くUbuntuの構成に合わせ、ファイルを管理者とワーカーだけが読めるようにします。
sudo install -d -o root -g www-data -m 0750 /etc/nginx/auth &&
sudo htpasswd -c -B /etc/nginx/auth/private.htpasswd demo &&
sudo chown root:www-data /etc/nginx/auth/private.htpasswd &&
sudo chmod 0640 /etc/nginx/auth/private.htpasswd
パスワードは表示されたプロンプトで入力します。利用者の追加やパスワード変更には -c を省きます。ワーカーの実行ユーザーを変更した環境では、認証ファイルを読めるグループを実際の構成に合わせます。Apache HTTP Server公式のhtpasswdマニュアル
Basic認証だけを試す場合は、第2節で作った location ^~ /private/ を次の内容に更新します。auth_basic の文字列は認証の識別名、auth_basic_user_file は認証ファイルのパスです。
location ^~ /private/ {
auth_basic "Private area";
auth_basic_user_file /etc/nginx/auth/private.htpasswd;
try_files $uri $uri/ =404;
}
構文チェックと再読み込み後、認証情報なしで 401 と WWW-Authenticate が返り、正しいパスワードでは 200 になることを確認します。-u demo はパスワードを対話入力する指定です。
curl -sSI https://example.com/private/index.html
curl -sSI -u demo https://example.com/private/index.html
4. IP制限とBasic認証を両方必須にする
許可した接続元から、正しい認証情報を使ったときだけ通すには satisfy all を指定します。satisfy any にすると条件のどちらかを満たすだけで通るため、両方を必須にする設定では all を使います。Nginx公式のsatisfyの説明
location ^~ /private/ {
satisfy all;
allow 192.0.2.10;
deny all;
auth_basic "Private area";
auth_basic_user_file /etc/nginx/auth/private.htpasswd;
try_files $uri $uri/ =404;
}
構文チェックと再読み込み後、許可IPで正しい認証情報を使うと 200、許可IPでも認証情報がなければ 401、許可外のIPで正しい認証情報を使うと 403 になることを確認します。公開ページの / が従来どおり表示されることと、HTTP側で検証用ファイルが直接配信されずHTTPSへ転送されることも確認します。
5. 想定どおりに制限できないときの確認箇所
| 症状 | 確認すること |
|---|---|
| 許可した端末でも403になる | アクセスログの接続元IPを確認します。別回線、NAT、IPv6で想定とは異なるアドレスになっていることがあります。 |
| 認証しても401になる | 入力したユーザー名・パスワードと、Nginxが参照する認証ファイルを確認します。ブラウザーの認証情報の影響を避けるにはcurlで試します。 |
| 認証情報を送ると500になる | エラーログを読み、認証ファイルのパスと読み取り権限を確認します。 |
| 認証せずに200になる | HTTPS側の server と対象の location に制限があるか確認します。より具体的な location や、同じファイルを配信する別のURLも確認します。 |
CDNやロードバランサーの背後では、Nginxから見える接続元が中継サーバーになることがあります。実際の利用者のIPで判定するには、構成に合ったIPの受け渡し方法を確認し、set_real_ip_from で信頼する中継元を限定します。Nginx公式のReal IPモジュール
まとめ
固定IPで絞るなら allow と deny、利用者を確認するならHTTPS上のBasic認証を使います。設定を適用した後は、アクセスできる条件と拒否される条件をそれぞれ確認してから、保護対象のコンテンツを配置します。