Networking
Azure NSG, UDR and Firewall: diagnose blocked traffic before adding a rule
A production runbook for qualifying blocked Azure traffic by separating NSG, UDR, Azure Firewall, DNS, effective routes, logs and rollback before opening access too broadly.
Blocked application traffic in Azure often turns into the same request: “add an NSG rule” or “open the firewall so we can test”. That is quick, but it is rarely a diagnosis. Between an unexpected effective route, a UDR pointing to an appliance, a subnet NSG, a NIC NSG, Azure Firewall, incorrect DNS resolution or an identity calling the wrong endpoint, a missing rule is only one hypothesis.
The use case is a workload in an Azure spoke that can no longer reach an internal dependency or a privately exposed PaaS service. The application may have changed, a route may have been updated, a central firewall may be filtering the flow, or an NSG may have been hardened. The runbook goal is to prove where the flow stops before adding an exception, then validate that the correction is narrow and reversible.
Name the exact flow
A network incident rarely starts with enough detail. “The application cannot reach the API” is not enough to change a rule. Describe the flow as an operational object: source, destination, port, protocol, environment, application identity and expected path.
Flow to qualify
Source: subnet-app-prod / vmss-api-prod / private IP 10.42.12.18
Destination: api.internal.example.net / expected private IP 10.55.4.20
Protocol: TCP
Port: 443
Direction: application spoke to service hub
Observed window: last 30 minutes
Recent change: new UDR on subnet-app-prod
Evidence required before exception
DNS resolution from the source
Effective route from the NIC or subnet
Effective NSG decision
Azure Firewall or appliance logs
Application test with correlation ID This contract avoids broad openings such as “source any to destination any on 443”. It also forces the team to separate naming, routing, filtering and service behavior.
Check DNS before routing
If the destination is an FQDN, the first question is simple: does the source resolve the expected address? Many network incidents are actually resolution incidents: missing private zone link, absent forwarder, public suffix resolved from the wrong place or stale local DNS cache.
From the source network
nslookup api.internal.example.net
nslookup api.internal.example.net <expected-dns-resolver>
Compare
IP returned from the application source
Expected IP from the runbook or inventory
TTL and local cache
CNAME chain for PaaS or private endpoint services
Resolver used by the VM, container or platform Changing an NSG rule while the name points to a public address or an old private IP only adds noise. The flow must first target the right destination.
Read the effective route
The route shown in a diagram is not enough. In Azure, the decision depends on system routes, peering, UDRs, propagated routes, the source subnet and sometimes forced tunneling through Azure Firewall or a network virtual appliance. Read the effective route from the resource that emits the traffic.
Effective route check
Source: workload NIC or subnet
Destination: resolved dependency IP
Questions
Does the destination use VirtualNetwork, Internet, VirtualAppliance or None?
Is a more specific UDR taking precedence?
Does the next hop match the expected firewall?
Does peering allow forwarded traffic when needed?
Is the return path symmetric or at least allowed? If the effective route sends traffic to a central firewall, diagnosis moves to that firewall. If it goes to Internet while the destination should be private, the likely correction is DNS, routing or peering, not an application exception.
Separate subnet NSG and NIC NSG
An NSG can filter at subnet level and at network interface level. Both decisions matter. An allow on the subnet does not compensate for a more specific deny on the NIC, and the reverse is also true. The right check is based on effective rules, not only Terraform files or naming conventions.
For the source -> destination flow
Source subnet NSG: applied rule, priority, action
Source NIC NSG: applied rule, priority, action
Destination subnet NSG if Azure workload: applied rule, priority, action
Destination NIC NSG if VM: applied rule, priority, action
Watch for
Lower priority number means higher precedence
Overbroad service tag
Historical deny rule
Ephemeral port confused with destination port
Return flow blocked by an external stateful device Azure NSGs are stateful for allowed flows, but that does not remove the need to check return traffic when an appliance or firewall is involved. The block may sit somewhere other than the first NSG you inspect.
Use logs as evidence, not decoration
NSG flow logs, Azure Firewall logs and application logs should answer one precise question: was the packet seen, allowed, denied, translated or ignored? Missing logs are also a signal, provided the team knows which component should have seen the flow.
let Window = 2h;
let SourceIp = "10.42.12.18";
let DestinationIp = "10.55.4.20";
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category in ("AzureFirewallNetworkRule", "AzureFirewallApplicationRule")
| where msg_s has SourceIp or msg_s has DestinationIp
| project TimeGenerated, Category, msg_s, Resource
| order by TimeGenerated desc If the firewall shows an explicit deny, a targeted firewall rule may be the correction. If the firewall sees nothing while the effective route points to it, check the next hop, peering, appliance path, route table or log collection before opening a rule.
Build the smallest useful exception
Once the block is proven, keep the exception close to the qualified flow. A broad temporary rule often becomes permanent because it “works”. An operable rule needs an owner, a reason, a duration when temporary, and a validation check.
Targeted exception
Name: allow-app-prod-to-api-internal-443
Source: 10.42.12.0/24 or precise application group
Destination: 10.55.4.20/32 or controlled FQDN tag
Protocol: TCP
Port: 443
Action: Allow
Priority: documented and not masking a critical deny
Owner: application or platform team
Ticket: related INC or CHG
Expiration: mandatory for temporary exception
Validation
Test from the real source
Observe allow log
Application metric back to expected level
No widening to unrelated destinations The key point is not only that the flow works. The team also needs to prove that the opening does not cover another case and can be removed without surprise.
Decide between route, rule and rollback
Not every correction has the same meaning. Adding a rule may be right when an explicit deny blocks a legitimate flow. Rolling back a UDR may be cleaner when a route table diverted an entire subnet. Fixing DNS may be required when the flow targets the wrong address.
Finding
DNS returns an unexpected IP
Decision: fix zone, VNet link or forwarder
Validation: correct resolution from the source
Effective route points to the wrong next hop
Decision: correct or roll back UDR / peering / propagation
Validation: expected next hop and successful application test
Explicit NSG deny on the expected flow
Decision: minimal NSG rule or priority correction
Validation: effective rule allow and matching logs
Explicit Azure Firewall deny
Decision: targeted firewall rule with owner
Validation: allow log followed by application success
No component sees the flow
Decision: return to source test, agent, host firewall or DNS path
Validation: capture or log on the first expected component This matrix prevents choosing the fix by habit. The right change is the one that matches the first solid piece of evidence.
Keep the rule rollbackable
A network exception should have a rollback path as clear as an application deployment. Before changing anything, capture the previous state. After the correction, confirm that the symptom is gone and the rule was not created broader than necessary.
Before change
Export or capture NSG, route table or firewall policy
Record priority, source, destination, protocol, port
Link the change to the incident or change ticket
Define the return-to-normal test
Rollback
Remove temporary rule or restore previous priority
Restore previous UDR or route table if changed
Replay the test from the real source
Confirm logs return to expected behavior
Document root cause or remaining debt A network rollback is not a failure. It is what allows the team to test a correction without turning the incident into a poorly documented permanent change.
Conclusion
Before adding an Azure NSG or Firewall rule, prove the traffic path: resolved name, effective route, effective rules, filtering point logs and a test from the real source. This sequence separates DNS, UDR, NSG, firewall and application issues without opening access more broadly than needed.
The final decision should be readable: fix DNS if the name is wrong, roll back routing if the next hop is wrong, add a minimal exception if a deny is proven, or go back to the source test if no component sees the traffic. The goal is not to open quickly. The goal is to open precisely, validate, and be able to close again.