Azure Container Apps における IP アクセス制限
はじめに
この記事は、Azure Container Apps における IP 制限を実際に構築してみて触ってみた記録です。
どのような指定が可能なのか確認していきます。
環境
で作成したリソースを再利用しています。
アクセスログを確認しやすくするため、Nginx イメージを用います。
デフォルトのログフォーマットは以下のとおりです。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
Env 外のクライアント環境は 36.12.195.236 といった IP を持つことがわかっています。
$ curl ipconfig.io
36.12.195.236
また、上記と合わせて https://webcurl.sh/ も使います。便利ですね。
Ingress が external=true なアプリに対してインターネットから接続
IP アクセス制限なしの状態での確認

リモートアドレスには 100.100.0.157 や 100.100.0.66 といった値が確認できます。
X-Forwareded-for には ローカルクライアントの 36.12.195.236 や、webcurl を利用した場合は 147.182.189.201 が確認できます。
リモートアドレスはHTTP エッジ プロキシ のものと推測されます。
複数存在するのでしょうか。
許可ルールの動作
先ほど確認できた webcurl.sh を利用した場合の 147.182.189.201 のみを許可するようにしてみます。
webcurl.sh 側の ouboundIP が固定されていない可能性もありますが、一旦気にしない。

結果は想定通り
webcurl.sh からはOK

36.12.195.236 のクライアントからのアクセスには 403
$ curl -I https://aca-without-vnet-2.whitemoss-043fed62.japaneast.azurecontainerapps.io/
HTTP/2 403
content-length: 19
content-type: text/plain
date: Thu, 08 Jan 2026 09:30:16 GMT
なおシンプルなテキストレスポンスなのでブラウザで表示するとこんな感じ

当然アプリには届いていないので Nginx のログには出力されません。
試しに 100.100.0.0/24 を許可範囲に指定してみましたが、36.12.195.236 からはアクセスできませんでした。
拒否ルールの動作
次は webcurl を利用した場合の 147.182.189.201 を拒否するようにしてみます。

結果は想定通りですね。

$ curl -I https://aca-without-vnet-2.whitemoss-043fed62.japaneast.azurecontainerapps.io/
HTTP/2 200
server: nginx/1.28.1
date: Thu, 08 Jan 2026 09:43:43 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 23 Dec 2025 18:40:33 GMT
etag: "694ae221-267"
accept-ranges: bytes
考察
いずれも直感的です想定動作と思いますが、NSG 等に比べると随分シンプルです。
すべてのルールは同じ型である必要があります。 許可規則と拒否規則を組み合わせることはできません。
とあるように、許可と拒否を組み合わせることができなかったり、ServiceTag も利用できません。また、優先順位もつけることはできません。
実際の設定はこんな感じのJSONとなっていました。
$ az containerapp show -g zenn-aca-without-vnet -n aca-without-vnet-2 \
--query "properties.{configuration: {ingress: configuration.ingress}}" \
-o json
{
"configuration": {
"ingress": {
"additionalPortMappings": null,
"allowInsecure": false,
"clientCertificateMode": "Ignore",
"corsPolicy": null,
"customDomains": null,
"exposedPort": 0,
"external": true,
"fqdn": "aca-without-vnet-2.whitemoss-043fed62.japaneast.azurecontainerapps.io",
"ipSecurityRestrictions": [
{
"action": "Deny",
"description": "Deny147.182.189.201",
"ipAddressRange": "147.182.189.201",
"name": "Deny147.182.189.201"
}
],
"stickySessions": {
"affinity": "none"
},
"targetPort": 80,
"targetPortHttpScheme": null,
"traffic": [
{
"latestRevision": true,
"weight": 100
}
],
"transport": "Auto"
}
}
}
Ingress が external=false なアプリに対して Env 内から接続
IP アクセス制限なしの状態での確認
以下の 3 パターンでアクセスします。
- パブリック FQDN
https://aca-without-vnet.whitemoss-043fed62.japaneast.azurecontainerapps.io/publicAccess -
.internal.FQDNhttps://aca-without-vnet.internal.whitemoss-043fed62.japaneast.azurecontainerapps.io/internalAccess - App名アクセス
http://aca-without-vnet
1 についてはアプリに到達せずに404が応答されることを以前にも確認済み です。
2、3については、Nginx から 404 が応答されていることが分かります。

その時のログは以下のとおりです。
リモートアドレスには 100.100.0.157 とEnv外からのアクセス時と同じですが、
.internal. 経由の場合の X-Forwareded-for は 100.100.0.103、<app名> の場合は未指定となっています。

2026-01-08T09:56:27.7244857Z stdout F 100.100.0.157 - - [08/Jan/2026:09:56:27 +0000] "HEAD /internalAccess HTTP/1.1" 404 0 "-" "curl/8.14.1" "100.100.0.103"
2026-01-08T09:56:31.1590966Z stdout F 100.100.0.157 - - [08/Jan/2026:09:56:31 +0000] "HEAD /AppNameAccess HTTP/1.1" 404 0 "-" "curl/8.14.1" "-"
ちなみにクライアント側のアプリでは 100.100.205.191 という Private IP アドレスを持っています。
root@aca-without-vnet-2--0000003-558c795cc9-t9hhp:/# hostname -i
100.100.205.191
実際どのような経路になるのかこのへんはおいおい深堀して調べていきたいと思います。
許可ルールの動作
試しにパブリックIPのみ許可してみます。
そもそも ingress.external = false としているので Env 内からのアクセスのみが許容された状態で、
追加で 8.8.8.8 からのアクセスのみを許容するとしてみます。
矛盾していますが、IPアクセス制限が効くのであれば、Env 内からのアクセスは 403 ことが想定されます。

結果は.internal. 経由も<app名> の経由もアクセス可能でした。
このことから、IP アクセス制限は Env 内の通信には効果がないものと言えます。
拒否ルールの動作
こちらも、Private IP を指定して拒否することはできませんでした。
以下のように拒否ルールを構成しても、アクセス可能でした。

ここまでの結論
Azure Container Apps における IP アクセス制限は、外部環境の Env においては、環境外からのアクセスにのみ有効となり、Env 内での制限には効果を発揮しない。
(追記予定)カスタム VNet を持つ Env で VNet 内のクライアントからの接続
ここは気になるので、カスタム VNet 環境を用意したら追記する。
Discussion