Container Apps don’t work with NSG-rule and needs more ports open
The project I am working on requires me to deploy our compute solution, .NET and Python, to an Azure service and it should only expose specific endpoints via Azure API Management (APIM). To accomplish this, I have set up some networking services including NSG-rules. The goal is to set up the network boundaries as strict as possible.
One of the things I started with is set up APIM in a subnet, the Container Apps in another subnet and use an NSG to limit traffic to only use port 443. This is based on the knowledge of my containers and what is mentioned on the overview pages of the Container Apps networking page.
┌─────────────────┐
│ APIM │
│ (Subnet A) │
└─────────────────┘
│
│ HTTPS Traffic
│ Port 443
│
│ NSG: Allow
│ Port 443 Only
│
▼
┌─────────────────┐
│ Container Apps │
│ (Subnet B) │
└─────────────────┘
Long story short: This does not work!
When trying to invoke any endpoint on the Container App via the APIM test page I continuously received an error.
Error occured while calling backend service.", “connection timed out: 10.0.6.139:443
As the IP-address is resolved, I know the DNS resolution works. Just a timeout on port 443.
Obviously, I’ve exposed port 443 in my containers. That’s the first thing you should probably validate when running into this issue.
I have two NSG rulesets, which do the following:
- APIM outbound:
AllowToContainerApps-10.0.3.0/24→10.0.6.0/23on port 443 - Container Apps inbound:
AllowFromApiManagement-10.0.3.0/24→*on port 443
It turns out, this isn’t enough.
The NSG rule AllowFromApiManagement on the Container Apps subnet only allows port 443, but the Container Apps Environment’s internal load balancer performs Destination NAT (DNAT) from port 443 to backend port 31443. The NSG evaluates traffic after the DNAT, so it is blocking traffic on port 31443. This is what happens:
- Source: APIM at 10.0.3.x
- Destination: LB VIP 10.0.6.139:443
- The load balancer NATs to backend: 10.0.7.49:31443 or 10.0.6.179:31443
Taken into account this information, the topology looks more like this
┌─────────────────┐
│ APIM │
│ (Subnet A) │
│ 10.0.3.0/24 │
└─────────────────┘
│
│ Port 443
│
▼
┌─────────────────┐
│ Load Balancer │
│ (10.0.6.139) │
│ │
│ DNAT: 443 → │
│ 31443 │
└─────────────────┘
│
│ Port 31443
│
│ NSG: Must Allow
│ Port 31443!
│
▼
┌─────────────────┐
│ Container Apps │
│ (Subnet B) │
│ 10.0.6.0/23 │
└─────────────────┘
In hindsight, this IS mentioned in the docs on a page called “Securing a virtual network in Azure Container Apps with Network Security Groups”, so hidden in plain sight. So when you want to use port 443 in the Container Apps and have an NSG in the network topology, you also need to allow port 31443.
This has taken me quite a few hours of troubleshooting as I was searching in the wrong direction at first and deployed APIM in it’s different networking modes. Hope this helps others who also haven’t read the documentation to it’s fullest.
