Webアプリケーションの配信と保護
[更新:2025年12月11日]
グローバルな配信基盤を通じてWebアプリケーションを高速に配信しつつ、WAFなどのセキュリティ機能で攻撃から保護する仕組みを構築します。これにより、遅延の少ない快適なユーザー体験と高い可用性を確保しながら、不正アクセス対策やトラフィック制御を一元化し、運用効率と安全性を同時に向上できます。
各機能のサービス対応
機能 |
対応サービス |
|---|---|
コードリポジトリ |
Azure Front Door |
システム構成要素
さくらのクラウド
エンハンスドロードバランサ
Nginxサーバ
Addon
Azure Front Door
構築手順
さくらのクラウドの準備
サンプルファイル内に、エンハンスドロードバランサとNginxサーバを作成するTerraformとAnsibleのサンプルコードを用意しています。
Let’s Encryptの設定
エンハンスドロードバランサーにLet’s Encryptを設定します。
SSL証明書のCommon Nameには、エンハンスドロードバランサーのFQDNを設定します。
オリジンガードの設定
エンハンスドロードバランサーのオリジンガードを有効にします。
オリジンガードトークンには、このサンプルではエンハンスドロードバランサーのリソースIDを設定します。
Addonの「ネットワークとCDN」機能 の準備
Azure Front Doorの作成
Addonの「CDNサーバ機能作成」APIを利用してAzure Front Doorを作成します。
endpoint.originGroup.origin.hostNameとendpoint.originGroup.origin.hostHeaderには、先に作成したエンハンスドロードバランサーのFQDNを設定します。
# APIキーを使用した認証トークン
TOKEN='<your-api-token>'
# POST
curl -v \
--location 'https://secure.sakura.ad.jp/cloud-test/zone/is1y/api/addon/1.0/cdn' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header "Authorization: Basic $TOKEN" \
--data '{
"location": "japaneast",
"profile": {
"level": 1
},
"endpoint": {
"route":{
"patterns": ["/*"],
"originGroup": {
"origin": {
"hostName": "example-lb.proxylb2.sakura.ne.jp",
"hostHeader": "example-lb.proxylb2.sakura.ne.jp"
}
}
}
}
}'
Azure Front Doorの診断ログ設定にAzure Data Lake Storage Gen2を利用するため、Addonの「データレイク機能作成」APIを利用してAzure Data Lake Storage Gen2を作成します。
#TOKEN='<your-api-token>'
#POST
curl -v \
--location 'https://secure.sakura.ad.jp/cloud-test/zone/is1y/api/addon/1.0/analytics/datalake' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header "Authorization: Basic $TOKEN" \
--data '{
"location": "japaneast",
"performance": 1,
"redundancy": 1
}'
Azure Front Doorの情報を取得
Addonの「CDNサーバ機能の個別取得」APIを利用して、作成したAzure Front Doorの情報を取得します。
properties.frontDoorIdの値はエンハンスドロードバランサ側の設定を行う際に利用するため、メモしておきます。
# APIキーを使用した認証トークン
TOKEN='<your-api-token>'
# GET
curl -v \
--location 'https://secure.sakura.ad.jp/cloud-test/zone/is1y/api/addon/1.0/cdn' \
--header 'Accept: application/json' \
--header "Authorization: Basic $TOKEN"
{
"data": {
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor",
"type": "Microsoft.Cdn/profiles",
"name": "myFrontDoor",
"location": "Global",
"kind": "frontdoor",
"tags": {},
"sku": {
"name": "Standard_AzureFrontDoor"
},
"properties": {
"originResponseTimeoutSeconds": 30,
"logScrubbing": null,
"frontDoorId": "324e651f-1234-1234-1234-123456789abc",
"extendedProperties": {},
"resourceState": "Active",
"provisioningState": "Succeeded"
},
"originGroups": [
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor/origingroups/myOriginGroup",
"type": "Microsoft.Cdn/profiles/origingroups",
"name": "myOriginGroup",
"properties": {
"loadBalancingSettings": {
"sampleSize": 4,
"successfulSamplesRequired": 3,
"additionalLatencyInMilliseconds": 50
},
"healthProbeSettings": null,
"trafficRestorationTimeToHealedOrNewEndpointsInMinutes": null,
"sessionAffinityState": "Disabled",
"provisioningState": "Succeeded",
"deploymentStatus": "NotStarted"
},
"origins": [
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor/origingroups/myOriginGroup/origins/myOrigin",
"type": "Microsoft.Cdn/profiles/origingroups/origins",
"name": "myOrigin",
"properties": {
"originGroupName": "myOriginGroup",
"hostName": "example-lb.proxylb2.sakura.ne.jp",
"httpPort": 80,
"httpsPort": 443,
"originHostHeader": "example-lb.proxylb2.sakura.ne.jp",
"priority": 1,
"weight": 1000,
"enabledState": "Enabled",
"sharedPrivateLinkResource": null,
"enforceCertificateNameCheck": true,
"provisioningState": "Succeeded",
"deploymentStatus": "NotStarted"
}
}
]
}
],
"endpoints": [
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor/afdendpoints/myEndpoint",
"type": "Microsoft.Cdn/profiles/afdendpoints",
"name": "myEndpoint",
"location": "Global",
"tags": {},
"properties": {
"hostName": "myEndpoint-1234567890ab.a03.azurefd.net",
"autoGeneratedDomainNameLabelScope": null,
"enabledState": "Enabled",
"provisioningState": "Succeeded",
"deploymentStatus": "NotStarted"
},
"routes": [
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor/afdendpoints/myEndpoint/routes/myRoute",
"type": "Microsoft.Cdn/profiles/afdendpoints/routes",
"name": "myRoute",
"properties": {
"cacheConfiguration": null,
"customDomains": [],
"originGroup": {
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Cdn/profiles/myFrontDoor/originGroups/myOriginGroup"
},
"originPath": null,
"ruleSets": [],
"supportedProtocols": [
"Http",
"Https"
],
"patternsToMatch": [
"/*"
],
"forwardingProtocol": "MatchRequest",
"linkToDefaultDomain": "Enabled",
"httpsRedirect": "Enabled",
"enabledState": "Enabled",
"provisioningState": "Succeeded",
"deploymentStatus": "NotStarted"
}
}
]
}
]
},
"url": "https://portal.azure.com/#@contoso.onmicrosoft.com/resource/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup"
}
エンハンスドロードバランサ側の追加設定
エンハンスドロードバランサ側でX-Azure-FDIDで該当する値を持つアクセスだけを許可するようにルールを設定します。X-Azure-FDIDの値は、先ほどメモしたproperties.frontDoorIdを設定します。
X-Azure-FDIDは特定のAzure Front Doorリソースからの要求を識別する参照文字列参考:https://learn.microsoft.com/ja-jp/azure/frontdoor/front-door-http-headers-protocol
リクエストヘッダーを持つ場合はアクセスできるルールを追加します。
リクエストヘッダーを持たない場合は拒否するルールを追加します。
動作確認
次の項目を確認します。
リクエストヘッダーを持つAzure Front Door経由のアクセスではNginxサーバが表示されること
リクエストヘッダーを持たない場合は403と表示されステータス403が返ってくること
アクセスログの設定
Azure Front Doorのアクセスログを取得するよう設定します。
監視 > 診断設定を選択し、診断設定の追加を選択
以下の設定を行い、「保存」を選択
診断設定名を入力
カテゴリグループ「allLogs」を選択
Addonのデータレイク機能APIで作成したストレージアカウントを選択
設定したストレージアカウントに診断設定ログが保存されることを確認
insights-logs-{診断設定名}のコンテナーにアクセスし、JSONファイル形式でアクセスログが保存されていることを確認する
アクセスログの例:
{
"time": "2025-10-15T06:34:26.0000000Z",
"resourceId": "/SUBSCRIPTIONS/{SUBSCRIPTION_ID}/RESOURCEGROUPS/RG-ALCCHPCLNEKY4/PROVIDERS/MICROSOFT.CDN/PROFILES/AFD-5BLH76CRKCEIM",
"category": "FrontDoorAccessLog",
"operationName": "Microsoft.Cdn/Profiles/AccessLog/Write",
"properties": {
"trackingReference": "20251015T063426Z-1758f994594pqswshC1OSAaw4n0000000b3g00000000mb3q",
"httpMethod": "GET",
"httpVersion": "2.0.0.0",
"requestUri": "https://fde-5blh76crkceim-ekhwcwfbavg9e3cd.a03.azurefd.net:443/",
"sni": "fde-5blh76crkceim-ekhwcwfbavg9e3cd.a03.azurefd.net",
"requestBytes": "20",
"responseBytes": "179",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0",
"clientIp": "{CLIENT_IP_ADDRES}",
"clientPort": "54944",
"socketIp": "{SOCKET_IP_ADDRES}",
"timeToFirstByte": "0.010",
"timeTaken": "0.010",
"requestProtocol": "HTTPS",
"securityProtocol": "TLS 1.3",
"rulesEngineMatchNames": [],
"httpStatusCode": "304",
"edgeActionsStatusCode": "0",
"roxyConnectStatusCode": "",
"httpStatusDetails": "304",
"pop": "OSA",
"cacheStatus": "CONFIG_NOCACHE",
"errorInfo": "NoError",
"ErrorInfo": "NoError",
"result": "N/A",
"endpoint": "fde-5blh76crkceim-ekhwcwfbavg9e3cd.a03.azurefd.net",
"routingRuleName": "route-5blh76crkceim",
"clientJA4FingerPrint": "t13d1517h2_8daaf6152771_b6f405a00624",
"hostName": "fde-5blh76crkceim-ekhwcwfbavg9e3cd.a03.azurefd.net",
"originUrl": "https://site-rvyb634.proxylb1.sakura.ne.jp:443/",
"originIp": "{ORIGIN_IP_ADDRES}",
"originName": "site-rvyb634.proxylb1.sakura.ne.jp:443",
"originCryptProtocol": "N/A",
"originCryptCipher": "N/A",
"referer": "",
"clientCountry": "Japan",
"domain": "fde-5blh76crkceim-ekhwcwfbavg9e3cd.a03.azurefd.net:443",
"securityCipher": "TLS_AES_256_GCM_SHA384",
"securityCurves": "0x9a9a:0x11ec:X25519:prime256v1:secp384r1"
}
}
Azure Front DoorのWAF設定
参考:Azure Front Door上のAzure Webアプリケーションファイアウォール
本ユースケースではWAFの利用例として、IP制限を行う手順について説明します。
Azure Front Doorのセキュリティ > セキュリティポリシーの画面に遷移し、「追加」を選択
以下の設定を行い、セキュリティポリシーの「新規作成」を選択
名前:任意のセキュリティポリシー名を入力
ドメイン:Addon APIで作成したAzure Front Doorに関連付けられているドメイン
任意の名前を入力し、「作成」を選択
セキュリティポリシーの「保存」を選択
上記で作成したWAFポリシーを選択
カスタムルール > カスタムルールの追加を選択
カスタムルールタブで、次の項目で設定する
カスタムルール名:任意のカスタムルール名
状態:有効
ルールの種類:一致
優先度:任意の優先度(例では
100を指定)
カスタムルールの条件で次の項目を設定し、「追加」を選択する。
一致の種類:IPアドレス
一致変数:RemoteAddr
演算:次の値を含まない
IP アドレス:IPv4またはIPv6の単一のIPアドレス、または範囲を入力
結果:トラフィックを拒否する
特定IPアドレス以外からのアクセスをブロックするために、WAFの動作モードの設定を「防止モードに切り替える」を選択する
動作確認
Azure Front DoorのWAF設定について、次の動作を確認します。
許可されたIPからアクセスした場合、Nginxのページを表示できること
許可されていないIPからアクセスした場合、ブロックされること
Azure Front Doorのメトリック
Azure Front Doorでは、トラフィックやパフォーマンスに関する様々なメトリックが使用できます。
Azure Front Doorで確認できるメトリックの詳細については、以下のリンクの記事を参照ください。