22_2 ‐ Single Private VNet with no internet, having all other services connected like blob storage - SanjeevOCI/Study GitHub Wiki
22_1 – Single Private VNet (no inbound internet) + Blob via Private Endpoint + NAT Gateway for Updates
-
VNet:
10.10.0.0/16
-
Private Subnet (workloads):
10.10.1.0/24
(no public IPs) - NAT Gateway: outbound-only SNAT for OS/package updates
- Private Endpoint (PE): Blob/Azure Files (Private Link) for storage without internet
- Admin access: Azure Bastion / VPN / ExpressRoute (no public inbound)
-
Goal: Keep workloads private while allowing:
- Private access to storage via PE
- Optional outbound internet (via NAT GW) for OS updates/repos
- No inbound internet access
- Resource Group: Logical container for resources.
-
VNet: CIDR
10.10.0.0/16
(non-overlapping). -
Private Subnet: CIDR
10.10.1.0/24
, no public IPs assigned to VMs.
- No public IP.
- Can access:
- Azure Managed Disks (block storage equivalent)
- Azure Blob Storage / Azure Files via Private Endpoint
- External repos (only if NAT Gateway is configured)
- For Blob Storage (or Azure Files, Key Vault, etc.).
- Placed in the Private Subnet (or a dedicated PE Subnet).
- Use Private DNS Zone for
privatelink.blob.core.windows.net
and link to the VNet. - Validate:
nslookup <account>.blob.core.windows.net
→ private IP from VNet.
- Create NAT Gateway and assign a Public IP or Public IP Prefix.
- Associate NAT GW with the Private Subnet.
- Required only if outbound internet is needed for:
- OS updates
- External package repos
- If not required, skip to ensure no internet connectivity.
Address Prefix | Next Hop Type | Next Hop | Purpose |
---|---|---|---|
0.0.0.0/0 |
NAT Gateway | <NATGW> |
Outbound internet via NAT GW (egress only) |
(Disable internet alternative) | None | — | Blackhole route to drop all outbound internet traffic |
(Blob PE traffic) | — | — | No explicit route needed — PE is reached via DNS to its private IP |
Attach this Route Table to the Private Subnet in VNet settings.
Priority | Name | Source | Destination | Protocol | Port(s) | Action | Purpose |
---|---|---|---|---|---|---|---|
100 | Allow-BlobPE-HTTPS | VirtualNetwork | Storage (Service Tag) | TCP | 443 | Allow | Blob/Azure Files via Private Endpoint |
110 | Allow-NATGW-HTTPS | VirtualNetwork | 0.0.0.0/0 |
TCP | 443 | Allow | Outbound to internet via NAT GW for updates/repos |
4000 | Deny-All-Outbound | * | 0.0.0.0/0 |
Any | * | Deny | Block all other outbound |
Priority | Name | Source | Destination | Protocol | Port(s) | Action | Purpose |
---|---|---|---|---|---|---|---|
100 | Allow-Admin | Bastion/VPN Subnet or VirtualNetwork | VirtualNetwork | TCP | 22,3389 | Allow | Admin via Bastion/VPN only |
4096 | Deny-All-Inbound | * | * | Any | * | Deny | Block all inbound from internet |
-
Default internet route:
Every subnet has a system route0.0.0.0/0 → Internet
.- If VM has a Public IP → inbound/outbound possible (NSG permitting).
- If VM has no Public IP → outbound still possible via Azure-provided SNAT (until Sept 2025 changes).
- To block, create a custom UDR replacing
0.0.0.0/0
with Next hop: None (blackhole) or point to NVA/Azure Firewall.
-
NAT Gateway vs default SNAT:
- NAT GW = dedicated outbound IP(s), scales better, avoids ephemeral SNAT port exhaustion.
- Default SNAT shares ephemeral ports → can cause outbound connection failures at scale.
-
Private Endpoint (PE) traffic:
- Always stays on Microsoft backbone.
- With Private DNS Zone linked, PE overrides public DNS → no public internet path.
-
Service Tags in NSG rules:
- Using Storage avoids hardcoding changing IP ranges.
-
DNS dependency for PE:
- Without Private DNS Zone, your VM may resolve storage to a public IP, bypassing PE.
- Validate:
nslookup <storageaccount>.blob.core.windows.net
→ private IP.
-
NAT Gateway scope:
- NAT GW is subnet-level in Azure (unlike OCI’s VCN-level NAT).
- Any VM in the associated subnet without a public IP uses that NAT for outbound.
-
PE works without internet:
- Even if you blackhole
0.0.0.0/0
, PE still works — Azure injects a/32
route for the PE IP.
- Even if you blackhole
-
Effective routes:
- Always check NIC → Effective routes to confirm NAT GW and PE routes are present.
- Prefer Azure Bastion for admin — removes need for jump hosts with public IPs.
- To restrict updates to specific domains, insert Azure Firewall and use FQDN rules (NSGs can’t filter by FQDN).
- Explicitly add Deny-All-Inbound & Deny-All-Outbound at low priority for clarity.
- Enable NSG Flow Logs for audit and troubleshooting.
- Use static NAT GW public IPs for allow-listing with external services.
- At scale, separate PE subnets for policy isolation.
-
DNS:
nslookup <acct>.blob.core.windows.net
→ private IP (privatelink
). -
Outbound IP:
curl https://ifconfig.io
→ shows NAT GW public IP. -
Blob Access:
azcopy
/SDK calls succeed via PE. -
Blocked test:
curl http://example.com:80
fails (NSG deny). -
Effective routes: NIC shows
0.0.0.0/0 → NAT GW
and/32
to PE.
[ VM (Private Subnet) ] | (TCP 443) v [ Private Endpoint: Blob ] ---> Microsoft Backbone ---> [ Azure Storage ] | | (TCP 443 via UDR) v [ NAT Gateway ] ---> Internet (Outbound only)
- Blob traffic → PE private IP (DNS via Private DNS Zone), stays private.
- Updates/repos → NAT Gateway → Internet (no inbound allowed).