Azure Bastion is a fully managed platform-as-a-service (PaaS) that provides secure and seamless RDP/SSH connectivity to your virtual machines directly through the Azure portal over TLS. This eliminates the need for public IP addresses on your VMs while providing secure access.
This diagram shows the high-level architecture of Azure Bastion. Users connect through the Azure Portal, which communicates with the Azure Bastion service. The Bastion service is deployed in a dedicated subnet called "AzureBastionSubnet" and provides secure connectivity to VMs within the same virtual network. The key benefit is that VMs don't need public IP addresses - all traffic flows through the secure Bastion tunnel.
This sequence diagram illustrates how traffic flows when establishing a connection through Azure Bastion:
The entire session is encrypted end-to-end, and no public IPs are exposed on the target VMs.
This diagram shows the network security architecture:
This diagram shows the logical sequence for implementing Azure Bastion. Each numbered step builds upon the previous one, and the order is critical for successful deployment. The components must be created in this specific sequence due to dependencies between resources.
az group create \
--name rg-bastion-demo \
--location eastus
--name
: Resource group name (must be unique within subscription)--location
: Azure region where resources will be deployedPurpose: Creates a logical container for all Bastion-related resources. This is the foundation that holds all other components and provides a single management boundary.
Alternative Options:
--tags
: Add metadata tags for resource organizationaz network vnet create \
--resource-group rg-bastion-demo \
--name vnet-bastion-demo \
--address-prefix 10.0.0.0/16 \
--location eastus
--address-prefix
: CIDR block for the entire virtual network (10.0.0.0/16 provides 65,536 IP addresses)--name
: Virtual network name--resource-group
: References the resource group created in step 1Purpose: Creates the virtual network foundation that will contain both the Bastion subnet and VM subnets. This establishes the network boundary for secure communication.
Network Planning:
az network vnet subnet create \
--resource-group rg-bastion-demo \
--vnet-name vnet-bastion-demo \
--name AzureBastionSubnet \
--address-prefix 10.0.1.0/26
--name
: MUST be exactly "AzureBastionSubnet" (case-sensitive, required by Azure)--address-prefix
: Must be /26 or larger (minimum 64 IP addresses)--vnet-name
: References the virtual network created in step 2Purpose: Creates the dedicated subnet where Azure Bastion service will be deployed. This subnet is exclusively reserved for Bastion infrastructure.
az network vnet subnet create \
--resource-group rg-bastion-demo \
--vnet-name vnet-bastion-demo \
--name subnet-vms \
--address-prefix 10.0.2.0/24
--name
: Subnet name for virtual machines (can be any valid name)--address-prefix
: /24 provides 256 IP addresses (251 usable after Azure reservations)Purpose: Creates the subnet where target virtual machines will be deployed. VMs in this subnet will be accessible through Bastion without requiring public IP addresses.
Subnet Planning:
az network nsg create \
--resource-group rg-bastion-demo \
--name nsg-bastion \
--location eastus
--name
: Network Security Group name for Bastion subnetPurpose: Creates firewall rules to control traffic to/from the Bastion subnet. This provides an additional layer of security for the Bastion service.
# Allow inbound HTTPS from Internet
az network nsg rule create \
--resource-group rg-bastion-demo \
--nsg-name nsg-bastion \
--name AllowHttpsInbound \
--protocol Tcp \
--direction Inbound \
--priority 1000 \
--source-address-prefix Internet \
--source-port-range "*" \
--destination-address-prefix "*" \
--destination-port-range 443 \
--access Allow
# Allow inbound from GatewayManager
az network nsg rule create \
--resource-group rg-bastion-demo \
--nsg-name nsg-bastion \
--name AllowGatewayManagerInbound \
--protocol Tcp \
--direction Inbound \
--priority 1001 \
--source-address-prefix GatewayManager \
--source-port-range "*" \
--destination-address-prefix "*" \
--destination-port-range 443 \
--access Allow
# Allow outbound SSH and RDP to VMs
az network nsg rule create \
--resource-group rg-bastion-demo \
--nsg-name nsg-bastion \
--name AllowSshRdpOutbound \
--protocol "*" \
--direction Outbound \
--priority 1000 \
--source-address-prefix "*" \
--source-port-range "*" \
--destination-address-prefix VirtualNetwork \
--destination-port-ranges 22 3389 \
--access Allow
Service Tags Used:
Internet
: Represents all public Internet addressesGatewayManager
: Azure service tag for gateway management trafficVirtualNetwork
: Represents all addresses in the virtual networkaz network public-ip create \
--resource-group rg-bastion-demo \
--name pip-bastion \
--sku Standard \
--allocation-method Static \
--location eastus
--sku Standard
: Required for Bastion (Basic SKU not supported)--allocation-method Static
: Ensures IP address doesn't change--name
: Public IP resource namePurpose: Creates the public IP address that Azure Bastion will use to receive inbound connections from the Internet. This is the only public IP required in the entire solution.
Additional Options:
--zone {1,2,3}
: Specify availability zone for zone-redundant deployment--dns-name-label
: Create DNS name like mybastion.eastus.cloudapp.azure.comaz network bastion create \
--resource-group rg-bastion-demo \
--name bastion-demo \
--public-ip-address pip-bastion \
--vnet-name vnet-bastion-demo \
--location eastus \
--sku Standard
--public-ip-address
: References the public IP created in step 6--vnet-name
: Virtual network containing AzureBastionSubnet--sku Standard
: Bastion SKU (Basic or Standard)Purpose: Deploys the actual Azure Bastion service into the AzureBastionSubnet. This process takes 10-15 minutes to complete as Azure provisions the managed infrastructure.
SKU Comparison:
az vm create \
--resource-group rg-bastion-demo \
--name vm-web-01 \
--image Ubuntu2204 \
--subnet subnet-vms \
--vnet-name vnet-bastion-demo \
--admin-username azureuser \
--authentication-type ssh \
--generate-ssh-keys \
--public-ip-address "" \
--size Standard_B2s
--image Ubuntu2204
: VM image (Ubuntu 22.04 LTS)--subnet
: VM subnet created in step 4--public-ip-address ""
: Explicitly prevents public IP creation--generate-ssh-keys
: Creates SSH keys for authentication--size Standard_B2s
: VM size (2 vCPUs, 4 GB RAM)Purpose: Creates a virtual machine without a public IP address to test Bastion connectivity. This VM can only be accessed through Azure Bastion.
Security Benefits:
az vm create \
--resource-group rg-bastion-demo \
--name vm-win-01 \
--image Win2022Datacenter \
--subnet subnet-vms \
--vnet-name vnet-bastion-demo \
--admin-username azureuser \
--admin-password 'ComplexPassword123!' \
--public-ip-address "" \
--size Standard_B2s
Windows VM Notes:
az network bastion update \
--resource-group rg-bastion-demo \
--name bastion-demo \
--enable-native-client true
Usage Example:
az network bastion ssh --name bastion-demo --resource-group rg-bastion-demo --target-resource-id /subscriptions/.../vm-web-01 --auth-type ssh-key --username azureuser
az network bastion update \
--resource-group rg-bastion-demo \
--name bastion-demo \
--scale-units 10
az network bastion show \
--resource-group rg-bastion-demo \
--name bastion-demo \
--output table
az network vnet subnet show \
--resource-group rg-bastion-demo \
--vnet-name vnet-bastion-demo \
--name AzureBastionSubnet \
--output table
az vm show \
--resource-group rg-bastion-demo \
--name vm-web-01 \
--show-details \
--query '{Name:name, PrivateIp:privateIps, PublicIp:publicIps, PowerState:powerState}' \
--output table
Expected Results:
Cost Savings:
Azure Bastion provides a secure, managed solution for VM connectivity without exposing public IP addresses. The implementation requires careful attention to subnet naming, sizing, and network security group configuration. Once deployed, it offers a streamlined way to access VMs through the Azure Portal with enterprise-grade security.