Understanding Azure Bastion: A Complete Guide

Azure Bastion

Azure Bastion is a fully managed PaaS service that provides secure RDP and SSH connectivity to your virtual machines directly through the Azure portal or native client — over TLS on port 443 — without exposing any public IP address on the VM itself.


Why Bastion Exists — The Problem It Solves

The traditional way to RDP or SSH into an Azure VM was to assign it a public IP and open port 3389 or 22 to the internet. This creates serious exposure:

Old approach:
VM has public IP 20.x.x.x → port 3389 open to internet
→ Constant brute-force attacks (thousands/day)
→ Any misconfigured NSG = immediate compromise
→ Public IP costs, management overhead
→ No session recording or audit trail
With Bastion:
VM has no public IP — completely unreachable from internet
→ Admin connects via browser to Bastion on port 443
→ Bastion proxies RDP/SSH over private VNet path
→ Session fully audited in Azure Monitor
→ No attack surface on the VM itself

How the Connection Works — Step by Step

1. Admin opens Azure portal or native client
Selects a VM → Connect → Bastion
2. Portal establishes WebSocket connection to Bastion
over HTTPS port 443 (same as normal web traffic)
→ passes through corporate firewalls without issue
3. Bastion authenticates the admin
via Azure AD / RBAC — checks if admin has
"Bastion User" role on the Bastion resource
4. Bastion opens RDP (:3389) or SSH (:22) connection
from its private NIC directly to the VM's private IP
entirely inside the VNet / peered spoke
5. RDP or SSH session streams back to browser
rendered as HTML5 — no RDP client needed
(Standard SKU supports native RDP/SSH client too)
6. Session ends → connection torn down
Audit log written to Azure Monitor / Log Analytics

The VM never sees a connection from the internet — it only sees a private IP connection from within the VNet.


AzureBastionSubnet Requirements

Bastion requires a dedicated subnet with a very specific name — Azure will refuse to deploy it anywhere else:

Subnet name: AzureBastionSubnet ← exact name required
Min size: /26 (64 addresses) ← Basic SKU minimum
Recommended: /24 or /25 ← room to scale instances
Location: Hub VNet only ← one Bastion serves all peered spokes

No other resources — VMs, firewalls, private endpoints — can share this subnet. The /26 minimum exists because Bastion deploys multiple managed instances internally and Azure reserves addresses for platform use.


Bastion SKUs

FeatureBasicStandardPremium
Browser-based RDP/SSH
Native client (RDP/SSH app)
Shareable links
IP-based connection (no Azure VM)
VNet peering support
Session scaling (instances)2 fixed2–50 scalable2–50 scalable
File transfer (upload/download)
Clipboard (copy/paste)✅ text✅ text + file✅ text + file
Session recording
Private-only Bastion (no public IP)
Kerberos authentication
Pricing~$140/month~$280/month~$470/month

Standard is the right choice for most enterprises — it adds native client support (so admins can use their local RDP or SSH client instead of the browser) and instance scaling for large teams.

Premium adds session recording — every RDP/SSH session is captured and stored in a storage account — critical for compliance environments (PCI-DSS, SOC 2) where you must prove what privileged users did during a session. It also supports fully private Bastion with no public IP at all, using a private endpoint instead.


NSG Rules Required

Two NSGs must be configured correctly — one on the AzureBastionSubnet and one on the target VM subnet:

NSG on AzureBastionSubnet

Inbound rules:

PrioritySourceDestPortProtocolActionPurpose
100InternetAny443TCPAllowAdmin HTTPS inbound
110GatewayManagerAny443TCPAllowAzure control plane
120AzureLoadBalancerAny443TCPAllowHealth probes

Outbound rules:

PrioritySourceDestPortProtocolActionPurpose
100AnyVirtualNetwork3389, 22TCPAllowRDP/SSH to VMs
110AnyAzureCloud443TCPAllowBastion diagnostics

NSG on target VM subnet

PrioritySourceDestPortProtocolActionPurpose
100VirtualNetworkAny3389TCPAllowRDP from Bastion
110VirtualNetworkAny22TCPAllowSSH from Bastion

The VM subnet must allow inbound from VirtualNetwork service tag — which includes all peered VNets including the hub where Bastion lives. Critically, there is no rule allowing port 3389 or 22 from Internet — the VM is completely shielded.


RBAC Roles for Bastion Access

Bastion access is controlled by Azure RBAC — not just network connectivity:

RoleWhat it allows
Reader on BastionSee the Bastion resource
Bastion ReaderConnect through Bastion (read-only session)
Virtual Machine Contributor on VMNeeded to initiate the connection
Bastion ContributorManage the Bastion resource

A typical setup grants an admin team the Virtual Machine Contributor role on specific spoke resource groups, plus Reader on the Bastion. They can then connect to VMs they have rights to — but cannot modify the Bastion configuration itself or connect to VMs outside their scope.


Bastion in Hub and Spoke — One Bastion for All Spokes

A single Bastion in the hub VNet reaches VMs in all peered spoke VNets — you do not need a Bastion in every spoke. This is a key cost and management advantage:

Hub VNet → AzureBastionSubnet → Azure Bastion
↓ peering allows Bastion to reach
Spoke 1 VMs (production)
Spoke 2 VMs (development)
Spoke 3 VMs (shared services)
Spoke 4 VMs (DMZ)

One Bastion instance, one Standard public IP, one monthly cost — covering your entire estate. The only requirement is that the hub-to-spoke peering has Allow gateway transit enabled on the hub side and Use remote gateways enabled on the spoke side (the same peering settings used for routing).


Key Takeaway

Azure Bastion eliminates the biggest attack surface in most Azure environments — publicly exposed management ports on VMs. By proxying all RDP and SSH through a hardened, Microsoft-managed PaaS service over HTTPS, it gives you secure, auditable VM access with no public IPs on your workloads, no VPN client requirement for browser sessions, and full RBAC control over who can connect to what.

Leave a comment