Azure Virtual Network Security: A Practical Guide for Network Engineers — AzureNetSec
VNet Security

Azure Virtual Network Security: A Practical Guide for Network Engineers

VNet design is where most Azure security problems start. Flat networks, overly permissive NSGs, and uncontrolled peering are the issues we see most often in real environments. This guide covers how to get it right from the ground up.

The Short Answer

A well-designed Azure VNet is built around three principles:

  • Segmentation — separate workloads into dedicated subnets so you can apply distinct security policies to each
  • Least privilege — default to deny, explicitly allow only the traffic you need
  • Defense in depth — layer NSGs at the subnet level, add NIC-level rules for sensitive VMs, and route internet-bound traffic through Azure Firewall

Most VNet security failures don't come from sophisticated attacks. They come from flat network designs and NSG rules that were never tightened after initial deployment.

VNet Design Fundamentals

A Virtual Network (VNet) in Azure is your private, isolated network boundary in the cloud. Everything that runs inside a VNet is isolated from the internet and from other VNets by default — unless you explicitly open it up.

The most important design decision you'll make is how to segment your VNet into subnets. Get this right early and security policies become easy to apply and maintain. Get it wrong and you'll spend years trying to retrofit controls onto a flat network.

Subnet Segmentation Strategy

The right approach is to create a dedicated subnet for each distinct workload tier or security boundary. A typical 3-tier application in Azure should look like this:

VNet: 10.0.0.0/16 Web Subnet 10.0.1.0/24 App Gateway WAF enabled Web VMs + NSG: 443 in only NSG on subnet App Subnet 10.0.2.0/24 App VMs No public IPs Port 8080 from web only NSG on subnet Data Subnet 10.0.3.0/24 SQL / Storage No public IPs Port 1433 from app only NSG on subnet Internet →

Notice that each subnet has its own NSG, and the traffic rules between subnets are explicit and minimal. The app subnet only accepts traffic from the web subnet on port 8080. The data subnet only accepts traffic from the app subnet on port 1433. Nothing else gets through.

Subnet Sizing

Azure reserves 5 IP addresses per subnet (the first 4 and the last), so a /24 subnet gives you 251 usable addresses. Plan your subnets larger than you think you need — it's painful to resize a subnet that has resources deployed in it.

A practical sizing guide:

  • /28 (11 usable) — small dedicated subnets like Azure Bastion (AzureBastionSubnet) or VPN Gateway (GatewaySubnet)
  • /26 (59 usable) — small workload subnets with a handful of VMs
  • /24 (251 usable) — standard workload subnet, good default for most tiers
  • /23 (507 usable) — large workload subnets like AKS node pools
Common Mistake

Don't create one giant subnet and put everything in it. A flat /16 with all workloads in the same subnet means a single misconfigured NSG rule can expose everything. Segment first — it's much harder to do after deployment.

NSG Design Best Practices

NSGs are the primary enforcement mechanism inside a VNet. Applied correctly they give you granular east-west and north-south traffic control. Applied carelessly they become a false sense of security with an Allow Any Any rule sitting at priority 100.

Apply NSGs at the Subnet Level First

Always start with subnet-level NSGs. They apply to everything in the subnet and are easier to manage than NIC-level rules spread across individual VMs. Add NIC-level NSGs only when you need to differentiate security policy within a subnet — for example, a jumpbox VM that needs different inbound rules from the other VMs in the same subnet.

The Allow/Deny Rule Pattern

Every NSG should follow this structure — specific allows first, explicit deny-all at the end:

Recommended NSG rule pattern
Priority | Direction | Name | Source | Dest Port | Action ---------|-----------|------------------------|----------------|-----------|------- 100 | Inbound | Allow-LB-Health | AzureLoadBalancer | Any | Allow 200 | Inbound | Allow-App-From-Web | 10.0.1.0/24 | 8080 | Allow 300 | Inbound | Allow-Mgmt-From-Bastion| 10.0.4.0/27 | 22,3389 | Allow 4000 | Inbound | Deny-All-Inbound | Any | Any | Deny 100 | Outbound | Allow-To-Data | Any | 1433 | Allow 200 | Outbound | Allow-To-Azure-Monitor | Any | 443 | Allow 4000 | Outbound | Deny-All-Outbound | Any | Any | Deny
Pro Tip

Use Service Tags instead of IP addresses wherever possible. Tags like AzureLoadBalancer, AzureMonitor, and Storage automatically stay current as Microsoft adds new IPs to those services. Hard-coded IPs in NSG rules break silently when Microsoft rotates infrastructure.

Application Security Groups (ASGs)

ASGs let you group VMs by role and write NSG rules that reference the group rather than individual IP addresses. As your environment scales this becomes essential — maintaining rules with explicit IP lists for 50 web VMs is error-prone and fragile.

Instead of:

Source: 10.0.1.4, 10.0.1.5, 10.0.1.6, 10.0.1.7 Dest Port: 8080 Allow

You write:

Source: ASG-WebServers Dest Port: 8080 Allow

When you add a new web VM, you just assign it to the ASG-WebServers group. The NSG rule automatically covers it — no rule changes required.

VNet Peering: The Security Trap Most Teams Fall Into

VNet peering connects two VNets so resources in each can communicate as if they're on the same network. It's fast, cheap, and widely used. It's also one of the most common sources of unintended lateral movement in Azure environments.

The Problem with Peering

When you peer two VNets, all subnets in both VNets can communicate with each other by default — unless NSGs explicitly block the traffic. Most teams set up peering to allow one specific workload to communicate, then forget that they've effectively opened a path between two entire networks.

Security Risk

Peering a production VNet with a dev/test VNet is one of the most common misconfigurations we see. A developer's compromised machine in the dev VNet now has a direct network path to production resources — unless your NSGs are tight enough to stop it.

Peering Security Checklist

  • Never peer dev/test to production without Azure Firewall between them to inspect and filter traffic
  • Disable gateway transit unless you specifically need peered VNets to use a shared VPN/ExpressRoute gateway
  • Audit peering settings — confirm AllowForwardedTraffic and AllowGatewayTransit are set intentionally, not left at defaults
  • Apply NSGs on peered subnets that explicitly limit which source VNets and ports are allowed in

Hub-Spoke as the Safer Alternative

For environments with multiple VNets, a hub-spoke topology with Azure Firewall in the hub is far safer than a mesh of direct VNet peerings. All spoke-to-spoke traffic is routed through the firewall, giving you centralized inspection and logging instead of relying on NSGs alone to prevent lateral movement.

Private Endpoints: Eliminating Public Exposure for Azure Services

By default, Azure PaaS services like Storage, SQL Database, and Key Vault are accessible over public internet endpoints. Even with firewall rules restricting access to your VNet's IP ranges, the traffic still traverses the public internet. Private Endpoints change this.

A Private Endpoint creates a private IP address inside your VNet that maps directly to a specific Azure service. Traffic from your VMs to that service never leaves the Microsoft network backbone — it stays entirely private.

When to Use Private Endpoints

  • Any PaaS service holding sensitive data — Storage accounts, SQL databases, Key Vault, Cosmos DB
  • Any environment with compliance requirements (PCI-DSS, HIPAA) — Private Endpoints are often a requirement, not just best practice
  • Any environment where you want to completely eliminate public internet exposure for backend services
Quick Win

Once you create a Private Endpoint for a service, go back and disable public network access on that service entirely. A Private Endpoint with public access still enabled only halves your attack surface — disabling public access removes it completely.

The Most Common VNet Misconfigurations

After auditing dozens of Azure environments, these are the issues we see most consistently:

MisconfigurationRiskFix
Flat VNet with one subnet for everythingBlast radius is entire VNet if one workload is compromisedSegment into workload-specific subnets
NSG with Allow Any Any at priority 100Effectively no network security controlsRewrite with explicit allows + deny-all at the end
Public IPs on backend VMsDirect internet exposure, bypasses all perimeter controlsRemove public IPs, use Bastion or Azure Firewall DNAT for access
Unrestricted VNet peering to dev/testLateral movement path from dev to productionAdd Azure Firewall between peered VNets or remove the peering
PaaS services with public endpointsData accessible over internet even with VNet service endpointsMigrate to Private Endpoints and disable public access
No NSG flow logs enabledZero visibility into what traffic is actually flowingEnable NSG flow logs to Log Analytics or Storage
Overly broad IP ranges in NSG rulesAllows more traffic than intendedTighten source/destination ranges to minimum required

Logging and Visibility

A VNet with perfect NSG rules and no logging is still flying blind. You need visibility into what traffic is actually flowing — both for security monitoring and for debugging when your NSG rules accidentally block something legitimate.

Enable NSG Flow Logs

NSG Flow Logs capture information about IP traffic flowing through your NSGs — source/destination IP, port, protocol, and whether the traffic was allowed or denied. Enable them on every NSG and send logs to a Log Analytics workspace for querying and alerting.

Enable NSG flow logs via Azure CLI
az network watcher flow-log create \ --location eastus \ --name myNSGFlowLog \ --nsg myNSG \ --storage-account myStorageAccount \ --enabled true \ --format JSON \ --log-version 2 \ --retention 30

Microsoft Defender for Cloud

Enable Defender for Cloud's Defender for Servers and Defender for DNS plans across your subscriptions. These provide adaptive network hardening recommendations — Defender analyzes your actual traffic patterns and recommends NSG rules that are tighter than your current configuration based on what it observes.

Key Takeaways

What to remember from this article

  • Segment early — create dedicated subnets per workload tier from the start, not after deployment
  • NSG rule order matters — specific allows at low priority numbers, explicit deny-all at 4000
  • Use ASGs for any environment with more than a handful of VMs — IP-based rules don't scale
  • VNet peering is not inherently secure — NSGs must explicitly control cross-VNet traffic, especially dev-to-prod
  • Private Endpoints + disabled public access is the gold standard for PaaS service security
  • Enable NSG Flow Logs on every NSG — you can't defend what you can't see