---
title: "Control Traffic with Network Security Groups"
description: "Create and manage Azure NSG rules, service tags, and application security groups to control inbound and outbound traffic using Azure CLI."
canonical: "https://adamtheautomator.com/control-traffic-network-security-groups/"
---

# Control Traffic with Network Security Groups

> Create and manage Azure NSG rules, service tags, and application security groups to control inbound and outbound traffic using Azure CLI.

Source: https://adamtheautomator.com/control-traffic-network-security-groups/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Control Traffic with Network Security Groups](https://adamtheautomator.com/wp-content/uploads/2026/02/featured_image-17.webp)

# Control Traffic with Network Security Groups

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)18 February 20265 min. read

Categories: [Cloud](/category/cloud/)

Tags:[Azure](/tag/azure/)[Azure CLI](/tag/azure-cli/)

Table of Contents

*   [What NSGs Actually Do](#what-nsgs-actually-do)
*   [Prerequisites](#prerequisites)
*   [Create Your First NSG](#create-your-first-nsg)
*   [Add Custom Security Rules](#add-custom-security-rules)
*   [Use Service Tags Instead of IP Addresses](#use-service-tags-instead-of-ip-addresses)
*   [Group VMs with Application Security Groups](#group-vms-with-application-security-groups)
*   [Troubleshoot with IP Flow Verify](#troubleshoot-with-ip-flow-verify)
*   [What to Do Next](#what-to-do-next)

You’d think controlling network traffic in Azure would require a dedicated firewall appliance, complex routing tables, and a networking certification. It doesn’t. Azure [Network Security Groups](https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview) (NSGs) give you stateful, Layer 4 traffic filtering that you can attach directly to subnets or network interfaces–no extra infrastructure required.

## What NSGs Actually Do

An NSG is a set of allow/deny rules that Azure evaluates against a [5-tuple](https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview#security-rules): source IP, source port, destination IP, destination port, and protocol. Every packet hitting your resources gets checked against these rules in priority order, lowest number first. The moment a packet matches a rule, processing stops.

| Property | What It Controls |
| --- | --- |
| Priority | Order of evaluation (100-4096, lower = first) |
| Source/Destination | IP, CIDR, service tag, or application security group |
| Protocol | TCP, UDP, ICMP, or Any |
| Action | Allow or Deny |

The key detail that separates NSGs from traditional router ACLs: they’re stateful. Allow inbound traffic on port 443, and the return traffic flows back automatically. You don’t need a matching outbound rule for the response. That alone cuts your rule count roughly in half compared to stateless firewalls.

## Prerequisites

Before you start creating NSGs, confirm you have these ready:

*   An Azure subscription with at least [Network Contributor](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#network-contributor) permissions
    
*   Azure CLI installed and authenticated (`az login`)
    
*   A resource group and virtual network already deployed
    

Verify your CLI is ready:

```bash
az account show --query "{subscription:name, tenantId:tenantId}" --output table
```

## Create Your First NSG

Start by creating an NSG and attaching it to a subnet. Subnet-level attachment is the recommended approach–it applies rules consistently to every resource in that subnet without requiring per-VM configuration.

```
# Create the NSG
az network nsg create \
  --resource-group myResourceGroup \
  --name mySubnet-nsg \
  --location eastus

# Attach it to a subnet
az network vnet subnet update \
  --resource-group myResourceGroup \
  --vnet-name myVNet \
  --name mySubnet \
  --network-security-group mySubnet-nsg
```

Every new NSG comes with [default security rules](https://learn.microsoft.com/azure/virtual-network/network-security-groups-overview#default-security-rules) that you can’t delete but can override with higher-priority custom rules.

| Default Rule | Priority | What It Does |
| --- | --- | --- |
| AllowVNetInBound | 65000 | Permits traffic within the VNet and peered VNets |
| AllowAzureLoadBalancerInBound | 65001 | Allows health probes from Azure Load Balancer |
| DenyAllInBound | 65500 | Blocks everything else inbound |
| AllowVNetOutBound | 65000 | Permits outbound traffic within the VNet |
| AllowInternetOutBound | 65001 | Allows all outbound internet traffic |
| DenyAllOutBound | 65500 | Blocks everything else outbound |

That `AllowInternetOutBound` rule is worth noting. It means every VM can reach the internet by default–fine for dev environments, but you’ll want to override it in production with a deny rule at a lower priority number.

* * *

**_Warning: Attaching different NSGs to both a subnet and a NIC creates a double-filter. Inbound traffic must pass the subnet NSG first, then the NIC NSG. Outbound traffic goes the other direction. This layering sounds secure but usually just creates troubleshooting headaches._**

* * *

## Add Custom Security Rules

Now add rules that match your actual workload. Here’s how to allow inbound HTTPS traffic:

```bash
az network nsg rule create \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --name AllowHTTPS \
  --priority 100 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes '*' \
  --source-port-ranges '*' \
  --destination-address-prefixes '*' \
  --destination-port-ranges 443
```

And block direct SSH access from the internet:

```bash
az network nsg rule create \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --name DenySSHFromInternet \
  --priority 200 \
  --direction Inbound \
  --access Deny \
  --protocol Tcp \
  --source-address-prefixes Internet \
  --source-port-ranges '*' \
  --destination-address-prefixes '*' \
  --destination-port-ranges 22
```

Leave gaps between priority numbers (100, 200, 300) so you can insert rules later without renumbering your entire stack.

Verify your rules are in place:

```bash
az network nsg rule list \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --output table
```

This lists every rule in priority order, so you can confirm your custom rules sit above the default deny-all at 65500.

If you’re managing environments with hundreds of IP addresses, you’ll bump into the [1,000 rules per NSG limit](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-resource-manager-virtual-networking-limits). Augmented security rules help here–they let you specify up to 4,000 IP addresses or ranges in a single rule’s source or destination field, condensing what would be hundreds of individual rules into one. Use comma-separated values in `--source-address-prefixes` or `--destination-address-prefixes`:

```bash
az network nsg rule create \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --name AllowPartnerIPs \
  --priority 250 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes 10.1.0.0/24 10.2.0.0/24 192.168.5.0/24 \
  --destination-port-ranges 443
```

## Use Service Tags Instead of IP Addresses

Hardcoding IP addresses into NSG rules is a maintenance trap. Azure IP ranges change, and your rules go stale the moment Microsoft updates their infrastructure. [Service tags](https://learn.microsoft.com/azure/virtual-network/service-tags-overview) solve this by representing groups of IP prefixes that Azure maintains automatically.

| Service Tag | What It Covers |
| --- | --- |
| Internet | All public IP space outside the VNet |
| VirtualNetwork | VNet address space, peered VNets, on-premises via gateway |
| AzureCloud | All Azure datacenter IPs (regionable: `AzureCloud.EastUS`) |
| Storage | Azure Storage endpoints (regionable: `Storage.WestUS`) |
| Sql | Azure SQL Database endpoints |

Restrict a subnet to only reach Azure Storage in a specific region:

```bash
az network nsg rule create \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --name AllowStorageWestUS \
  --priority 300 \
  --direction Outbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes '*' \
  --source-port-ranges '*' \
  --destination-address-prefixes Storage.WestUS \
  --destination-port-ranges 443
```

* * *

**_Pro Tip: You can list all available service tags for your region with_** **_`az network list-service-tags --location eastus`_****_. The output is verbose, so pipe it through_** **_`jq`_** **_to filter what you need._**

* * *

## Group VMs with Application Security Groups

[Application Security Groups](https://learn.microsoft.com/azure/virtual-network/application-security-groups) (ASGs) let you write NSG rules based on workload roles instead of IP addresses. Tag your web servers as “WebServers” and your database servers as “DbServers,” then write rules referencing those groups. When you add a new database server, you add its NIC to the ASG–the rules apply automatically.

Create ASGs and use them in a rule:

```
# Create ASGs
az network asg create --resource-group myResourceGroup --name WebServers --location eastus
az network asg create --resource-group myResourceGroup --name DbServers --location eastus

# Allow web tier to reach database tier on SQL port
az network nsg rule create \
  --resource-group myResourceGroup \
  --nsg-name mySubnet-nsg \
  --name AllowWebToDb \
  --priority 400 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-asgs WebServers \
  --destination-asgs DbServers \
  --destination-port-ranges 1433
```

After creating the ASGs, assign your VM’s network interface to the appropriate group:

```
# Add a VM's NIC to the WebServers ASG
az network nic ip-config update \
  --resource-group myResourceGroup \
  --nic-name myWebVM-nic \
  --name ipconfig1 \
  --application-security-groups WebServers
```

Deploy a new web server next month? Add its NIC to the `WebServers` ASG and your existing rules apply immediately. No rule edits, no IP address hunting.

ASGs have two constraints worth knowing: they’re [scoped to a single virtual network](https://learn.microsoft.com/azure/virtual-network/application-security-groups#constraints) (no spanning across peered VNets), and each subscription supports up to 3,000 ASGs.

## Troubleshoot with IP Flow Verify

You configured your rules, but traffic still isn’t flowing. Before you start reading through dozens of rules manually, use [IP Flow Verify](https://learn.microsoft.com/azure/network-watcher/ip-flow-verify-overview) in Azure Network Watcher. It tests a synthetic packet against all active NSG rules and tells you exactly which rule is allowing or denying traffic.

```bash
az network watcher test-ip-flow \
  --direction Inbound \
  --protocol Tcp \
  --local 10.0.0.4:443 \
  --remote 203.0.113.50:60000 \
  --vm myVM \
  --nic myVM-nic \
  --resource-group myResourceGroup
```

The output tells you `Access: Allow` or `Access: Deny` and names the specific rule responsible. No guessing, no manually tracing through rule priority chains.

For a broader view of all effective rules applied to a network interface, use [NSG Diagnostics](https://learn.microsoft.com/azure/network-watcher/nsg-diagnostics-overview). It aggregates default rules, subnet rules, and NIC rules into a single view–essential when you need to spot conflicts between layers.

* * *

**_Key Insight: Microsoft is retiring_** [**_NSG Flow Logs_**](https://learn.microsoft.com/azure/network-watcher/nsg-flow-logs-overview) **_in September 2027. New NSG Flow Log creation was disabled in June 2025. Migrate to_** [**_VNet Flow Logs_**](https://learn.microsoft.com/azure/network-watcher/vnet-flow-logs-overview) **_now–they cover traffic at the VNet level regardless of NSG attachment, and you configure them once per VNet instead of per NSG._**

* * *

## What to Do Next

You now have an NSG attached to a subnet, custom rules filtering traffic by port and protocol, service tags keeping your IP ranges current, and ASGs grouping your workloads by role. That covers the fundamentals.

From here, consider tightening your configuration. Override `AllowInternetOutBound` with explicit deny rules for production subnets. Set up [VNet Flow Logs](https://learn.microsoft.com/azure/network-watcher/vnet-flow-logs-overview) and connect them to [Traffic Analytics](https://learn.microsoft.com/azure/network-watcher/traffic-analytics) so you can see which VMs are talking to unexpected destinations. And if you’re running an N-tier architecture, create separate subnets and NSGs per tier so your web servers can’t directly reach your database subnet.

NSGs won’t replace a full [Azure Firewall](https://learn.microsoft.com/azure/firewall/overview) deployment for deep packet inspection or application-layer filtering. But for Layer 4 traffic control across your VNets, they’re the first thing you should configure–and often the only thing you need.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fcontrol-traffic-network-security-groups%2F&text=Control%20Traffic%20with%20Network%20Security%20Groups)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fcontrol-traffic-network-security-groups%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fcontrol-traffic-network-security-groups%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2026/04/featured_image-20.webp)

### [How to Secure Azure Service Accounts with Managed Identities](/secure-azure-managed-identities/)

Learn how to replace secret-based Azure service accounts with managed identities, grant least-privilege Azure RBAC access, validate token-based authentication,

![](https://adamtheautomator.com/wp-content/uploads/2026/02/featured_image-12.webp)

### [Prevent Azure VM Outages with Load Balancer Health Probes](/distribute-traffic-azure-load-balancer/)

Create a Standard Azure Load Balancer with the Azure CLI, configure health probes and backend pools, and distribute traffic across zone-redundant VMs.

![](https://adamtheautomator.com/wp-content/uploads/2026/02/featured_image-6.webp)

### [Replicate Data Across Zones with Azure NetApp Files](/replicate-data-across-zones-azure-netapp-files/)

Configure cross-zone replication for Azure NetApp Files to protect against availability zone failures with asynchronous replication and zero network transfer fees.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
