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 /26 or larger (/25, /24, …). For deployments made on or after November 2, 2021, /26 is the enforced minimum; older /27 subnets keep working but should be grown to /26 to 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.

SKUInfrastructurePublic IP / subnetKey added capabilities
DeveloperShared pool (free)No dedicated subnet or public IP; one VM at a timeBasic browser connectivity for dev/test, select regions
BasicDedicated, fixed capacity (two instances)Requires AzureBastionSubnet + Standard public IPBrowser RDP/SSH for production
StandardDedicated, host scalingSameNative client, shareable links, IP-based connections, custom ports, file transfer
PremiumDedicatedPublic IP or private-onlyAll 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:

  1. 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.
  2. Routing becomes optimal. A more-specific route with next-hop type VirtualNetworkServiceEndpoint is 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.

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 backboneexposing 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. blob or file — 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 workflowautomatic (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.

RDP/SSH over TLS 443private IPsrc = private IPnext hop:VirtualNetworkServiceEndpointresolves to PUBLIC IPto private IPprivatelink DNSbackbone onlyAdmin browser(HTML5 / native client)Azure Bastionin AzureBastionSubnetVM(no public IP)App VM in subnetService endpointoptimized backbone routeAzure PaaS(public endpoint, VNetrule)App VM in subnetPrivate endpoint NICprivate IP in your VNetAzure PaaS instance(no public exposure)

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 MgmtSubnet sized /27 that 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 /27 is 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 subnet AzureBastionSubnet at 10.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.

DimensionService endpointPrivate endpoint (Private Link)
What it isVNet identity extended to the serviceA private IP (NIC) from your VNet mapped to the service
Service endpoint exposureService keeps its public IP/endpointNo public exposure needed; reached via private IP
DNS behaviorFQDN still resolves to public IPFQDN must resolve to private IP (privatelink zone)
GranularityWhole service, secured by VNet ruleSpecific resource + subresource (anti-data-leakage)
On-premises accessNot supported (subnet-origin traffic only)Supported via VPN/ExpressRoute + peered VNets
Cross-regionSQL is region-bound; others any regionPaaS resource can be in another region
CostNo extra chargeBilled per Private Link/data processed
SetupOne selection on the subnetCreate endpoint, approve connection, configure DNS
Scope of configPer subnetPer 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 /26 or 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

  1. 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.

  2. Q: What are the three hard requirements for the Bastion subnet? A: It must be named exactly AzureBastionSubnet, be /26 or larger, and contain no other resources (same VNet/resource group as the host).

  3. 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.

  4. 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.

  5. 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 blob of 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.