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 trailWith 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 → Bastion2. Portal establishes WebSocket connection to Bastion over HTTPS port 443 (same as normal web traffic) → passes through corporate firewalls without issue3. Bastion authenticates the admin via Azure AD / RBAC — checks if admin has "Bastion User" role on the Bastion resource4. Bastion opens RDP (:3389) or SSH (:22) connection from its private NIC directly to the VM's private IP entirely inside the VNet / peered spoke5. 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 requiredMin size: /26 (64 addresses) ← Basic SKU minimumRecommended: /24 or /25 ← room to scale instancesLocation: 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
| Feature | Basic | Standard | Premium |
|---|---|---|---|
| Browser-based RDP/SSH | ✅ | ✅ | ✅ |
| Native client (RDP/SSH app) | ❌ | ✅ | ✅ |
| Shareable links | ❌ | ✅ | ✅ |
| IP-based connection (no Azure VM) | ❌ | ✅ | ✅ |
| VNet peering support | ✅ | ✅ | ✅ |
| Session scaling (instances) | 2 fixed | 2–50 scalable | 2–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:
| Priority | Source | Dest | Port | Protocol | Action | Purpose |
|---|---|---|---|---|---|---|
| 100 | Internet | Any | 443 | TCP | Allow | Admin HTTPS inbound |
| 110 | GatewayManager | Any | 443 | TCP | Allow | Azure control plane |
| 120 | AzureLoadBalancer | Any | 443 | TCP | Allow | Health probes |
Outbound rules:
| Priority | Source | Dest | Port | Protocol | Action | Purpose |
|---|---|---|---|---|---|---|
| 100 | Any | VirtualNetwork | 3389, 22 | TCP | Allow | RDP/SSH to VMs |
| 110 | Any | AzureCloud | 443 | TCP | Allow | Bastion diagnostics |
NSG on target VM subnet
| Priority | Source | Dest | Port | Protocol | Action | Purpose |
|---|---|---|---|---|---|---|
| 100 | VirtualNetwork | Any | 3389 | TCP | Allow | RDP from Bastion |
| 110 | VirtualNetwork | Any | 22 | TCP | Allow | SSH 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:
| Role | What it allows |
|---|---|
Reader on Bastion | See the Bastion resource |
Bastion Reader | Connect through Bastion (read-only session) |
Virtual Machine Contributor on VM | Needed to initiate the connection |
Bastion Contributor | Manage 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.