Azure Firewall FQDN Egress for Mixed Protocols
App servers in spoke1 (10.21.0.0/24) must reach only three external services. The NSG on the app subnet allows outbound only to 10.0.0.4 (Azure Firewall, hub) on TCP 443, 587 and 8080, and to the hub DNS servers 10.10.3.4/10.10.3.5. A 0.0.0.0/0 UDR sends everything else to 10.0.0.4. On the firewall, application rules exist for api.contoso.com on 443, smtp.contoso.com on 587, and payments.contoso.com on 8080. Results after cutover: HTTPS calls to api.contoso.com succeed; SMTP on 587 times out; TCP 8080 to payments.contoso.com fails. Firewall logs show 'no rule matched' for the 8080 flows. Separately, the team wants to allow Azure Storage but not the whole service.
1. Explain why 443 works while 587 and 8080 do not, and what the firewall is actually doing in each case.
Read the worked answer
Azure Firewall application rules filter L7 and only understand HTTP, HTTPS and MSSQL.
- 443 succeeds because the firewall inspects the TLS ClientHello SNI, matches api.contoso.com, and allows the flow. No dependency on the client's DNS answer.
- 587 fails because SMTP is not a supported application-rule protocol. The rule can never match, so the flow is dropped with 'no rule matched'. It needs a network rule, which is IP/port based.
- 8080 fails for the same reason. Putting payments.contoso.com:8080 in an application rule is the design error - the firewall cannot read a hostname out of a non-TLS-ClientHello stream.
There is a second, quieter dependency: FQDN-based network rules (the fix for 587/8080) require the firewall to resolve those FQDNs, which means the client's DNS queries must reach the firewall's DNS proxy. Here the app servers point at 10.10.3.4/10.10.3.5, so the firewall never sees the queries and cannot refresh the IPs - the rule will work until the cached IP goes stale, then break intermittently. That is the trap hidden in this design.
Evidence to gather: firewall application-rule log lines for 587/8080 (absent), network-rule log lines (absent), and a packet capture on the app server confirming SYN-SENT with no response.
2. Propose a working design for smtp.contoso.com:587 and payments.contoso.com:8080 that does not weaken the egress control.
Read the worked answer
Option A - enable the firewall DNS proxy and use FQDN-based network rules (recommended).
- Enable DNS proxy on Azure Firewall and set the app servers' DNS to the firewall private IP. The NSG must allow UDP/TCP 53 to 10.0.0.4; keeping 10.10.3.4/5 as a secondary is fine for internal names but the firewall must be the resolver for external FQDNs.
- Replace the two failing application rules with network rules: source 10.21.0.0/24 -> FQDN smtp.contoso.com, port 587; and FQDN payments.contoso.com, port 8080, both next hop Allow.
- Keep api.contoso.com as an application rule (HTTPS/SNI filtering is stronger than IP allowlisting).
- Keep the default deny and the NSG as a second layer; the NSG should still only permit 443/587/8080 to 10.0.0.4.
Option B - publish static IPs. Ask the providers for stable egress IP ranges and use plain IP network rules. Cheapest, but breaks when the provider changes ranges, and it is a weaker control (anyone on that IP/port passes).
Option C - SNI-aware proxy or third-party NVA for protocols the firewall cannot filter. Higher operational cost; only justified if the provider refuses both A and B.
State the trade-off plainly: application rules give hostname-level control for HTTP/S only; anything else degrades to IP-based control unless you add a proxy.
3. The team wants the app servers to reach only Contoso's own storage account, not any Azure Storage endpoint. What is the correct control and what must be verified?
Read the worked answer
The Storage service tag is a service-wide aggregate and is the wrong control here. It covers every storage account in the region/cloud, so it permits data exfiltration to any attacker-controlled account.
Correct design:
- Put a private endpoint on stcontoso01 in a hub subnet and force the app servers to use the private IP path; resolve through the linked private DNS zone (or hub forwarder). Egress then stays inside the VNet and never traverses the firewall's internet path - the NSG/UDR combination does not even need a public rule.
- Keep
publicNetworkAccess= Disabled (or firewall-restricted to named ranges) so the private path cannot be bypassed by a client that resolves the public name. - If a public path is genuinely required, allow the specific public IP of the storage account in a network rule and re-check that IP after any platform change; do not use the Storage tag.
Verify:
- From the app server,
nslookup stcontoso01.blob.core.windows.netreturns the private endpoint IP; if it returns a public IP, DNS is the gap, not the firewall. - Effective routes on the app NIC cover the private endpoint subnet; a correct IP with no route fails identically to a blocked flow.
- Azure Storage diagnostic logs show requests arriving via the private endpoint (and
203.0.113.x-style public callers do not appear). - Test the negative case: from the app server, attempt an upload to a different storage account's public endpoint and confirm it is denied by the firewall/NSG - a control you have not tested negatively is not a control.