🌐 Azure Inbound NAT Rules

Complete Configuration Guide with Visual Diagrams & CLI Commands

📋 Overview

Inbound NAT rules in Azure allow you to forward traffic from a specific port on the load balancer's frontend IP address to a specific port on a backend virtual machine. This enables direct access to individual VMs behind a load balancer.

Key Benefits:
  • Direct access to specific VMs for management purposes
  • Port forwarding for applications requiring unique ports
  • Simplified remote administration (RDP/SSH)
  • Cost-effective alternative to individual public IPs
graph TB A[Internet User] -->|Port 3389| B[Load Balancer Public IP] B -->|NAT Rule| C[Backend VM Port 3389] A2[Internet User] -->|Port 2201| B B -->|NAT Rule| D[Backend VM1 Port 22] A3[Internet User] -->|Port 2202| B B -->|NAT Rule| E[Backend VM2 Port 22] style B fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff style C fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style D fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style E fill:#28a745,stroke:#333,stroke-width:2px,color:#fff
Diagram Explanation:

This diagram illustrates the fundamental concept of inbound NAT rules. Multiple internet users can access different backend VMs through a single public IP address by using different port numbers:

  • Blue Box (Load Balancer Public IP): The single entry point that receives all incoming traffic from the internet
  • Green Boxes (Backend VMs): The target virtual machines that don't have direct public IP addresses
  • Port 3389: Direct RDP access to a Windows VM (1:1 port mapping)
  • Port 2201 → VM1:22: SSH access to Linux VM1 through a custom external port
  • Port 2202 → VM2:22: SSH access to Linux VM2 through a different external port
  • Key Benefit: Each VM gets unique access while sharing one public IP, reducing costs and complexity

🏗️ Architecture Components

graph TB subgraph "Azure Subscription" subgraph "Resource Group" subgraph "Virtual Network" subgraph "Subnet" VM1[Virtual Machine 1] VM2[Virtual Machine 2] VM3[Virtual Machine 3] end end LB[Load Balancer] PIP[Public IP Address] NSG[Network Security Group] NIC1[Network Interface 1] NIC2[Network Interface 2] NIC3[Network Interface 3] end end Internet[Internet] --> PIP PIP --> LB LB --> NIC1 LB --> NIC2 LB --> NIC3 NIC1 --> VM1 NIC2 --> VM2 NIC3 --> VM3 NSG -.-> VM1 NSG -.-> VM2 NSG -.-> VM3 style LB fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff style PIP fill:#ffc107,stroke:#333,stroke-width:2px,color:#000 style VM1 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style VM2 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style VM3 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff
Azure Architecture Components Explained:

This diagram shows the hierarchical structure and relationships of all Azure components involved in NAT rule configuration:

Resource Hierarchy:

  • Azure Subscription: Top-level billing and management boundary
  • Resource Group: Logical container that groups related resources for easy management and deletion
  • Virtual Network (VNet): Isolated network environment in Azure that acts like your private data center
  • Subnet: Network segment within the VNet where VMs are placed for organization and security

Network Components:

  • Public IP Address (Yellow): Internet-routable IP address that serves as the entry point from the internet
  • Load Balancer (Blue): Traffic distribution service that also handles NAT rule processing
  • Network Interfaces (NICs): Virtual network cards that connect VMs to the network infrastructure
  • Virtual Machines (Green): The actual compute resources hosting your applications
  • Network Security Group (NSG): Acts as a virtual firewall controlling inbound and outbound traffic

Traffic Flow:

  • Solid Lines: Direct network connections and traffic flow paths
  • Dotted Lines: Security policy enforcement (NSG rules apply to VMs)
  • Direction: Internet → Public IP → Load Balancer → NICs → VMs

Component Relationships

erDiagram RESOURCE-GROUP ||--o{ VIRTUAL-NETWORK : contains RESOURCE-GROUP ||--o{ LOAD-BALANCER : contains RESOURCE-GROUP ||--o{ PUBLIC-IP : contains RESOURCE-GROUP ||--o{ NSG : contains VIRTUAL-NETWORK ||--o{ SUBNET : contains SUBNET ||--o{ VIRTUAL-MACHINE : contains VIRTUAL-MACHINE ||--|| NETWORK-INTERFACE : has LOAD-BALANCER ||--|| FRONTEND-IP : has LOAD-BALANCER ||--o{ BACKEND-POOL : has LOAD-BALANCER ||--o{ NAT-RULE : has PUBLIC-IP ||--|| FRONTEND-IP : assigned-to BACKEND-POOL ||--o{ NETWORK-INTERFACE : contains NAT-RULE ||--|| NETWORK-INTERFACE : targets
Entity Relationship Diagram Explained:

This diagram shows the logical relationships between Azure components and how they depend on each other:

Relationship Types:

  • ||--o{ (One-to-Many): One parent can have multiple children (e.g., one Resource Group contains many Virtual Networks)
  • ||--|| (One-to-One): Direct exclusive relationship (e.g., each VM has exactly one Network Interface)

Key Relationships:

  • Resource Group as Container: All resources must belong to exactly one resource group
  • Network Hierarchy: VNet → Subnet → VM → Network Interface (nested containment)
  • Load Balancer Structure: Has one frontend IP, multiple backend pools, and multiple NAT rules
  • Critical Dependencies: NAT rules target specific network interfaces, creating direct VM access paths
  • Public IP Assignment: The public IP is assigned to the load balancer's frontend IP configuration

Configuration Impact:

  • Deletion Order: Understanding these relationships helps determine safe deletion order
  • Dependency Management: Some resources cannot be deleted if others depend on them
  • Configuration Validation: Azure validates these relationships during resource creation

📋 Prerequisites

Before You Begin: Ensure you have Azure CLI installed and are logged in to your Azure subscription.

1Install and Login to Azure CLI

Install Azure CLI (if not already installed)
# Windows (using winget)
winget install Microsoft.AzureCLI

# macOS (using Homebrew)
brew install azure-cli

# Linux (Ubuntu/Debian)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
Login to Azure
az login

# Set your subscription (if you have multiple)
az account set --subscription "Your-Subscription-Name-or-ID"

# Verify your current subscription
az account show --output table

2Set Environment Variables

Define Configuration Variables
# Resource naming variables
RESOURCE_GROUP="rg-nat-demo"
LOCATION="eastus"
VNET_NAME="vnet-nat-demo"
SUBNET_NAME="subnet-backend"
LB_NAME="lb-nat-demo"
PUBLIC_IP_NAME="pip-nat-demo"
NSG_NAME="nsg-nat-demo"

# Network configuration
VNET_PREFIX="10.0.0.0/16"
SUBNET_PREFIX="10.0.1.0/24"

# VM configuration
VM_SIZE="Standard_B2s"
ADMIN_USERNAME="azureuser"
VM_IMAGE="Ubuntu2204"

⚙️ Step-by-Step Configuration

1Create Resource Group

Create Resource Group
az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION \
    --tags Environment=Demo Purpose=NAT-Rules

2Create Virtual Network and Subnet

Create Virtual Network
az network vnet create \
    --resource-group $RESOURCE_GROUP \
    --name $VNET_NAME \
    --address-prefix $VNET_PREFIX \
    --subnet-name $SUBNET_NAME \
    --subnet-prefix $SUBNET_PREFIX \
    --location $LOCATION

3Create Network Security Group

Create NSG with Rules
# Create NSG
az network nsg create \
    --name $NSG_NAME \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION

# Allow SSH access through NAT rules
az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name Allow-SSH-NAT \
    --priority 1000 \
    --protocol Tcp \
    --destination-port-ranges 22 \
    --access Allow \
    --direction Inbound

# Allow RDP access through NAT rules
az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name Allow-RDP-NAT \
    --priority 1010 \
    --protocol Tcp \
    --destination-port-ranges 3389 \
    --access Allow \
    --direction Inbound

# Allow custom application ports
az network nsg rule create \
    --resource-group $RESOURCE_GROUP \
    --nsg-name $NSG_NAME \
    --name Allow-HTTP \
    --priority 1020 \
    --protocol Tcp \
    --destination-port-ranges 80 \
    --access Allow \
    --direction Inbound

4Create Public IP Address

Create Static Public IP
az network public-ip create \
    --name $PUBLIC_IP_NAME \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --allocation-method Static \
    --sku Standard \
    --tier Regional

5Create Load Balancer

Create Load Balancer with Frontend IP
az network lb create \
    --name $LB_NAME \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --frontend-ip-name LoadBalancerFrontend \
    --public-ip-address $PUBLIC_IP_NAME \
    --backend-pool-name BackendPool \
    --sku Standard

6Create Virtual Machines

Create Multiple VMs for NAT Rule Demo
# Create VM1
az vm create \
    --name vm-web-01 \
    --resource-group $RESOURCE_GROUP \
    --image $VM_IMAGE \
    --size $VM_SIZE \
    --admin-username $ADMIN_USERNAME \
    --generate-ssh-keys \
    --vnet-name $VNET_NAME \
    --subnet $SUBNET_NAME \
    --nsg $NSG_NAME \
    --public-ip-address "" \
    --no-wait

# Create VM2
az vm create \
    --name vm-web-02 \
    --resource-group $RESOURCE_GROUP \
    --image $VM_IMAGE \
    --size $VM_SIZE \
    --admin-username $ADMIN_USERNAME \
    --generate-ssh-keys \
    --vnet-name $VNET_NAME \
    --subnet $SUBNET_NAME \
    --nsg $NSG_NAME \
    --public-ip-address "" \
    --no-wait

# Create VM3
az vm create \
    --name vm-web-03 \
    --resource-group $RESOURCE_GROUP \
    --image $VM_IMAGE \
    --size $VM_SIZE \
    --admin-username $ADMIN_USERNAME \
    --generate-ssh-keys \
    --vnet-name $VNET_NAME \
    --subnet $SUBNET_NAME \
    --nsg $NSG_NAME \
    --public-ip-address "" \
    --no-wait

# Wait for all VMs to be created
az vm wait --resource-group $RESOURCE_GROUP --name vm-web-01 --created
az vm wait --resource-group $RESOURCE_GROUP --name vm-web-02 --created
az vm wait --resource-group $RESOURCE_GROUP --name vm-web-03 --created

7Add VMs to Load Balancer Backend Pool

Add Network Interfaces to Backend Pool
# Get the network interface IDs
VM1_NIC_ID=$(az vm show --name vm-web-01 --resource-group $RESOURCE_GROUP --query 'networkProfile.networkInterfaces[0].id' -o tsv)
VM2_NIC_ID=$(az vm show --name vm-web-02 --resource-group $RESOURCE_GROUP --query 'networkProfile.networkInterfaces[0].id' -o tsv)
VM3_NIC_ID=$(az vm show --name vm-web-03 --resource-group $RESOURCE_GROUP --query 'networkProfile.networkInterfaces[0].id' -o tsv)

# Add NICs to backend pool
az network nic ip-config address-pool add \
    --address-pool BackendPool \
    --ip-config-name ipconfig1 \
    --nic-name vm-web-01VMNic \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME

az network nic ip-config address-pool add \
    --address-pool BackendPool \
    --ip-config-name ipconfig1 \
    --nic-name vm-web-02VMNic \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME

az network nic ip-config address-pool add \
    --address-pool BackendPool \
    --ip-config-name ipconfig1 \
    --nic-name vm-web-03VMNic \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME

8Create Inbound NAT Rules

Create SSH NAT Rules for Each VM
# NAT Rule for VM1 SSH (Port 2201 -> 22)
az network lb inbound-nat-rule create \
    --name SSH-VM1 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 2201 \
    --backend-port 22 \
    --frontend-ip-name LoadBalancerFrontend

# NAT Rule for VM2 SSH (Port 2202 -> 22)
az network lb inbound-nat-rule create \
    --name SSH-VM2 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 2202 \
    --backend-port 22 \
    --frontend-ip-name LoadBalancerFrontend

# NAT Rule for VM3 SSH (Port 2203 -> 22)
az network lb inbound-nat-rule create \
    --name SSH-VM3 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 2203 \
    --backend-port 22 \
    --frontend-ip-name LoadBalancerFrontend
Create HTTP NAT Rules for Web Applications
# NAT Rule for VM1 HTTP (Port 8001 -> 80)
az network lb inbound-nat-rule create \
    --name HTTP-VM1 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 8001 \
    --backend-port 80 \
    --frontend-ip-name LoadBalancerFrontend

# NAT Rule for VM2 HTTP (Port 8002 -> 80)
az network lb inbound-nat-rule create \
    --name HTTP-VM2 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 8002 \
    --backend-port 80 \
    --frontend-ip-name LoadBalancerFrontend

# NAT Rule for VM3 HTTP (Port 8003 -> 80)
az network lb inbound-nat-rule create \
    --name HTTP-VM3 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 8003 \
    --backend-port 80 \
    --frontend-ip-name LoadBalancerFrontend

9Associate NAT Rules with Network Interfaces

Link NAT Rules to Specific VMs
# Associate SSH NAT rules
az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-01VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule SSH-VM1 \
    --lb-name $LB_NAME

az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-02VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule SSH-VM2 \
    --lb-name $LB_NAME

az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-03VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule SSH-VM3 \
    --lb-name $LB_NAME

# Associate HTTP NAT rules
az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-01VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule HTTP-VM1 \
    --lb-name $LB_NAME

az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-02VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule HTTP-VM2 \
    --lb-name $LB_NAME

az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-03VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule HTTP-VM3 \
    --lb-name $LB_NAME

🔄 Traffic Flow Analysis

Inbound Traffic Flow

sequenceDiagram participant Client as Internet Client participant PIP as Public IP participant LB as Load Balancer participant NAT as NAT Rule Engine participant VM as Target VM Client->>PIP: Request to Public IP:2201 PIP->>LB: Forward to Load Balancer LB->>NAT: Process NAT Rule (SSH-VM1) Note over NAT: Port 2201 -> Port 22
Target: VM1 NIC NAT->>VM: Forward to VM1:22 VM->>NAT: Response from VM1:22 NAT->>LB: Translate back to Port 2201 LB->>PIP: Return via Public IP PIP->>Client: Response to Client
Sequence Diagram Step-by-Step Explanation:

This diagram shows the exact sequence of events when a client connects through an inbound NAT rule:

Request Flow (Steps 1-5):

  1. Client → Public IP: Internet client initiates connection to the public IP address on port 2201 (could be SSH, RDP, HTTP, etc.)
  2. Public IP → Load Balancer: Azure's network infrastructure routes the packet to the associated load balancer
  3. Load Balancer → NAT Engine: Load balancer identifies this as NAT rule traffic and passes it to the NAT rule processing engine
  4. NAT Rule Processing: The engine looks up the rule for port 2201, finds it maps to VM1's network interface on port 22
  5. NAT Engine → Target VM: Packet is forwarded to the specific VM's network interface with destination port changed to 22

Response Flow (Steps 6-8):

  1. VM → NAT Engine: VM processes the request and sends response back through its network interface
  2. NAT Engine → Load Balancer: Response is translated back - source port becomes 2201 again
  3. Load Balancer → Client: Response is sent back to the original client through the public IP

Key Points:

  • Stateful Connection: The load balancer maintains connection state to ensure responses reach the correct client
  • Port Translation: External port 2201 is transparently translated to internal port 22
  • VM Isolation: The VM only sees traffic on its native port (22), unaware of the external port mapping
  • Bidirectional: Both request and response packets are processed and translated

Detailed Network Path

graph TD A[Internet Request] -->|Step 1| B[Azure Edge Network] B -->|Step 2| C[Regional Network] C -->|Step 3| D[Public IP Address] D -->|Step 4| E[Load Balancer Frontend] E -->|Step 5| F{NAT Rule Matching} F -->|Port 2201| G[SSH-VM1 Rule] F -->|Port 2202| H[SSH-VM2 Rule] F -->|Port 2203| I[SSH-VM3 Rule] F -->|Port 8001| J[HTTP-VM1 Rule] F -->|Port 8002| K[HTTP-VM2 Rule] F -->|Port 8003| L[HTTP-VM3 Rule] G -->|Translate to Port 22| M[VM1 Network Interface] H -->|Translate to Port 22| N[VM2 Network Interface] I -->|Translate to Port 22| O[VM3 Network Interface] J -->|Translate to Port 80| M K -->|Translate to Port 80| N L -->|Translate to Port 80| O M --> P[VM1 Application] N --> Q[VM2 Application] O --> R[VM3 Application] style F fill:#ff6b6b,stroke:#333,stroke-width:2px,color:#fff style G fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style H fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style I fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style J fill:#ffc107,stroke:#333,stroke-width:2px,color:#000 style K fill:#ffc107,stroke:#333,stroke-width:2px,color:#000 style L fill:#ffc107,stroke:#333,stroke-width:2px,color:#000
Detailed Network Path Explanation:

This diagram illustrates the complete journey of a network packet from the internet to a specific VM through Azure's infrastructure:

Azure Network Infrastructure (Steps 1-4):

  1. Azure Edge Network: Global network of edge locations that provide the first point of contact for internet traffic
  2. Regional Network: Azure's regional backbone that connects edge locations to specific Azure regions
  3. Public IP Address: The specific IP address assigned to your load balancer that receives the traffic
  4. Load Balancer Frontend: The frontend IP configuration that processes incoming connections

NAT Rule Processing (Step 5):

  • Decision Point (Red Diamond): The load balancer examines the destination port to determine which NAT rule applies
  • Rule Categories:
    • Green Rules (SSH): Ports 2201-2203 for secure shell access to different VMs
    • Yellow Rules (HTTP): Ports 8001-8003 for web application access to different VMs
  • Port Translation: Each rule translates the external port to the appropriate internal port (22 for SSH, 80 for HTTP)

Final Delivery:

  • Network Interface Targeting: Each NAT rule points to a specific VM's network interface
  • Application Layer: The packet finally reaches the application running on the target VM
  • Multi-Service Support: Notice how VM1 can serve both SSH (port 22) and HTTP (port 80) through different external ports

Example Traffic Scenarios:

  • SSH to VM2: Client connects to PublicIP:2202 → Rule SSH-VM2 → VM2:22
  • Web access to VM1: Client connects to PublicIP:8001 → Rule HTTP-VM1 → VM1:80
  • Simultaneous Access: Multiple clients can access different VMs simultaneously through different ports

Port Mapping Overview

NAT Rule Port Mappings:
  • SSH Access: Public IP:2201 → VM1:22, Public IP:2202 → VM2:22, Public IP:2203 → VM3:22
  • HTTP Access: Public IP:8001 → VM1:80, Public IP:8002 → VM2:80, Public IP:8003 → VM3:80
  • Protocol: All rules use TCP
  • Direction: Inbound only (from Internet to VMs)

💡 Practical Examples & Testing

Verification Commands

Get Public IP Address
# Get the public IP address for connection testing
PUBLIC_IP=$(az network public-ip show \
    --name $PUBLIC_IP_NAME \
    --resource-group $RESOURCE_GROUP \
    --query ipAddress \
    --output tsv)

echo "Load Balancer Public IP: $PUBLIC_IP"
List All NAT Rules
# List all inbound NAT rules
az network lb inbound-nat-rule list \
    --lb-name $LB_NAME \
    --resource-group $RESOURCE_GROUP \
    --output table
Show Load Balancer Configuration
# Show complete load balancer configuration
az network lb show \
    --name $LB_NAME \
    --resource-group $RESOURCE_GROUP \
    --output json | jq '{
        name: .name,
        frontendIPConfigurations: .frontendIPConfigurations,
        backendAddressPools: .backendAddressPools,
        inboundNatRules: .inboundNatRules
    }'

Testing NAT Rules

Test SSH Connections
# Test SSH to VM1 through NAT rule
ssh -p 2201 $ADMIN_USERNAME@$PUBLIC_IP

# Test SSH to VM2 through NAT rule
ssh -p 2202 $ADMIN_USERNAME@$PUBLIC_IP

# Test SSH to VM3 through NAT rule
ssh -p 2203 $ADMIN_USERNAME@$PUBLIC_IP
Install and Test Web Server
# Connect to VM1 and install nginx
ssh -p 2201 $ADMIN_USERNAME@$PUBLIC_IP << 'EOF'
sudo apt update
sudo apt install -y nginx
echo "

Hello from VM1

" | sudo tee /var/www/html/index.html sudo systemctl start nginx sudo systemctl enable nginx exit EOF # Test HTTP access through NAT rule curl http://$PUBLIC_IP:8001

Advanced NAT Rule Examples

Create Custom Application NAT Rule
# Create NAT rule for custom application (e.g., Node.js on port 3000)
az network lb inbound-nat-rule create \
    --name NodeJS-VM1 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 9001 \
    --backend-port 3000 \
    --frontend-ip-name LoadBalancerFrontend

# Associate with VM1
az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-01VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule NodeJS-VM1 \
    --lb-name $LB_NAME
Create Database NAT Rule
# Create NAT rule for database access (e.g., PostgreSQL)
az network lb inbound-nat-rule create \
    --name PostgreSQL-VM2 \
    --resource-group $RESOURCE_GROUP \
    --lb-name $LB_NAME \
    --protocol Tcp \
    --frontend-port 5432 \
    --backend-port 5432 \
    --frontend-ip-name LoadBalancerFrontend

# Associate with VM2
az network nic ip-config inbound-nat-rule add \
    --resource-group $RESOURCE_GROUP \
    --nic-name vm-web-02VMNic \
    --ip-config-name ipconfig1 \
    --inbound-nat-rule PostgreSQL-VM2 \
    --lb-name $LB_NAME

Monitoring and Troubleshooting

Monitor NAT Rule Usage
# Check connection status
az network lb show \
    --name $LB_NAME \
    --resource-group $RESOURCE_GROUP \
    --query "inboundNatRules[].{Name:name,FrontendPort:frontendPort,BackendPort:backendPort,Protocol:protocol}" \
    --output table

# Check backend pool members
az network lb address-pool show \
    --name BackendPool \
    --lb-name $LB_NAME \
    --resource-group $RESOURCE_GROUP \
    --query "backendIpConfigurations[].{Name:id}" \
    --output table
Network Diagnostics
# Test network connectivity
az network watcher test-connectivity \
    --source-resource vm-web-01 \
    --dest-address google.com \
    --dest-port 80 \
    --resource-group $RESOURCE_GROUP

# Check effective security rules
az network nic list-effective-nsg \
    --name vm-web-01VMNic \
    --resource-group $RESOURCE_GROUP

Complete Traffic Flow Visualization

graph TB subgraph "Internet" Client1[SSH Client :2201] Client2[Web Browser :8001] Client3[DB Client :5432] end subgraph "Azure Load Balancer" PIP[Public IP: X.X.X.X] Frontend[Frontend IP Config] subgraph "NAT Rules" NAT1[SSH-VM1: 2201→22] NAT2[HTTP-VM1: 8001→80] NAT3[DB-VM2: 5432→5432] end end subgraph "Backend VMs" subgraph "VM1" SSH1[SSH Service :22] Web1[Nginx :80] end subgraph "VM2" DB2[PostgreSQL :5432] end end Client1 -->|Port 2201| PIP Client2 -->|Port 8001| PIP Client3 -->|Port 5432| PIP PIP --> Frontend Frontend --> NAT1 Frontend --> NAT2 Frontend --> NAT3 NAT1 -->|Port 22| SSH1 NAT2 -->|Port 80| Web1 NAT3 -->|Port 5432| DB2 style PIP fill:#ffc107,stroke:#333,stroke-width:2px,color:#000 style NAT1 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style NAT2 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style NAT3 fill:#28a745,stroke:#333,stroke-width:2px,color:#fff style SSH1 fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff style Web1 fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff style DB2 fill:#0078d4,stroke:#333,stroke-width:2px,color:#fff
Complete Traffic Flow Visualization Explained:

This comprehensive diagram demonstrates real-world scenarios with multiple client types accessing different services:

Client Scenarios:

  • SSH Client (Administrative Access): System administrator connecting via SSH client to manage VM1
  • Web Browser (End User Access): Regular user accessing a web application hosted on VM1
  • Database Client (Application Access): Application or database tool connecting to PostgreSQL on VM2

Load Balancer Components:

  • Public IP (Yellow): Single internet-facing IP address (e.g., 20.120.45.123) that all clients connect to
  • Frontend IP Config: Internal configuration that binds the public IP to the load balancer
  • NAT Rules (Green): Translation rules that map external ports to internal VM ports:
    • SSH-VM1: External port 2201 → Internal port 22
    • HTTP-VM1: External port 8001 → Internal port 80
    • DB-VM2: External port 5432 → Internal port 5432 (same port)

Backend Services (Blue):

  • VM1 Multi-Service: Hosts both SSH daemon (port 22) and Nginx web server (port 80)
  • VM2 Database: Dedicated PostgreSQL database server (port 5432)
  • Service Isolation: Each service runs on its standard port within the VM

Connection Examples:

  • Admin SSH: ssh -p 2201 admin@20.120.45.123 → VM1 SSH service
  • Web Access: http://20.120.45.123:8001 → VM1 Nginx server
  • Database Connection: psql -h 20.120.45.123 -p 5432 → VM2 PostgreSQL

Key Benefits Illustrated:

  • Cost Efficiency: Three different services accessible through one public IP instead of three separate IPs
  • Security: VMs have no direct internet exposure - all access controlled through load balancer
  • Flexibility: Can easily add more services by creating additional NAT rules
  • Concurrent Access: Multiple clients can access different services simultaneously
Key Testing Points:
  • Verify each NAT rule works independently
  • Test from different source IP addresses
  • Monitor connection logs on target VMs
  • Validate NSG rules allow the traffic
  • Check load balancer health probes if configured

Cleanup Commands

Remove All Resources
# Delete the entire resource group (removes all resources)
az group delete \
    --name $RESOURCE_GROUP \
    --yes \
    --no-wait

# Or delete individual NAT rules
az network lb inbound-nat-rule delete \
    --name SSH-VM1 \
    --lb-name $LB_NAME \
    --resource-group $RESOURCE_GROUP

📚 Best Practices & Security Considerations

Security Best Practices:
  • Use non-standard ports for SSH (avoid 22) to reduce attack surface
  • Implement strong authentication (SSH keys, MFA)
  • Regularly update NSG rules to restrict source IP ranges
  • Monitor connection logs and set up alerts
  • Use Azure Security Center recommendations
Performance Considerations:
  • NAT rules have minimal performance overhead
  • Standard Load Balancer provides better performance than Basic
  • Consider using availability zones for high availability
  • Monitor connection limits and scale accordingly