複数のAzureサービスを組み合わせる場合、IPアドレスによるアクセス制限などのために、各サービスに割り当てられるIPアドレスの範囲を取得しなければならないことがある。App ServiceとFront Doorを例に、その方法と注意点、実装例を説明する。
対象:Azureサービス(例: App Service on Linux、Front Door)
Tech TIPS「【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点」では、Azure App Service on Linuxに内蔵のWebサーバ「NGINX」の設定を変えることで、ソース(クライアント)IPアドレスによるアクセス制限を実装する方法を紹介した。
ただ、Azureのリバースプロキシ/CDNサービスである「Front Door」をクライアントデバイスとの通信路の間に設置する場合、この記事通りに設定してもNGINXが正しいクライアントIPアドレスを取得できず、アクセス制限も正しく働かない。
このような場合に、Azureサービスに割り当てられるIPアドレスの範囲を確認して、アクセス制限の設定を変える必要がある。本Tech TIPSでは、その方法と注意点を説明する。
App Service内蔵のNGINXの設定変更については、「【Azure】App ServiceのWebサーバ『NGINX』をカスタマイズする方法」「【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点」を前提としている。
本Tech TIPSでは、AzureサービスのIPアドレスを取得/利用する例として、以下のように「App Service」「Front Door」というAzureサービスを利用した一般公開のWebサーバのシステムを紹介する。
このシステムでは、Tech TIPS「【Azure】App Service on LinuxでディレクトリごとにクライアントIP制限を実装する方法と注意点」の通りに設定しても、NGINXの変数「$remote_addr」で表されるクライアントIPアドレスは図中の「バックエンド(Backend)」のIPアドレスとなり、本来のクライアントデバイスのIPアドレスとはならない。
この問題を解消するには、Front DoorのバックエンドのIPアドレス範囲を取得し、それをNGINXの設定ファイルに記述する。これにより、NGINXがクライアントデバイスのIPアドレスを正しく取り扱えるようになる。
Azure Front DoorなどのAzureサービスのリソースに割り当てられるIPアドレス範囲の一覧は、以下のMicrosoft Download Centerページで公開(配布)されている。
[Download]ボタンをクリックすると、IPアドレス範囲などが記されているJSONファイル[ServiceTags_Public_<年月日>.json]がダウンロードできる。約13万行でサイズは約4MBである(執筆時点)。
{
"changeNumber": 346,
"cloud": "Public",
"values": [
{
"name": "ActionGroup",
"id": "ActionGroup",
"properties": {
"changeNumber": 48,
"region": "",
"regionId": 0,
"platform": "Azure",
"systemService": "ActionGroup",
"addressPrefixes": [
"4.145.74.52/30",
"4.149.254.68/30",
"4.150.239.212/30",
"4.151.103.92/30",
"4.171.31.152/30",
<後略>
このJSONには、各リソースの情報が[values]キーの値(配列)として格納されている。その中の[properties]−[addressPrefixes]に、リソースに割り当てられるIPアドレス範囲が記載されている。
ここからは、ダウンロードしたJSONファイルからFront DoorのIPアドレスを抜き出して、App ServiceのWebサーバ「NGINX」にリバースプロキシ/ロードバランサーのIPアドレスとして伝達する例を紹介する。
[ServiceTags_Public_<年月日>.json]には、Front Doorに関係のあるリソースが複数記述されている。そのうち必要なのは、[name][id]キーの値が「AzureFrontDoor.Backend」である部分だ。前出の構成図の通り、「Backend(バックエンド)」はApp Serviceと直接通信する側を指している(フロントエンドはその反対側で、クライアントデバイスと通信する側)。以下にその該当部分を抜粋する。
<前略>
{
"name": "AzureFrontDoor.Backend",
"id": "AzureFrontDoor.Backend",
"properties": {
"changeNumber": 19,
"region": "",
"regionId": 0,
"platform": "Azure",
"systemService": "",
"addressPrefixes": [
"4.213.28.114/31",
"4.213.81.64/29",
"4.232.98.120/29",
"13.73.248.16/29",
<中略>
"2603:1050:6:1::7e0/123",
"2603:1050:403::5c0/123",
"2a01:111:20a::/48",
"2a01:111:2050::/44"
],
"networkFeatures": [
"API",
"NSG",
"UDR",
"FW"
]
}
},
<後略>
IPアドレスは[properties]−[addressPrefixes]キーに記載されている。これをNGINXの設定ファイルの「server」コンテキスト内に「set_real_ip_from」ディレクティブで記述していけばよい。
ただ、このIPアドレス一覧はしばしば変わるため、「server」コンテキストに直接記述するより、別の設定ファイル(以下では[inc/real-ip-frontdoor.conf])に記述して「include」ディレクティブで読み込ませた方が安全に更新しやすいだろう。
# inc/real-ip-frontdoor.conf: Azure Front DoorバックエンドのIPアドレスをリバースプロキシ/ロードバランサーのものとして伝達する
# Azure Front DoorバックエンドのIPアドレスをJSONファイルから転記
set_real_ip_from 4.213.28.114/31;
set_real_ip_from 4.213.81.64/29;
set_real_ip_from 4.232.98.120/29;
set_real_ip_from 13.73.248.16/29;
<中略>
set_real_ip_from 2603:1050:6:1::7e0/123;
set_real_ip_from 2603:1050:403::5c0/123;
set_real_ip_from 2a01:111:20a::/48;
set_real_ip_from 2a01:111:2050::/44;
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;
# ---------- 以下を挿入 ----------
real_ip_header X-Forwarded-For; # クライアントIPを記載するヘッダー名
set_real_ip_from 169.254.0.0/16; # App Service標準のロードバランサーのIPアドレス範囲
real_ip_recursive on; # 多段のリバースプロキシ/ロードバランサーに対応
include inc/real-ip-frontdoor.conf; # Front DoorのIPアドレス範囲を記述したファイルを読み込み
# ---------- 挿入終わり ----------
<後略>
}
「real_ip_recursive on;」というディレクティブは、複数のリバースプロキシ/ロードバランサーがWebサーバの手前の通信路に挿入されている場合に必要となる。ここでは、App Service標準のロードバランサーに加え、Front Doorも接続されているので、これが必要になる。
前述のように[ServiceTags_Public_<年月日>.json]はしばしば更新される。それに伴い、NGINXの設定ファイル[inc/real-ip-frontdoor.conf]の方も更新する必要がある。これは自動化したいところだ。
それには、最低でも以下の処理を自動実行できるようにする必要がある。
参考までに、上記を自動実行するRubyスクリプトを掲載しておく。
詳細は、ダウンロードされるZIPファイルを解凍すると現れるRubyスクリプトを参照していただきたい。
■関連リンク
Copyright© Digital Advantage Corp. All Rights Reserved.