T Techclick ← All lessons
Microsoft · Azure security · Lesson 6 of 10

Private Link: allow Azure is not private

SQL and Storage are “locked down” to Azure. The firewall exception is Allow Azure services. That is every Azure IP, including strangers. Private is a Private Endpoint in the spoke — a NIC with a 10.41.x.x address — and public access off. Private Link is the service-side of that NIC.

Updated 2026-08-18·18 min read·L2 primary·Quiz at end

After this page you can

The ticket

CISO: “SQL is not on the internet.” The SQL blade shows Public network access = Selected networks, plus Allow Azure services on. A scanner in another tenant’s VM can still reach it from an Azure IP. You documented “private.” It is not.

Quick interview answer

Private Endpoint puts a NIC in your VNet (here the spoke 10.41.0.0/16) that maps to a PaaS resource (Storage, SQL, Key Vault, …). Traffic stays on the Microsoft backbone to that resource. Private Link is the platform that publishes the service to that NIC. Public + firewall IP list is still a public endpoint. “Allow trusted Azure services / Allow Azure services” is an exception for Azure-sourced IPs — not your VNet. Disable public access when the endpoint is live, and fix DNS with the privatelink.* zone so the FQDN returns the private IP.

Hero · private NIC
Private Endpoint NIC in the spoke versus public PaaS
10.41 is private. “Allow Azure” is a crowd.
Lab data · dummy only

Tenant techclick-lab.in · MG tc-root / tc-landing / tc-workloads · subs sub-hub sub-spoke-app · hub VNet 10.40.0.0/16 · spoke 10.41.0.0/16 · Azure Firewall 10.40.0.4 · VPN GW public 203.0.113.50 · on-prem FortiGate WAN 203.0.113.10. Not a live tenant.

Mental model

ModeWho can hit itThis lab
Public + anyThe internetNever for pay-api data
Public + IP listThose IPs (and whoever shares them)Break-glass only, if ever
Public + Allow Azure servicesAzure-sourced IPs, not “our VNet”Not private
Private Endpoint, public offYour VNet / peered / on-prem via hubpe-sql-pay in 10.41.0.0/16
Same FQDN, different answer
Public endpoint sql-pay.database.windows.net → public VIP Private Endpoint same FQDN via privatelink zone → 10.41.2.10 on spoke NIC

If DNS still returns the public VIP, you built a museum piece. The app never uses the NIC.

How to choose

NeedDoDo not
PaaS from pay-api / on-premPrivate Endpoint + privatelink DNSAllow Azure services
Partner on the internetTheir IP on the public firewall, or a different patternPretend PE is optional
kv-tc-labPE in the spoke, public disabledPortal-only “from my IP” forever
https://portal.azure.com
Training mock · not live
HomeMicrosoft Entra IDVirtual networksAzure Firewall
Private endpoints → pe-sql-pay

Overview

sql-pay · Microsoft.Sql
10.41.2.10 · spoke 10.41.0.0/16
Disabled
privatelink.database.windows.net
Off — not a private control
Private Endpoint NIC + public off. Training mock.

Runbook

  1. Side A — endpoint

    Create PE in the spoke subnet (not GatewaySubnet, not AzureFirewallSubnet). Approve it. Repeat for kv-tc-lab if that vault is still public.

  2. Side B — DNS

    Private DNS zone + VNet link on hub and spoke (and on-prem conditional forwarder to the hub if Priya must resolve it). FQDN must return 10.41.2.10 from pay-api.

  3. Side C — prove

    Disable public network access. From pay-api: resolve + connect. From a random Internet host: fail. From another Azure VM that is not peered: fail.

az · dummy
az network private-endpoint list -g rg-spoke -o table
# Name        PrivateIP    Resource
# pe-sql-pay  10.41.2.10   sql-pay
# pe-kv-lab   10.41.2.11   kv-tc-lab

# on pay-api
nslookup sql-pay.database.windows.net
# 10.41.2.10
# If you see a public A record, DNS is wrong — PE is unused.

Four failures

1 · Allow Azure services = private

It is not. It is “Azure-sourced.”

2 · PE without DNS

Clients still hit the public VIP. Public disable then looks like an outage.

3 · Public left On

You now have two doors. Attackers use the old one.

4 · PE in the hub, no route/DNS for the spoke

Works from a jump box in the hub. Dies on pay-api. Design DNS + UDR deliberately.

How to prove it

Close only when

1) FQDN from pay-api = 10.41.x.x. 2) Public access is Disabled. 3) Allow Azure services is off. 4) A non-peered Azure VM cannot connect.

Traps

Looks lockedIs not
Selected networks + Allow AzureOther tenants’ Azure IPs
Private Endpoint createdPublic still On + public DNS
Service endpoint on the subnetStill a public PaaS VIP, just from that VNet — not Private Link

Knowledge check

Judgment items. One best answer. Reasons send you back to the matching section.

Q1

A Private Endpoint is…

Correct: b. PE = NIC in your VNet.
Q2

Allow Azure services on SQL/Storage means…

Correct: b. Not a perimeter.
Q3

After creating a PE you must still…

Correct: b. DNS + public off.
Q4

nslookup from pay-api still returns a public A record. Effect?

Correct: b. Failure 2.
Q5

Service endpoint vs Private Endpoint?

Correct: b. Trap.
Q6

Proof SQL is actually private?

Correct: b. Verify.

Azure security class series: Shared + Entra · Landing zone · NSG vs Firewall vs WAF · Conditional Access · Key Vault + MI · Private Link · Defender + Sentinel · Hub-spoke · Identity path · Interview

Sources

Related: Azure session factory · Migration series.