【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点Tech TIPS

Azureの「App Service」で、サイトコンテンツへのアクセスをクライアント(ソース)IPアドレスで制限する方法は幾つかある。そのうち、内蔵のWebサーバ「NGINX」の設定を変更すると、App Service単体でディレクトリ単位でのアクセス制御を実現できる。その手順と注意点を説明する。

» 2025年03月05日 05時00分 公開
[島田広道デジタルアドバンテージ]
「Tech TIPS」のインデックス

連載目次

Azure App Service on LinuxにディレクトリごとのクライアントIPによるアクセス制限を実装

対象:Azure App Service on Linux(NGINX内蔵)


 広く一般公開しているWebサイトでも、一部コンテンツは管理者だけにアクセスを限定したい。そのような要件はよくあることだ。

 こうしたアクセス制限を手っ取り早く実装する方法の一つとして、特定のソースIP(クライアントIP)アドレスを判定して、アクセス許可/拒否を決めるというものがある。ユーザーを特定できずとも(会社などの)組織を限定できれば十分という場合によく用いられる。

 しかしAzureの「App Service」の場合、標準かつ内蔵の機能だとサイト全体でしか制限できない。ほとんどのコンテンツは一般公開のまま、特定のコンテンツのみを制限したい場合は、Front Doorなどの外部サービスの助けが必要になり、追加コストが必要になってしまう。

 実はApp Service on Linuxであれば、内蔵のWebサーバ「NGINX」の設定を書き換えることで、月々のクラウド料金を増やすことなく、特定ディレクトリに対するクライアントIPアドレスでのアクセス制限を実装することが可能だ。本Tech TIPSでは、その具体的な手順と注意点を説明する。

 App Service内蔵のNGINXの設定変更については、「【Azure】App ServiceのWebサーバ『NGINX』をカスタマイズする方法」を前提としている。

 また、App ServiceのランタイムスタックはPHP 8.3とする。その他のスタックではスタートアップスクリプト(後述)の名称や内容が異なる、といった違いがあるので注意していただきたい。

手順1――クライアントIPアドレスごとの許可/拒否を決める設定ファイルを作る

 まず、許可または拒否するクライアントIPアドレスを定義する設定ファイルを用意する。ここでは[/home/custom/etc/nginx/inc]というフォルダを新設し、そこに[restrict-by-ip.conf]という設定ファイルを以下のように記述する。

# restrict-by-ip.conf: クライアントIPアドレスごとのアクセス許可/拒否を決定する

# 取引先のIPv4アドレス(1つ)を許可
allow 192.0.2.3;

# ISP1から割り当てられたIPv4(複数)を許可/拒否
deny 198.51.100.14; # このIPのみ拒否
allow 198.51.100.8/29; # その他のサブネット内IPは許可

# ISP2から割り当てられたIPv6の一部を許可
allow 2001:db8:2:3:4:5::/96;

# 上記以外は全て拒否
deny all;

【NGINX】クライアントIPアドレスでアクセスを制限するために[inc/restrict-by-ip.conf]を新規追加する
パス: /home/custom/etc/nginx/inc/restrict-by-ip.conf
NGINXのレファレンス: allow/deny

 クライアントIPアドレスは上記リストの上から一致した順に許可/拒否が判定される。例えば「198.51.100.13」であれば「allow 198.51.100.8/29;」によってアクセスが許可される。一方、どれにも該当しないIPアドレスは最終行の「deny all;」によってアクセスが拒否される。

 上記リストは、後述の[sites-available/default]に直接記述することも可能だ。ただ、別ファイルに格納した方が、複数のディレクトリを容易に制限できる他、複雑になりやすい[sites-available/default]のシンプルに維持しやすい、といったメリットがある。

手順2――特定のディレクトリでクライアントIPアドレスによるアクセス制限を有効にする

 次に、正しいクライアントIPアドレスを取得するための設定と、制限対象のディレクトリに関する設定を、[sites-available/default]に記載する。

server {
    #proxy_cache cache;
    #proxy_cache_valid 200 1s;
    listen 8080;
    listen [::]:8080;
    root /home/site/wwwroot;
    index  index.php index.html index.htm;
    server_name  example.com www.example.com
    port_in_redirect off;

    # ---------- 以下を挿入 ----------
    # 正しいクライアントIPアドレスを取得するための設定
    real_ip_header X-Forwarded-For;
    set_real_ip_from 169.254.0.0/16;

    # 管理専用の「/kanrishanoheya」ディレクトリ以下は、
    # 特定のクライアントIPアドレスからのアクセスだけを許可
    location ~ ^/kanrishanoheya/ {
        # IP制限を記述した設定ファイルを読み込む
        include inc/restrict-by-ip.conf

        # 必要なら他のディレクティブをここに記述
    }
    # ---------- 挿入終わり ----------

    location / {            
        index  index.php index.html index.htm hostingstart.html;
    }

<後略>
}

【NGINX】[sites-available/default]を書き換えてクライアントIPアドレスによるアクセス制限を有効にする
パス: /home/custom/etc/nginx/sites-available/default
NGINXのレファレンス: real_ip_header/set_real_ip_from

 上記で挿入している「real_ip_header」「set_real_ip_from」ディレクティブは、NGINXとクライアントの間にリバースプロキシまたはロードバランサーなどが存在している状況で、実際のクライアントのIPアドレスを導出するためのものだ。

 App Serviceも、標準でクライアントとの間にロードバランサーが配置されている。デフォルト設定のままだと、前述の「allow」「deny」ディレクティブにはクライアントIPアドレスではなくロードバランサーのIPアドレスが伝わるため、意図した通りに制限できない。前出の[inc/restrict-by-ip.conf]の場合、全てのクライアントからのアクセスが拒否されてしまうので注意してほしい。

デフォルト(=「real_ip_header」などが未設定)時のクライアントIPアドレス検出結果 デフォルト(=「real_ip_header」などが未設定)時のクライアントIPアドレス検出結果

 そこで、まず「real_ip_header」に、経路上の各ロードバランサー/リバースプロキシがクライアントのIPアドレスを記載するヘッダー名称を指定する。App Serviceの場合は「X-Forwarded-For」を指定すればよい。

 次に、各ロードバランサー/リバースプロキシが取り得るIPアドレスを列挙して、「set_real_ip_from」に記載する。App Serviceの場合は「169.254.0.0/16」を指定すること。

 以上により、ロードバランサー/リバースプロキシの先にあるクライアントIPアドレス(発信元IPアドレス)がNGINXで正しく取り扱えるようになる。前述の「allow」「deny」ディレクティブにも、本当のクライアントIPアドレスが伝わり、意図通りに制限できるようになる。

「real_ip_header」などの設定後のクライアントIPアドレス検出結果 「real_ip_header」などの設定後のクライアントIPアドレス検出結果

 注意すべきは、「real_ip_header」「set_real_ip_from」ディレクティブをNGINXの設定ファイルのhttpコンテキストに記述しても、その中にあるserverコンテキストには反映されない、という点だ。そのため、[nginx.conf]や[conf.d/*.conf]ではなく、上記リストのように[sites-available/default]のserverコンテキスト内に記述する必要がある。

手順3――書き換えた設定ファイルで動作確認したらstartup.shに反映する

 ここまでの手順で各設定ファイルを追加/修正したら、Tech TIPS「【Azure】App ServiceのWebサーバ『NGINX』をカスタマイズする方法」の手順3〜5で説明しているように、動作確認をしてから[/home/startup.sh]に反映して、App Serviceを再起動する。

#!/usr/bin/env bash

# 設定ファイルを変更または差し替える
ln -snf /home/custom/etc/nginx/sites-available/default /etc/nginx/sites-available/default
ln -snf /home/custom/etc/nginx/inc /etc/nginx/inc

# NGINXに設定ファイルを再度読み込ませる
nginx -s reload

【シェルスクリプト】[/home/startup.sh]でNGINXの設定ファイルを差し替える

 設定ファイルが正しければ、許可していないIPアドレスから指定のディレクトリ以下(ここでは「/kanrishanoheya/」以下)のコンテンツをWebブラウザで開こうとすると、以下のように「403 Forbidden」が発生し、本来のコンテンツは表示されないはずだ。

制限をかけたディレクトリに対し、許可していないクライアントIPアドレスからアクセスした結果 制限をかけたディレクトリに対し、許可していないクライアントIPアドレスからアクセスした結果

【注意】常時接続(Always On)や正常性チェックのプローブ先はIP制限すべきではない

 Tech TIPS「【Azure】App Service on LinuxにBASIC認証を実装する方法と注意点」で説明しているように、「Always On(常時接続)」「正常性チェック」のプローブのアクセス先に何らかのアクセス制限を施すと、インスタンスが異常と見なされる恐れがある。

 具体的には「/」(ルート」と正常性チェックのプローブパスについては、クライアントIPアドレスでの制限を加えないようにする。制限したいディレクトリ(パス)だけをlocationディレクティブに指定して、他に影響しないようにアクセス制限を設定した方がよい。

【注意】Front Doorなど経由する全リバースプロキシのIPアドレスを「set_real_ip_from」ディレクティブに記述すべき

 もし、クライアントとApp Serviceの間に、Front Doorのようなリバースプロキシ/ロードバランサーが加わっている場合は、それらのIPアドレスも「set_real_ip_from」に追記する必要がある。そうしないと、本来のクライアントのIPアドレスがApp Serviceに伝わらなくなってしまうからだ。

 さらに、「real_ip_recursive on;」というディレクティブも追記して、多段のリバースプロキシ/ロードバランサーに対応させる必要もある。

 この辺りの詳細については、機会があれば別の記事で詳しく説明したい。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。