Microsoft Azure — Network Security Groups & ASGs
NSG rules, application security groups, service tags, and effective security rules..
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- ✓Azure subscription with contributor access, Azure CLI 2.50+, basic understanding of Azure networking (VNet, subnet), familiarity with bash or PowerShell, and a test VM or two to apply NSG rules.
Network Security Groups & ASGs is like having a specialized tool that handles nsg asg in the Microsoft cloud — you manage the configuration, Azure handles the infrastructure.
Azure is Microsoft's cloud computing platform offering over 200 services. This article covers network security groups & asgs with production-ready configurations, best practices, and hands-on examples.
Why Network Security Groups Are Not Optional
Network Security Groups (NSGs) are the first line of defense for any Azure virtual network. They act as a distributed, stateful firewall that filters traffic at the subnet or NIC level. In production, every subnet should have at least one NSG attached. Without NSGs, your VNet is wide open — any VM can reach any other VM, and inbound traffic from the internet is unrestricted by default. I've seen teams skip NSG configuration during rapid prototyping, only to be hit by lateral movement attacks after a breach. NSGs are free, easy to audit, and can prevent entire classes of incidents. The rule of thumb: default deny inbound, default allow outbound, and explicitly permit only what's necessary. This section sets the foundation for understanding how to build secure, scalable network policies.
az network nsg rule list before applying to production.NSG Rule Evaluation: Priority, Direction, and Flow
NSG rules are evaluated in priority order, lowest number first. Each rule has a direction (Inbound or Outbound), source/destination address prefixes, port ranges, and protocol. Rules are stateful — if you allow inbound traffic on port 443, the return traffic is automatically allowed regardless of outbound rules. This is a common point of confusion: you don't need a matching outbound rule for responses. However, outbound initiated traffic requires explicit outbound rules. In production, always reserve priority ranges: use 100-199 for critical allow rules, 200-299 for less critical, and 3000+ for deny rules. This prevents accidental overrides when adding new rules. Also, remember that NSG rules are evaluated per packet, not per connection — but statefulness means the first packet creates a flow entry.
Application Security Groups: Logical Grouping at Scale
Application Security Groups (ASGs) let you group VMs by application role — like 'web', 'app', or 'db' — and reference those groups in NSG rules instead of IP addresses. This decouples security from network topology. When you scale out or replace VMs, you just update the ASG membership; the NSG rules stay the same. In production, ASGs are essential for microservices architectures where IPs change frequently. For example, you can create a rule that allows traffic from the 'web' ASG to the 'app' ASG on port 8080. ASGs are regional and can span VNets if peered. However, they don't support external IPs or service tags — those still need explicit prefixes. Use ASGs for east-west traffic within your VNet.
Combining NSGs and ASGs for Defense in Depth
In production, you should attach NSGs at both subnet and NIC levels, and use ASGs for intra-application rules. The subnet NSG enforces boundary policies (e.g., deny all inbound from internet except to the web tier), while the NIC NSG applies per-role rules (e.g., allow only web tier to app tier). When both are attached, the NIC NSG is evaluated after the subnet NSG. Traffic must pass both to reach the VM. This layered approach prevents misconfigurations in one NSG from exposing the entire subnet. For example, if the subnet NSG accidentally allows all inbound, the NIC NSG can still block it. Use ASGs in the NIC NSG to keep rules clean. Always document which NSG is responsible for what — I've seen teams duplicate rules across both, leading to confusion.
Service Tags and Application Security Groups: When to Use Which
Service tags represent groups of Azure IP prefixes for services like AzureLoadBalancer, Internet, or Sql. They are used in NSG rules to allow or deny traffic from those services without hardcoding IP ranges. ASGs, on the other hand, represent your own application tiers. Use service tags for external Azure services (e.g., allow AzureLoadBalancer health probes) and ASGs for internal traffic between your VMs. Never use service tags for your own VMs — that's what ASGs are for. A common mistake is using the 'VirtualNetwork' service tag to allow all VNet traffic, which bypasses ASG-based segmentation. Instead, use ASGs to restrict traffic between tiers. For internet-facing rules, use the 'Internet' service tag, but combine with ASGs for the destination.
NSG Flow Logs: Debugging and Auditing Traffic
NSG flow logs capture information about IP traffic flowing through an NSG. They are stored in Azure Storage and can be analyzed with Traffic Analytics or third-party tools. In production, enable flow logs on critical NSGs to debug connectivity issues and detect anomalies. For example, if a VM can't reach the internet, flow logs will show whether the traffic was allowed or denied by the NSG. Flow logs are not real-time — expect a 1-2 minute delay. They also incur storage costs, so only enable on NSGs you actively monitor. Use Traffic Analytics to visualize flows and identify patterns like port scanning. I recommend enabling flow logs on all NSGs attached to production subnets, with a retention policy of 30 days.
Common NSG Anti-Patterns in Production
Over the years, I've seen several recurring mistakes with NSGs. First, using overly broad source/destination prefixes like '0.0.0.0/0' or 'Any' when a more specific range would do. This violates least privilege. Second, creating too many rules — NSGs have a limit of 1000 rules (including defaults). Use ASGs and service tags to reduce rule count. Third, not documenting rule purpose. A rule named 'AllowSomething' with no description is a maintenance nightmare. Fourth, applying NSGs only at subnet level and ignoring NIC level. This gives no per-VM granularity. Fifth, forgetting to update NSGs when adding new services. Always pair infrastructure-as-code with NSG changes. Finally, not testing NSG rules before production — use az network nsg rule list and test connectivity with a tool like tcping.
Automating NSG and ASG Management with Infrastructure as Code
Manual NSG management doesn't scale. Use Terraform, Bicep, or ARM templates to define NSGs and ASGs as code. This ensures consistency, auditability, and version control. For example, define an NSG with rules that reference ASGs by name. When you deploy a new VM, assign it to the appropriate ASG in the same template. This couples security with deployment. In production, I recommend using Bicep for its simplicity and modularity. Store NSG definitions in a separate module and reuse across environments. Use parameters for environment-specific values like allowed IP ranges. Always run what-if operations before applying changes to catch unintended rule modifications. CI/CD pipelines should validate NSG rules against a baseline to prevent drift.
Monitoring and Alerting on NSG Changes
NSG changes can have immediate security and connectivity impacts. You need to monitor them. Use Azure Policy to enforce that NSGs have required rules (e.g., deny all inbound from internet). Use Azure Monitor alerts on NSG rule changes via Activity Log. For example, create an alert when a rule with priority < 100 is created or modified. Also, monitor NSG flow logs for denied traffic spikes — that could indicate a misconfiguration or an attack. In production, I set up a dashboard showing top denied flows per NSG. Combine with Azure Sentinel for advanced threat detection. Remember that NSG changes are logged in the Activity Log with a 15-minute delay. For real-time detection, use Event Hubs and stream to a SIEM.
Troubleshooting NSG Connectivity Issues
When a VM can't connect, NSGs are often the culprit. Start by checking effective security rules: az network nic show-effective-nsg. This shows the combined rules from subnet and NIC NSGs. Look for a deny rule that matches the traffic. If you see an allow rule but traffic is still blocked, check for network virtual appliances (NVAs) or user-defined routes (UDRs) that might be routing traffic differently. Also verify that the destination VM's NSG allows inbound traffic. Use Network Watcher's IP flow verify to test a specific flow. For outbound issues, check if the source NSG allows outbound traffic to the destination. Remember that NSGs are stateful — if you allow inbound, outbound response is automatic. If you see asymmetric routes, NSGs might block return traffic.
NSG Best Practices for Multi-Tier Applications
For a typical web-app-db architecture, use separate subnets per tier, each with its own NSG. The web subnet NSG allows inbound HTTP/HTTPS from the internet (using service tag 'Internet') and outbound to the app subnet on the app port. The app subnet NSG allows inbound from the web ASG on the app port and outbound to the db subnet on the db port. The db subnet NSG allows inbound from the app ASG on the db port and denies all other inbound. Use ASGs to reference the tiers instead of IPs. This pattern scales: you can add more VMs to an ASG without changing NSG rules. Also, consider using Azure Firewall for centralized egress control and logging. NSGs are per-subnet/NIC, while Azure Firewall is a managed service that can inspect traffic at the VNet level.
Evolving Beyond NSGs: When to Use Azure Firewall or NVAs
NSGs are great for simple allow/deny rules, but they lack advanced features like application-level filtering, TLS inspection, or intrusion detection. For production environments with compliance requirements (PCI-DSS, HIPAA), consider Azure Firewall or a third-party NVA. Azure Firewall is a managed, stateful firewall with built-in threat intelligence and FQDN filtering. It can inspect outbound traffic and log all flows. NSGs still have a role — they provide per-subnet filtering at low cost. Use NSGs for east-west traffic within a VNet and Azure Firewall for north-south traffic (inbound from internet, outbound to internet). This hybrid approach balances cost and security. For example, use NSGs to allow web-to-app traffic, and Azure Firewall to restrict outbound to approved FQDNs.
NSG Diagnostics with Network Watcher: Pinpointing Rule Conflicts
Azure Network Watcher's NSG diagnostics tool lets you check and troubleshoot security rules applied to your Azure traffic through NSGs and Azure Virtual Network Manager. Instead of manually tracing through dozens of rules, you input source/destination IP, port, protocol, and direction, and the tool evaluates all applied security rules — including subnet NSG, NIC NSG, and Azure Virtual Network Manager security admin rules — and tells you exactly which rule allows or denies the traffic. It also shows the effective rule hierarchy, so you can see if a subnet NSG rule is being overridden by a NIC NSG rule or vice versa. In production, use NSG diagnostics as your first troubleshooting step for connectivity issues. It's faster than manually inspecting effective routes and NSG rules. Common findings: an NSG at the subnet level allows traffic but the NIC NSG denies it, or a Virtual Network Manager rule unexpectedly overrides a custom NSG rule. The tool also suggests remediation — you can add a new security rule directly from the diagnostic results page. This is especially useful for Azure Bastion connectivity issues, where misconfigured NSGs frequently block the Bastion subnet traffic.
Azure Policy for NSG and Flow Log Governance at Scale
Managing NSGs manually across dozens of subscriptions doesn't scale. Azure Policy provides built-in policies to enforce NSG configuration, ensure flow logs are enabled, and validate traffic analytics configuration. Key built-in policies include: 'Network Watcher flow logs should have traffic analytics enabled' (audits existing flow logs), 'Configure network security groups to use specific workspace, storage account and flow log retention policy for traffic analytics' (DeployIfNotExists — auto-configures flow logs on NSGs), and 'Configure network security groups to enable traffic analytics' (similar but doesn't overwrite existing settings). In production, assign these policies at the subscription or management group level to enforce consistent monitoring across all NSGs. Use the audit policy first to identify non-compliant NSGs, then create remediation tasks to auto-configure flow logs and traffic analytics. Policy assignments can target specific regions using parameters. Remediation tasks use managed identities with Contributor permissions on the target resources. Also enforce that NSGs have required rules (e.g., deny all inbound from internet) using custom policy definitions. This prevents configuration drift and ensures every new NSG is properly monitored from day one.
NSG Limits, Quotas, and Scaling Considerations
NSGs and ASGs have hard limits that affect production architectures. Each NSG can have up to 1000 security rules (including default rules). Each Azure subscription can have up to 200 ASGs per region. Each NIC can be associated with up to 20 ASGs. NSG flow logs have a throughput limit — in high-traffic subnets, flow logs may drop packets at extreme volumes. If you approach the 1000-rule limit, consolidate using ASGs (each ASG reference counts as one rule regardless of how many VMs are in the group) or service tags. Also use larger CIDR blocks instead of multiple individual IP rules. For high-traffic production subnets (>1 Gbps), consider VNet flow logs instead of NSG flow logs — they have higher throughput capacity. Azure Policy can alert when NSG rule counts approach limits. Monitor NSG rule count using Azure Resource Graph. If you exceed 20 ASGs per NIC, consider using Azure Firewall with application rule groups for role-based access instead. Plan your rule priority scheme early: use 100-499 for critical allow rules, 500-2999 for standard rules, 3000-4095 for deny rules. This leaves room to insert rules without renumbering existing ones.
| File | Command / Code | Purpose |
|---|---|---|
| create-nsg.sh | az network nsg create \ | Why Network Security Groups Are Not Optional |
| list-nsg-rules.sh | az network nsg rule list \ | NSG Rule Evaluation |
| create-asg.sh | az network asg create \ | Application Security Groups |
| attach-nsg-nic.sh | az network nic update \ | Combining NSGs and ASGs for Defense in Depth |
| service-tag-rule.sh | az network nsg rule create \ | Service Tags and Application Security Groups |
| enable-flow-logs.sh | az monitor flow-log create \ | NSG Flow Logs |
| test-nsg-connectivity.sh | tcping -t 5 10.0.1.4 8080 | Common NSG Anti-Patterns in Production |
| nsg-asg.bicep | param location string = resourceGroup().location | Automating NSG and ASG Management with Infrastructure as Cod |
| alert-nsg-change.sh | az monitor activity-log alert create \ | Monitoring and Alerting on NSG Changes |
| effective-rules.sh | az network nic show-effective-nsg \ | Troubleshooting NSG Connectivity Issues |
| multi-tier-nsg.sh | az network nsg rule create --nsg-name web-nsg --name AllowHTTP --priority 100 --... | NSG Best Practices for Multi-Tier Applications |
| azure-firewall-rule.sh | az network firewall policy rule-collection-group create \ | Evolving Beyond NSGs |
| nsg-diagnostics.sh | az network watcher test-nsg-diagnostics \ | NSG Diagnostics with Network Watcher |
| assign-nsg-policy.sh | az policy assignment create \ | Azure Policy for NSG and Flow Log Governance at Scale |
| check-nsg-limits.sh | az network nsg show \ | NSG Limits, Quotas, and Scaling Considerations |
Key takeaways
Common mistakes to avoid
3 patternsNot planning nsg asg properly before deployment
Ignoring Azure best practices for nsg asg
Overlooking cost implications of nsg asg
Interview Questions on This Topic
Explain Network Security Groups & ASGs and its use cases.
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Azure. Mark it forged?
8 min read · try the examples if you haven't