Episode 6 — Secure Access to VMs & PaaS: Bastion, Service Endpoints & Private Link
In Episode 5 you learned how NSGs and ASGs filter packets inside the VNet; now we tackle the two hardest exposure problems those filters can't fully solve — reaching a VM for management, and reaching Azure PaaS — without ever opening a public door.
Learning objectives
- Explain how Azure Bastion provides browser-based RDP/SSH over TLS so your VMs need no public IP.
- Configure the mandatory AzureBastionSubnet (name, size, SKU choices) and diagnose a failed Bastion deployment.
- Distinguish a service endpoint (VNet identity extended to a still-public PaaS endpoint) from a private endpoint (a private IP inside your VNet with private DNS).
- Choose between service endpoints and private endpoints for a given PaaS access scenario, including on-premises access.
Why it matters
Once workloads run in a VNet, two access paths remain dangerously easy to get wrong. Administrators still need to log in to virtual machines, and the reflexive answer — a public IP with port 3389/22 open — is exactly the surface that internet-wide port scanners hunt. Meanwhile, application code needs to reach Azure PaaS services such as Storage, SQL Database, and Key Vault, which by default sit on public endpoints reachable by anyone with the key. This episode covers the three services that close both gaps: Bastion for management access, and service endpoints and Private Link for data-plane access to PaaS. Getting these right is the difference between a VNet that is merely segmented and one that is genuinely private.
Azure Bastion: a managed jump host in the browser
Azure Bastion is a fully managed PaaS service that gives you secure RDP/SSH connectivity to your VMs directly over TLS, either from the Azure portal (an HTML5 web client) or through the native SSH/RDP client on your machine. It is deployed directly into your virtual network and serves all VMs in that network using their private IP addresses.
The headline benefit: when you connect through Bastion, your VMs don't need a public IP address, an agent, or special client software. RDP and SSH ride over TLS on port 443, so you never expose 3389 or 22 to the internet. Because there is no public IP on the VM, it is protected from port scanning and other external threats. Think of Bastion as a hardened, Microsoft-managed jump box that you never have to patch.
The AzureBastionSubnet requirement
Bastion has one non-negotiable prerequisite for every SKU except Developer: a dedicated subnet named exactly AzureBastionSubnet. The rules are strict:
- The subnet name must be
AzureBastionSubnet(any other name fails). - The subnet must be
/26or larger (/25,/24, …). For deployments made on or after November 2, 2021,/26is the enforced minimum; older/27subnets keep working but should be grown to/26to allow host scaling. - It must be in the same virtual network and resource group as the bastion host.
- It can't contain any other resources.
Memory hook — "N-S-R": Name is fixed, Size is /26+, Resources — none allowed. If a Bastion deploy fails, check N-S-R first.
Dedicated deployments (Basic, Standard, Premium) also need a Standard-SKU public IP with Static allocation. Only Premium supports a private-only deployment with no public IP at all; the Developer SKU uses shared infrastructure and needs no dedicated subnet.
SKUs at a glance
Bastion comes in four SKUs: Developer, Basic, Standard, and Premium.
| SKU | Infrastructure | Public IP / subnet | Key added capabilities |
|---|---|---|---|
| Developer | Shared pool (free) | No dedicated subnet or public IP; one VM at a time | Basic browser connectivity for dev/test, select regions |
| Basic | Dedicated, fixed capacity (two instances) | Requires AzureBastionSubnet + Standard public IP | Browser RDP/SSH for production |
| Standard | Dedicated, host scaling | Same | Native client, shareable links, IP-based connections, custom ports, file transfer |
| Premium | Dedicated | Public IP or private-only | All Standard features + session recording for compliance |
By default the connect ports are 3389 (RDP) and 22 (SSH); custom ports are a Standard-or-higher feature. Host scaling (adding instances/scale units) requires Standard or higher — Basic is fixed at two instances.
Deploying Bastion (portal, high level)
From the target VNet or VM, choose Connect > Bastion. Default settings does a one-click deploy with the Standard SKU; Configure manually lets you pick the tier, availability zone, instance count, subnet, and public IP. Either way a dedicated deployment takes about 10 minutes; Developer deploys in seconds. When creating the subnet in the portal you set Subnet purpose = Azure Bastion, an IPv4 range such as 10.1.1.0/26, and Size /26 or larger. Afterwards you can safely dissociate and delete the VM's public IP since it is no longer needed.
Exercise 1 — Choose: Bastion vs a self-managed jumpbox. Your team currently keeps one Windows VM with a public IP and RDP open, used as a jump box into a subnet of 30 production VMs. You want to reduce attack surface and patching effort. Should you keep the jumpbox or move to Bastion? Justify.
Solution. Move to Azure Bastion. The self-managed jumpbox still needs a public IP with 3389 open, is a port-scanning target, and you must patch and harden it. Bastion is fully managed (no OS to patch), serves all 30 VMs over their private IPs, and carries RDP/SSH over TLS on 443 so no VM — including the entry point — needs a public IP. Deploy the Basic SKU if you only need browser connectivity for a moderate production load, or Standard if you want native-client access, file transfer, or host scaling. After deployment, dissociate the public IPs from the VMs.
Service endpoints: extend VNet identity to public PaaS
A virtual network service endpoint provides secure, direct connectivity to Azure services over an optimized route on the Azure backbone. You enable it per subnet, selecting the service's Microsoft.* resource (for example Microsoft.Storage, Microsoft.Sql, Microsoft.KeyVault). Two things then change:
- Source IP switches to the private VNet address. Traffic from VMs in that subnet to the service stops using a public IP as its source and starts using the VNet private IP as the source. This lets you add a virtual network rule on the PaaS resource to allow only your VNet and remove public internet access to it.
- Routing becomes optimal. A more-specific route with next-hop type
VirtualNetworkServiceEndpointis injected, keeping service traffic on the backbone even when you force-tunnel internet traffic to on-prem. These routes override any BGP or user-defined routes for the service's prefixes.
Crucially, the service keeps its public endpoint. With service endpoints, DNS entries for the Azure service remain unchanged and still resolve to the service's public IP address — you are securing by VNet identity, not moving the service into your network. Setup is a single selection on the subnet, there is no NAT/gateway required, and there is no extra charge.
Two limits worth remembering: service endpoints can't be used from on-premises (they only apply to traffic originating in the subnet), and for Azure SQL the endpoint applies only within the service's region.
Exercise 2 — Service endpoint vs private endpoint for a storage account. An app tier of VMs must reach a Storage account privately. Requirement A: also allow secure access from an on-premises office over ExpressRoute. Requirement B: DNS/FQDN must transparently resolve to a private address so no client reconfiguration is needed. Which technology fits, and why?
Solution. Choose a private endpoint (Private Link). A service endpoint won't work from on-premises — it secures only traffic originating inside the subnet, and the storage FQDN still resolves to the public IP. A private endpoint places a private IP from your VNet in front of the storage account, is reachable from on-premises over ExpressRoute/VPN and peered VNets, and with private DNS zone integration the storage FQDN resolves to that private IP (Requirement B satisfied). It also protects against data leakage because the endpoint maps to the specific storage resource, not the whole service. A service endpoint would only satisfy the in-VNet case with the resource still on a public endpoint.
Private Link and private endpoints: a private IP for PaaS
Azure Private Link lets you access Azure PaaS services (and customer/partner services) over a private endpoint in your virtual network, with traffic travelling entirely on the Microsoft backbone — exposing the service to the public internet is no longer necessary.
A private endpoint is a network interface that uses a private IP address from your VNet, connecting you privately to a Private Link-powered service. In effect, you bring the service into your virtual network. Key properties:
- A read-only NIC is automatically created and assigned a dynamic private IP from the chosen subnet; that IP stays fixed for the life of the endpoint.
- The endpoint maps to a specific PaaS instance and subresource (for Storage, e.g.
bloborfile— each needs its own private endpoint), giving strong protection against data leakage. - Connections are one-directional: only the client initiates; the service provider cannot originate connections inward.
- Reachable from the same VNet, regionally/globally peered VNets, and on-premises over VPN/ExpressRoute. The endpoint must be in the same region and subscription as the VNet, but the PaaS resource can live in another region.
- Access uses an approval workflow — automatic (you have the RBAC permission) or manual (a Pending request the resource owner approves/rejects).
DNS is the part people forget
To reach the service over its private endpoint, the FQDN must resolve to the private IP. Public DNS still points at the public endpoint, so you configure separate DNS settings, typically via a private DNS zone (the privatelink.* zones), which we cover in Episode 7. Get DNS wrong and clients silently keep hitting the public endpoint.
The diagram makes the contrast concrete: Bastion is a management path (browser → TLS → private VM IP); a service endpoint still lands on the public PaaS endpoint but with a private source IP and a VNet rule; a private endpoint terminates on a private IP inside your VNet and relies on privatelink DNS.
Exercise 3 — Size the AzureBastionSubnet / fix a failed deploy. A colleague tries to deploy Bastion (Standard SKU) into an existing subnet named
MgmtSubnetsized/27that also holds a small management VM. The deployment fails. List every reason and give the corrected configuration.Solution. Three violations: (1) Wrong name — the subnet must be named exactly
AzureBastionSubnet; (2) Too small — Standard requires /26 or larger (a/27is below the current minimum and blocks host scaling); (3) Not dedicated — the subnet can't contain other resources, so the management VM must be moved out. Corrected config: create a new subnetAzureBastionSubnetat10.1.1.0/26, in the same VNet and resource group as the bastion host, empty of other resources, plus a Standard-SKU, Static public IP. Then deploy.
The core decision: service endpoint vs private endpoint
Microsoft recommends Private Link / private endpoints as the default for private access to PaaS. Use this table to justify the choice.
| Dimension | Service endpoint | Private endpoint (Private Link) |
|---|---|---|
| What it is | VNet identity extended to the service | A private IP (NIC) from your VNet mapped to the service |
| Service endpoint exposure | Service keeps its public IP/endpoint | No public exposure needed; reached via private IP |
| DNS behavior | FQDN still resolves to public IP | FQDN must resolve to private IP (privatelink zone) |
| Granularity | Whole service, secured by VNet rule | Specific resource + subresource (anti-data-leakage) |
| On-premises access | Not supported (subnet-origin traffic only) | Supported via VPN/ExpressRoute + peered VNets |
| Cross-region | SQL is region-bound; others any region | PaaS resource can be in another region |
| Cost | No extra charge | Billed per Private Link/data processed |
| Setup | One selection on the subnet | Create endpoint, approve connection, configure DNS |
| Scope of config | Per subnet | Per resource |
Rule of thumb: if you only need to lock a PaaS resource to your VNet with minimal effort and no on-prem requirement, a service endpoint is fine. If you need on-premises reachability, per-resource isolation, a private IP, or no public endpoint at all, use a private endpoint.
Key takeaways
- Azure Bastion = managed browser RDP/SSH over TLS (443); VMs need no public IP, no agent, no client software.
- Bastion (except Developer) requires a dedicated
AzureBastionSubnet, sized/26or larger, with no other resources, plus a Standard/Static public IP (Premium can be private-only). - Bastion SKUs: Developer, Basic, Standard, Premium; native client, shareable links, custom ports = Standard+; session recording = Premium.
- Service endpoints keep the PaaS public endpoint but switch the source to the private VNet IP and let you add a VNet rule; enabled per subnet, free, DNS unchanged, no on-prem support.
- Private endpoints put a private IP from your VNet in front of a specific PaaS resource; traffic stays on the backbone, works from on-premises/peered VNets, and needs private DNS integration.
- Microsoft recommends private endpoints as the default; service endpoints suit simple, in-VNet-only lockdowns.
Quick recall
-
Q: What ports does a VM need open to the internet to be reached through Azure Bastion? A: None. Bastion connects to the VM's private IP; RDP/SSH ride over TLS on 443 to Bastion itself, so the VM needs no public IP and no inbound 3389/22 from the internet.
-
Q: What are the three hard requirements for the Bastion subnet? A: It must be named exactly
AzureBastionSubnet, be/26or larger, and contain no other resources (same VNet/resource group as the host). -
Q: After enabling a service endpoint, what does the PaaS FQDN resolve to? A: Still the service's public IP address — DNS is unchanged; only the client's source IP switches to the VNet private address, and you secure access with a VNet rule.
-
Q: Which option lets on-premises clients reach a PaaS service privately, and why not the other? A: A private endpoint — it exposes a private IP reachable over VPN/ExpressRoute. A service endpoint only applies to traffic originating inside the subnet, so it can't serve on-premises.
-
Q: Why does a private endpoint protect against data leakage better than a service endpoint? A: It maps to a specific resource and subresource (e.g. only the
blobof one storage account), so clients can't reach other resources in the service; a service endpoint secures the service at the VNet level.
Coming up
Private endpoints only work when the FQDN resolves to that private IP — which is exactly the job of Azure DNS. Episode 7 covers name resolution: Azure Public and Private DNS, zones, records, VNet links, and the privatelink zones that make private endpoints resolve correctly.