Skip to main content

Theoretical Foundation: Create and Configure Network Security Groups (NSGs) and Application Security Groups


1. Initial Intuition​

Imagine a modern office building. At the main entrance, there's a security guard who checks who can enter and who can leave, with a list of rules: "visitors only enter through the lobby", "suppliers can only go to the warehouse", "finance staff cannot access the IT server". Each floor can have its own additional rules.

A Network Security Group (NSG) is exactly this security guard: a set of rules that controls which network traffic can enter and exit resources in Azure. Each rule defines: where the traffic comes from, where it's going, which protocol and port, and whether it's allowed or blocked.

An Application Security Group (ASG) is an elegant extension of this concept: instead of writing rules based on individual IP addresses, you group VMs by function (such as "web servers", "database servers") and write rules using these groups. When a new VM joins the group, it automatically inherits all the rules associated with the group.


2. Context​

2.1 NSGs and ASGs in the Azure ecosystem​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

2.2 Why NSGs and ASGs exist​

Before NSGs, controlling network traffic in the cloud was done only with traditional firewalls on dedicated appliances. NSGs democratized network control by making it declarative, free (no additional cost beyond infrastructure), and manageable as code.

ASGs emerged to solve the scale problem: in environments with hundreds of VMs, maintaining rules based on individual IPs was impractical. An ASG decouples security identity (the group) from IP addressing.

2.3 What depends on NSGs​

  • SSH/RDP access to VMs: Controlled by NSG inbound rule
  • Communication between tiers (web, app, database): Controlled by rules between NSGs/ASGs
  • Azure Bastion: Requires specific rules in the Bastion subnet NSG
  • Load Balancer probes: Requires explicit permission from IP 168.63.129.16
  • Service Endpoints: Work in conjunction with NSG rules

3. Building the Concepts​

3.1 Anatomy of an NSG rule​

Each NSG rule has five mandatory attributes and one result:

AttributeDescriptionExample
PriorityNumber from 100 to 4096; lower number = higher priority100
NameUnique identifier of the rule in the NSGAllow-HTTP-Inbound
ProtocolTCP, UDP, ICMP or * (any)TCP
SourceIP, CIDR, Service Tag, or ASG where traffic comes fromInternet
DestinationIP, CIDR, Service Tag, or ASG destination10.0.1.0/24
Source Port RangeSource port (usually *)*
Destination Port RangeDestination port80, 443, 3389-3400
ActionAllow or DenyAllow
DirectionInbound or OutboundInbound

Why is Source Port Range usually *? TCP connections start with an ephemeral source port (chosen by the operating system, usually above 1024). You rarely know this port beforehand, so you use * at the source and specify only the destination port.


3.2 Default rules​

Every NSG is created with a set of default rules that cannot be deleted, only overridden by higher priority rules:

Default Inbound rules:

PriorityNameSourceDestinationPortAction
65000AllowVnetInBoundVirtualNetworkVirtualNetwork*Allow
65001AllowAzureLoadBalancerInBoundAzureLoadBalancer**Allow
65500DenyAllInBound***Deny

Default Outbound rules:

PriorityNameSourceDestinationPortAction
65000AllowVnetOutBoundVirtualNetworkVirtualNetwork*Allow
65001AllowInternetOutBound*Internet*Allow
65500DenyAllOutBound***Deny

Non-obvious behavior: By default, all traffic between VMs in the same VNet is allowed (AllowVnetInBound and AllowVnetOutBound). And all traffic outbound to the internet is also allowed. For secure environments, you need to add explicit Deny rules with priority lower than 65000 to override these defaults.


3.3 Service Tags: simplifying IP rules​

Service Tags are labels that represent sets of IP prefixes from Azure services. Instead of maintaining lists of IPs that change, you use the service tag and Microsoft automatically keeps the list updated.

Most used tags in NSGs:

Service TagRepresents
InternetAll traffic from/to the public internet
VirtualNetworkThe entire VNet and peered VNets
AzureLoadBalancerAzure Load Balancer probe IPs
AzureCloudAll Azure public IPs
StorageAzure Storage IPs (all endpoints)
SqlAzure SQL server IPs
AppServiceAzure App Service IPs
AzureActiveDirectoryAzure AD endpoint IPs
GatewayManagerVPN/ExpressRoute Gateway management IPs

3.4 Application Security Groups (ASGs)​

An ASG is an Azure object that groups NICs (network interfaces) from VMs. You then reference these groups in NSG rules instead of individual IPs.

Analogy: An ASG is like a "role" in a company. Instead of writing a rule saying "John, Mary and Peter can access the finance server", you say "employees with the 'Financial Analyst' role can access". When a new analyst is hired, just put them in the group and they automatically gain access.

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

3.5 ASG restrictions​

To use ASGs, there are important restrictions:

  • A NIC can be associated with multiple ASGs
  • All ASGs referenced in a rule must be in the same VNet
  • All ASGs used as source and destination in a rule must be in the same VNet
  • You cannot combine ASG with IP address in the same rule (source or destination needs to be one type: ASG, IP/CIDR, or Service Tag)

4. Structural View​

4.1 Traffic evaluation flow (double verification)​

When traffic reaches a VM, Azure evaluates two NSGs in sequence, in the correct order:

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

For Outbound traffic, the order is reversed: NIC NSG is evaluated first, then Subnet NSG.

Fundamental rule: For traffic to pass, both NSGs need to allow it. If either blocks it, the traffic is denied.


4.2 Where NSGs can be associated​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Best practice: Associate NSGs to subnets, not individual NICs. This is simpler to manage. Use NSG on NIC only for specific exceptions that the subnet NSG shouldn't cover.


5. Practical Operation​

5.1 Complete scenario: three-tier architecture​

Consider a three-tier application: Web, App and Database.

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

In this model:

  • NSG-Web is associated with the Web subnet and allows only HTTP/HTTPS from the internet
  • NSG-App allows only traffic on port 8080 from ASG-WebServers
  • NSG-DB allows only SQL (port 1433) from ASG-AppServers
  • Lateral movement between tiers is blocked by default

5.2 Effective Security Rules: effective rules diagnosis​

A powerful Azure feature is the ability to see the combined effective rules from NSGs on a specific NIC:

In the portal: VM NIC > Effective Security Rules

This shows rules from all associated NSGs (subnet + NIC) in a consolidated view, in evaluation order. It's the main tool for diagnosing why traffic is being blocked or allowed.


5.3 Network Watcher: IP Flow Verify​

For more direct connectivity diagnosis:

Azure Network Watcher > IP Flow Verify

You specify:

  • Source VM
  • Destination IP address
  • Port and protocol
  • Direction (inbound/outbound)

Azure simulates the flow and reports whether it would be allowed or denied, and which specific rule would be responsible for the decision.


6. Implementation Methods​

6.1 Azure Portal​

When to use: Initial creation, effective rules visualization, visual troubleshooting.

Create NSG: Resource Groups > + Create > Network Security Group

After creating, add rules in Settings > Inbound security rules or Outbound security rules.

Associate to subnet: Virtual Network > Subnets > [subnet] > Network security group

Limitation: Not scalable for multiple NSGs or complex rules.


6.2 Azure CLI​

Creating NSG:

az network nsg create \
--name NSG-Web \
--resource-group myRG \
--location eastus

Adding inbound rule:

# Allow HTTP and HTTPS from internet
az network nsg rule create \
--nsg-name NSG-Web \
--resource-group myRG \
--name Allow-HTTP-HTTPS \
--priority 100 \
--protocol Tcp \
--direction Inbound \
--source-address-prefixes Internet \
--source-port-ranges '*' \
--destination-address-prefixes '*' \
--destination-port-ranges 80 443 \
--access Allow

# Deny all other inbound (explicit)
az network nsg rule create \
--nsg-name NSG-Web \
--resource-group myRG \
--name Deny-All-Inbound \
--priority 4000 \
--protocol '*' \
--direction Inbound \
--source-address-prefixes '*' \
--source-port-ranges '*' \
--destination-address-prefixes '*' \
--destination-port-ranges '*' \
--access Deny

Associating NSG to a subnet:

az network vnet subnet update \
--vnet-name myVNet \
--name WebSubnet \
--resource-group myRG \
--network-security-group NSG-Web

Creating ASG:

az network asg create \
--name ASG-WebServers \
--resource-group myRG \
--location eastus

Associating VM NIC to an ASG:

az network nic update \
--name myVM-NIC \
--resource-group myRG \
--application-security-groups ASG-WebServers

Creating NSG rule with ASG as source and destination:

az network nsg rule create \
--nsg-name NSG-DB \
--resource-group myRG \
--name Allow-SQL-from-AppServers \
--priority 100 \
--protocol Tcp \
--direction Inbound \
--source-asgs ASG-AppServers \
--source-port-ranges '*' \
--destination-asgs ASG-DatabaseServers \
--destination-port-ranges 1433 \
--access Allow

Checking effective rules:

az network nic show-effective-nsg \
--name myVM-NIC \
--resource-group myRG \
--output table

6.3 Azure PowerShell​

# Create NSG
$nsg = New-AzNetworkSecurityGroup `
-Name "NSG-Web" `
-ResourceGroupName "myRG" `
-Location "eastus"

# Create rule and add to NSG
$rule = New-AzNetworkSecurityRuleConfig `
-Name "Allow-HTTP-HTTPS" `
-Protocol Tcp `
-Direction Inbound `
-Priority 100 `
-SourceAddressPrefix Internet `
-SourcePortRange '*' `
-DestinationAddressPrefix '*' `
-DestinationPortRange 80, 443 `
-Access Allow

$nsg.SecurityRules.Add($rule)
Set-AzNetworkSecurityGroup -NetworkSecurityGroup $nsg

# Create ASG
$asg = New-AzApplicationSecurityGroup `
-Name "ASG-WebServers" `
-ResourceGroupName "myRG" `
-Location "eastus"

# Associate NIC to ASG
$nic = Get-AzNetworkInterface `
-Name "myVM-NIC" `
-ResourceGroupName "myRG"

$nic.IpConfigurations[0].ApplicationSecurityGroups = @($asg)
Set-AzNetworkInterface -NetworkInterface $nic

6.4 Bicep​

// Application Security Groups
resource asgWeb 'Microsoft.Network/applicationSecurityGroups@2023-05-01' = {
name: 'ASG-WebServers'
location: location
}

resource asgApp 'Microsoft.Network/applicationSecurityGroups@2023-05-01' = {
name: 'ASG-AppServers'
location: location
}

resource asgDb 'Microsoft.Network/applicationSecurityGroups@2023-05-01' = {
name: 'ASG-DatabaseServers'
location: location
}

// NSG for Web tier
resource nsgWeb 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
name: 'NSG-Web'
location: location
properties: {
securityRules: [
{
name: 'Allow-HTTP-HTTPS'
properties: {
priority: 100
protocol: 'Tcp'
access: 'Allow'
direction: 'Inbound'
sourceAddressPrefix: 'Internet'
sourcePortRange: '*'
destinationAddressPrefix: '*'
destinationPortRanges: ['80', '443']
}
}
]
}
}

// NSG for Database tier with rule using ASG
resource nsgDb 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
name: 'NSG-DB'
location: location
properties: {
securityRules: [
{
name: 'Allow-SQL-from-App'
properties: {
priority: 100
protocol: 'Tcp'
access: 'Allow'
direction: 'Inbound'
sourceApplicationSecurityGroups: [{ id: asgApp.id }]
sourcePortRange: '*'
destinationApplicationSecurityGroups: [{ id: asgDb.id }]
destinationPortRange: '1433'
}
}
{
name: 'Deny-All-Inbound'
properties: {
priority: 4000
protocol: '*'
access: 'Deny'
direction: 'Inbound'
sourceAddressPrefix: '*'
sourcePortRange: '*'
destinationAddressPrefix: '*'
destinationPortRange: '*'
}
}
]
}
}

7. Control and Security​

7.1 Permissions to manage NSGs and ASGs​

OperationMinimum Role
Create/edit NSG and rulesNetwork Contributor
Associate NSG to subnetNetwork Contributor on VNet and NSG
Create/edit ASGNetwork Contributor
Associate NIC to ASGNetwork Contributor on NIC and ASG
View effective rulesReader + Network Contributor

7.2 Rules for Azure Load Balancer​

A common mistake in Load Balancer environments is blocking health probes. The Load Balancer uses IP 168.63.129.16 to check if VMs are healthy. If the NSG blocks this IP, the LB marks VMs as unhealthy and stops sending traffic to them.

The default rule AllowAzureLoadBalancerInBound (priority 65001) allows this, but if you have a Deny All rule with priority lower than 65001, it overrides the default.

Always explicitly include:

az network nsg rule create \
--nsg-name NSG-Web \
--resource-group myRG \
--name Allow-LB-HealthProbe \
--priority 150 \
--protocol '*' \
--direction Inbound \
--source-address-prefixes AzureLoadBalancer \
--source-port-ranges '*' \
--destination-address-prefixes '*' \
--destination-port-ranges '*' \
--access Allow

7.3 NSG Flow Logs​

NSG Flow Logs record information about IP traffic that passed or was blocked by NSGs. They are fundamental for auditing, forensics, and troubleshooting.

# Enable flow logs (requires Network Watcher and Storage Account)
az network watcher flow-log create \
--location eastus \
--name FlowLog-NSG-Web \
--nsg NSG-Web \
--resource-group myRG \
--storage-account mystorageaccount \
--enabled true \
--retention 7 \
--traffic-analytics true \
--workspace <log-analytics-workspace-id>

With Traffic Analytics enabled, you can visualize traffic patterns, top talkers, and blocked flows in a rich dashboard in Azure Monitor.


8. Decision Making​

8.1 NSG on Subnet vs NSG on NIC​

SituationBest choiceReason
Rules that apply to all VMs in a tierNSG on subnetSingle rule covers all VMs
Exception for a specific VM within the subnetAdditional NSG on NICDoesn't affect other VMs in the subnet
Simple environment with few VMsNSG on subnetLower operational complexity
VM that needs more restrictive rules than the subnetNSG on NIC in addition to subnetDual verification, more restrictive
Microsegmentation by workloadASGs + NSG on subnetRules based on function, not IP

8.2 IP/CIDR vs Service Tag vs ASG​

SituationUseReason
Traffic from/to internetService Tag InternetCovers all internet IPs
Communication between application tiersASGRules based on function, scales without change
Traffic from/to specific Azure servicesService Tag (e.g., Storage, Sql)Microsoft maintains updated IPs
Specific partner/customer IPIP/CIDRFixed and specific address
Group of VMs with same purposeASGEasier to maintain than IP lists

8.3 When to use ASGs mandatorily​

ASGs are especially necessary when:

  • The number of VMs in the group varies frequently (scale sets, automated deployments)
  • VM IPs are dynamically assigned (without static IPs)
  • The same VM needs to belong to multiple security groups
  • You want security rules to be defined by the security team independently of the infrastructure team managing IPs

9. Best Practices​

  • Associate NSGs with subnets, not NICs, to simplify management. Use NSGs on NIC only for specific exceptions.
  • Always include an explicit Deny All rule with high priority (e.g., 4000) instead of relying only on the default 65500 rule. This makes your intention clear and auditable.
  • Use Service Tags for Azure-to-Azure traffic instead of maintaining changing IP lists.
  • Use ASGs for microsegmentation instead of IPs when resources are dynamic or change frequently.
  • Enable NSG Flow Logs on all production NSGs for auditing and troubleshooting.
  • Don't block AzureLoadBalancer if there's a Load Balancer in the architecture.
  • Number priorities with intervals (100, 200, 300) to allow insertion of new rules without reorganization.
  • Name rules descriptively: Allow-HTTPS-from-Internet, Deny-SSH-from-All, Allow-SQL-from-AppTier.
  • Use resource tags on NSGs to identify owner, environment, and related workload.
  • Periodically review unnecessary rules using Network Watcher and Traffic Analytics to identify unused rules.

10. Common Errors​

ErrorWhy it happensHow to avoid
VMs out of health in Load BalancerDeny All rule with priority lower than 65001 blocks LB probesAlways include Allow AzureLoadBalancer with priority lower than Deny All
SSH/RDP blocked unexpectedlyDeny All rule overrides subnet AllowCheck priority order; use IP Flow Verify
ASG doesn't work between different VNetsASGs must be in the same VNetUse IPs/CIDRs for cross-VNet communication
Unwanted traffic allowed by defaultAllowVnetInBound allows all intra-VNet trafficAdd explicit Deny rules for microsegmentation
Rule with two source typesNSG doesn't accept ASG + IP in the same ruleSeparate into two distinct rules
NIC associated with ASG from another regionASG and NIC must be in the same regionCreate ASG in the same region as VMs
Flow Logs don't appearStorage Account in different region from Network WatcherUse Storage Account in the same region
Higher priority rule (lower number) blockingForgot that lower number = higher priorityAlways review priority order after adding rules

11. Operations and Maintenance​

11.1 Diagnosing connectivity​

Step 1: Use IP Flow Verify in Network Watcher to confirm if NSG is blocking.

Step 2: If blocked, use Effective Security Rules on the NIC to see which specific rule is denying.

Step 3: If allowed by NSG but traffic still doesn't reach, the issue may be in firewall within the VM (Windows Firewall, iptables) or routing.

Step 4: Use Connection Troubleshoot in Network Watcher for end-to-end diagnosis including latency and packet loss.


11.2 Monitoring NSGs with Azure Monitor​

# Create alert for NSG changes (via Activity Log)
az monitor activity-log alert create \
--name "NSG-rule-change-alert" \
--resource-group myRG \
--condition category=Administrative \
--condition operationName=Microsoft.Network/networkSecurityGroups/securityRules/write \
--action-group myActionGroup

Also configure alerts for:

  • Blocked flows above a threshold (Traffic Analytics)
  • Access attempts to sensitive ports (22, 3389) from unauthorized IPs

11.3 Important limits​

ResourceLimit
NSGs per subscription5,000
Rules per NSG1,000
NSGs per NIC1
NSGs per subnet1
ASGs per subscription3,000
ASGs per NIC20
ASGs per NSG rule (source + destination)10

12. Integration and Automation​

12.1 Azure Policy for NSG compliance​

# Built-in policy: Subnets without NSG should be audited
az policy assignment create \
--name "require-nsg-on-subnets" \
--policy "e71308d3-144b-4262-b144-efdc3cc90517" \
--scope "/subscriptions/<sub-id>"

Custom policy to deny creation of subnets without NSG:

{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks/subnets"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id",
"exists": false
},
{
"not": {
"field": "name",
"in": ["GatewaySubnet", "AzureFirewallSubnet", "AzureBastionSubnet"]
}
}
]
},
"then": {
"effect": "deny"
}
}

Note that some special subnets (GatewaySubnet, AzureFirewallSubnet, AzureBastionSubnet) don't support NSGs and must be excluded from the policy.


12.2 Terraform for NSG with ASG​

resource "azurerm_application_security_group" "web" {
name = "ASG-WebServers"
location = var.location
resource_group_name = var.resource_group
}

resource "azurerm_application_security_group" "db" {
name = "ASG-DatabaseServers"
location = var.location
resource_group_name = var.resource_group
}

resource "azurerm_network_security_group" "db_nsg" {
name = "NSG-DB"
location = var.location
resource_group_name = var.resource_group

security_rule {
name = "Allow-SQL-from-Web"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "1433"
source_application_security_group_ids = [azurerm_application_security_group.web.id]
destination_application_security_group_ids = [azurerm_application_security_group.db.id]
}

security_rule {
name = "Deny-All-Inbound"
priority = 4000
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}

13. Final Summary​

Essential concepts:

  • An NSG is a list of network security rules that control inbound and outbound traffic of Azure resources.
  • Each rule has priority, protocol, source, destination, port, and action (Allow/Deny). Lower priority number = higher precedence.
  • NSGs can be associated with subnets (protects all VMs) or NICs (protects a specific VM).
  • When both are associated, both are evaluated: for inbound, subnet NSG first; for outbound, NIC NSG first.
  • An ASG is a logical grouping of NICs that can be used as source or destination in NSG rules, eliminating the need to maintain IP lists.

Critical differences:

  • NSG on subnet vs NSG on NIC: Subnet covers all VMs; NIC covers only one. Both coexist and both must allow for traffic to pass.
  • Allow vs Deny: The first matching rule (by priority) is applied. The rest are ignored.
  • ASG vs Service Tag vs IP: ASG is for internal Azure resources grouped by function. Service Tag is for Azure services with Microsoft-managed IPs. IP/CIDR is for specific external addresses.
  • Default AllowVnetInBound: By default, all traffic between VMs in the same VNet is allowed. For microsegmentation, add explicit Deny rules.

What needs to be remembered:

  • NSGs on GatewaySubnet, AzureFirewallSubnet, and AzureBastionSubnet are not supported.
  • Always include Allow AzureLoadBalancer before any Deny All rule when there's a Load Balancer.
  • ASGs must be in the same VNet as associated NICs.
  • A NIC can belong to up to 20 ASGs.
  • Use IP Flow Verify and Effective Security Rules to diagnose connectivity issues.
  • NSG Flow Logs are essential for auditing and must be enabled in production.
  • Default rules (65000, 65001, 65500) cannot be deleted, only overridden with lower priorities.