Stopping Lateral Movement in Azure: Securing Subnets with NSGs

Control and secure traffic inside an Azure virtual network by applying Network Security Groups (NSGs) at the subnet level.

Scenario

Your organisation recently migrated several internal applications into Azure. To simplify deployment, all workloads were placed inside a single virtual network with multiple subnets. During a routine security review, the security team discovered that every VM inside the VNET could freely communicate with every other VM, regardless of workload sensitivity.

This raised a major concern: if one VM were ever compromised, an attacker could move laterally across the network without resistance.

You’ve been asked to implement a solution that:

  • Prevents unrestricted communication between subnets
  • Allows only the traffic required for each workload
  • Enforces least‑privilege access
  • Uses Azure‑native controls that scale easily
  • Avoids exposing any VM to the public internet

Lab Objectives

  • Create a virtual network with multiple subnets
  • Deploy Windows and Linux virtual machines
  • Configure Azure Bastion for secure RDP/SSH access
  • Apply NSGs at the subnet level
  • Create custom rules to control traffic between subnets
  • Validate that only approved traffic is allowed

Prerequisites

  • An active Azure subscription
  • Permissions to create networking and compute resources
  • Basic understanding of Azure VNETs and NSGs

Create the Virtual Network and Subnets

Create a virtual network with the following subnets:

AzureBastionSubnet

  • Required for Azure Bastion
  • Must be named exactly: AzureBastionSubnet

PC Subnet

  • Hosts the Windows 11 client VM

Web Server Subnet

  • Hosts the Linux web server VM

After creation, verify that all three subnets appear under the VNET.

Deploy the Virtual Machines

Windows 11 VM

  • Deploy into the PC Subnet
  • No public IP address
  • Will be accessed via Azure Bastion (RDP)

Linux Web Server

  • Deploy into the Web Server Subnet
  • No public IP address
  • Will be accessed via Azure Bastion (SSH)
  • Install a simple web server such as Apache or Nginx

Once deployed, confirm both VMs are reachable through Bastion.

Configure Azure Bastion

  1. Create Azure Bastion in the AzureBastionSubnet
  2. Open each VM and select Connect → Bastion
  3. Use RDP (Windows) or SSH (Linux) to verify access
  4. Confirm that neither VM has a public IP assigned

This ensures secure access without exposing the VMs to the internet.

Create and Apply Subnet-Level NSGs

You will create two NSGs and associate them with the PC Subnet and Web Server Subnet.

NSG for PC Subnet

Rule NameSourceDestinationPortActionPurpose
Allow‑RDP‑From‑BastionBastion SubnetPC Subnet3389AllowEnable RDP via Bastion
Allow‑AzureLBAzure Load BalancerPC SubnetAnyAllowRequired by Azure services
Deny‑AllAnyAnyAnyDenyBlock all other traffic

Associate this NSG with the PC Subnet.

NSG for Web Server Subnet

Rule NameSourceDestinationPortActionPurpose
Allow‑SSH‑From‑BastionBastion SubnetWeb Server Subnet22AllowEnable SSH via Bastion
Allow‑HTTP‑From‑PCPC SubnetWeb Server Subnet80AllowAllow PC to access the web server
Allow‑AzureLBAzure Load BalancerWeb Server SubnetAnyAllowRequired by Azure services
Deny‑AllAnyAnyAnyDenyBlock all other traffic

Associate this NSG with the Web Server Subnet.

Validate Traffic Flow

Before applying NSGs, all VMs could communicate freely inside the VNET.

After applying NSGs:

  • Bastion → PC (RDP): Allowed
  • Bastion → Web Server (SSH): Allowed
  • PC → Web Server (HTTP): Allowed
  • Any other traffic: Denied

This enforces least‑privilege access and prevents lateral movement between workloads.

Conclusion

By applying NSGs at the subnet level, you’ve implemented a scalable and secure method for controlling traffic inside an Azure virtual network. This approach aligns with zero‑trust principles and ensures that only required communication paths remain open while all other traffic is blocked.

Lab Video