Nasazení minimální hub-spoke topologie v Azure - část 4

2.11.2026

Do hub-spoke topologie přidáme Azure VPN Gateway pro vzdálený přístup (point-to-site) s ověřováním přes Entra ID a podporou DNS.

Slovník

Azure Landing Zone (ALZ) Ověřená a doporučená architektura pro řízení, zabezpečení a škálování Azure prostředí s více subskripcemi. Skládá se z platform landing zóny, která tvoří centrální základ se sdílenými službami, a z workload landing zón, kam se nasazují aplikace v rámci definovaných pravidel.
Hub-spoke topologie Doporučená síťová topologie v Azure, kde je centrální síť (hub) propojena s dalšími sítěmi (spokes). Alternativou je Virtual WAN.
Azure VPN Gateway Služba, která umožňuje bezpečné a šifrované spojení virtuální sítě s lokální on-prem sítí (site-to-site, S2S), se vzdálenými uživateli (point-to-site, P2S) nebo s dalšími virtuálními sítěmi (VNet-to-VNet).
Azure DNS Private Resolver Spravovaná služba, která umožňuje překlad DNS názvů mezi Azure a lokální (on-prem) sítí v obou směrech a také překlad Azure názvů pro vzdálené uživatele připojené přes VPN (point-to-site, P2S).
  • Inbound endpoint má privátní IP adresu ve virtuální síti a přijímá DNS dotazy z on-prem sítě a od P2S uživatelů, které jsou pak překládány pomocí Azure DNS, včetně privátních zón.
  • Outbound endpoint na základě forwarding pravidel přeposílá dotazy z Azure sítě na zvolené DNS servery, například v on-prem síti.

Obsah

Úvod

V předchozím článku jsme do hub-spoke topologie přidali Azure Firewall, kterým jsme nahradili původní linuxový router. Dále jsme nastavili hierarchii management groups a Azure Policy. Dnes přidáme Azure VPN Gateway pro vzdálený přístup (point-to-site) s ověřováním přes Entra ID a překladem názvů přes Azure DNS Private Resolver.
Detail změny

Příprava prostředí

V Azure portálu bychom již měli mít vytvořené subskripce Management, Connectivity, app1-dev a app2-dev. Dále musíme mít nainstalované Azure CLI a Bicep CLI. Veškeré příkazy v článku spouštíme z PowerShell terminálu.
winget install --exact --id "Microsoft.AzureCLI" 
az bicep upgrade
Stáhneme si projekt s deployment scripty.
git clone "https://github.com/Ninjanaut/azure-hub-spoke-bicep-template-04.git"
Oproti předchozí části projekt obsahuje změnu, kdy se parametr addressPrefix z původních souborů landing-zones/app1-dev.bicepparam a landing-zones/app2-dev.bicepparam přesunul nově do konfiguračního souboru config/platform.json.
landingZones.app1-dev.addressPrefix: 10.0.4.0/22
landingZones.app2-dev.addressPrefix: 10.0.8.0/22
Důvodem je, že hodnoty nově vstupují nejen do deploymentu aplikace 1 a 2, ale i do hub deploymentu, kde se vytvoří VPN Gateway s nastavenou routovací tabulkou na tyto subnety. V souboru platform.json musíme dále nastavit tyto hodnoty:
tenantId
sshPublicKeyPath
testUserUpn
management.subscriptionId
connectivity.subscriptionId
landingZones.app1-dev.subscriptionId
landingZones.app2-dev.subscriptionId
Vyplněné hodnoty se pak načítají v souboru platform.bicep a vstupují do deploymentu.

Deployment

Pokud nemáme nastaveno z předchozího článku, nejdříve připravíme uživatele a skupiny v Entra ID. Poté vytvoříme management group hierarchii a přiřadíme do ní subskripce. Dále nasadíme politiky (Azure Policy) a nakonec spustíme deployment do všech prostředí (management, hub, app1, app2). Pokud pokračujeme v předchozím článku, stačí spustit pouze poslední skript deploy.ps1. Skripty v sobě obsahují kontroly a je možné je spustit opakovaně, aniž by vznikaly duplicity. Pomocí parametrů lze také určit, které služby se nasadí. Nasazení DNS Private Resolveru a Bastionu se řídí v souboru platform/connectivity/main.bicepparam parametry deployDnsResolver a deployBastion. O nasazení VPN Gateway rozhoduje parametr vpnGatewayEnabled v souboru config/platform.bicep.

# Přihlásíme se do Azure
az login --tenant "<tenant-id>"

# Vytvoříme testovacího uživatele a security groups, do kterých ho přidáme.
# ID vytvořených skupin se automaticky uloží do souboru config/platform.json.
./scripts/setup-entra.ps1

# Vytvoříme management group hierarchii a přiřadíme do ní subskripce.
./scripts/setup-management-groups.ps1   

# Na Corp management group skupině nastavíme politiky (Azure Policy).
./scripts/deploy-governance.ps1

# Nasazení do management, hub, app1 a app2 subskripcí.
./scripts/deploy.ps1

Oproti první, druhé a třetí části se navíc vytvoří následující resources:

Změny

VPN Gateway

Vytvořila se nová VPN Gateway se třemi veřejnými IP adresami a routovací tabulka, která směruje provoz od VPN klientů přes firewall do spoke sítí. Dvě IP adresy slouží pro active-active režim a budoucí site-to-site připojení, které zatím nemáme nastavené. Třetí adresa slouží pro P2S VPN klienty.
Routovací tabulka v gateway subnetu.

DNS Private Resolver

Vytvořila se nová služba DNS Private Resolver s inbound endpointem, na který je možné z VPN klienta posílat dotazy na překlad názvů.

Azure Firewall

Firewall zůstal beze změny, pouze přibylo pravidlo rc-allow-p2s-to-spokes, které VPN uživatelům povoluje komunikaci do spoke sítí přes ICMP a HTTPS protokoly.
Detail pravidla rc-allow-p2s-to-spokes

Vystavení webové služby

Pod admin účtem se přihlásíme do Azure portálu a pomocí Bastion služby se připojíme k virtuálnímu serveru aplikace 1. Na serveru spustíme jednoduchou webovou službu dostupnou přes HTTPS se self-signed certifikátem. Ke službě se pak pokusíme připojit z VPN klienta.
mkdir -p ~/demo/www && cd ~/demo

openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365 -subj "/CN=test"

echo "Hello from $(hostname)" > www/index.html
cat > server.py <<'EOF'
import http.server
import os
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("cert.pem", "key.pem")
os.chdir("www")
server = http.server.ThreadingHTTPServer(("0.0.0.0", 443), http.server.SimpleHTTPRequestHandler)
server.socket = context.wrap_socket(server.socket, server_side=True)
server.serve_forever()
EOF

sudo python3 server.py

Ověření připojení

Příprava profilu

Nejdříve ze strany platformy vygenerujeme a stáhneme VPN profil (vpnclientconfiguration.zip/AzureVPN/azurevpnconfig.xml).
az network vnet-gateway vpn-client generate `
  -g "rg-hub-shared" `
  -n "vgw-hub-shared-swedencentral-001" `
  --subscription "<hub-subscription-id>" `
  -o tsv
Profil ale neobsahuje nastavení DNS, což je IP adresa inbound endpointu našeho resolveru a název privátní zóny. Nahradíme tedy element <clientconfig i:nil="true" /> za nový element s DNS adresou a suffixem.
<clientconfig>
  <dnsservers><dnsserver>10.0.1.132</dnsserver></dnsservers>
  <dnssuffixes><dnssuffix>.hubspoke.internal</dnssuffix></dnssuffixes>
</clientconfig>

Instalace VPN klienta

U vzdáleného uživatele nainstalujeme VPN klienta.
winget install Microsoft.AzureVPNClient --source winget
Nainstalovaného klienta spustíme, naimportujeme upravený VPN profil azurevpnconfig.xml a připojíme se k VPN Gateway. VPN klient by měl mít správně nastavený DNS server s adresou inbound endpointu našeho DNS private resolveru a routování do obou spoke sítí.
Při generování VPN profilu se nastaví routy k hubu a ke spokům, které mají s hubem nastavený gateway transit peering. V případě změny topologie, například přidání dalšího spoku, je potřeba vygenerovat a importovat profil znovu. Routovací tabulka v GatewaySubnet nemá na nastavení rout ve VPN profilu vliv. S tímto by mohla pomoci aktuálně preview funkce disable peering route propagation, ale bude třeba ji vyzkoušet. VPN profil je také možné distribuovat přes Intune a je vhodné mít nastavené i MFA a Conditional Access politiku.

Test konektivity

Pod testovacím uživatelem, se kterým jsme se připojili do VPN, ověříme, že se můžeme připojit k virtuálnímu serveru aplikace 1 a vyzkoušíme si ping na DNS název a zobrazení webové stránky přes HTTPS. HTTPS používá self-signed certifikát, takže je potřeba potvrdit upozornění v prohlížeči.

Dealokace a smazání

Vzhledem k provozním nákladům můžeme Firewall dealokovat.
az account set --subscription "<hub-subscription-id>"
$fw = Get-AzFirewall -ResourceGroupName "rg-hub-shared" -Name "afw-hub-shared-swedencentral-001"
$fw.Deallocate()
Set-AzFirewall -AzureFirewall $fw
# Kontrola, dealokovaný fw by měl vrátit "0"
# (Get-AzFirewall -ResourceGroupName rg-hub-shared -Name afw-hub-shared-swedencentral-001).IpConfigurations.Count
Smazat službu Azure Bastion.
az account set --subscription "<hub-subscription-id>"
az network bastion delete -g "rg-hub-shared" -n "bas-hub-shared-swedencentral-001"
az network public-ip delete -g "rg-hub-shared" -n "pip-bas-hub-shared-swedencentral-001"
Smazat Azure DNS Private Resolver.
az account set --subscription "<hub-subscription-id>"
az extension add -n dns-resolver
az dns-resolver inbound-endpoint delete -g "rg-hub-shared" --dns-resolver-name "dnspr-hub-shared-swedencentral-001" -n "in-dnspr-hub-shared-swedencentral-001"
az dns-resolver delete -g "rg-hub-shared" -n "dnspr-hub-shared-swedencentral-001"
Smazat VPN Gateway. Po smazání je potřeba nastavit parametr vpnGatewayEnabled = false v souboru config/platform.bicep a udělat redeploy aplikace 1 a aplikace 2, pokud bychom chtěli, aby nám fungovala komunikace mezi jednotlivými spoke sítěmi.
az account set --subscription "<hub-subscription-id>"
az network vnet-gateway delete -g "rg-hub-shared" -n "vgw-hub-shared-swedencentral-001"
az network public-ip delete -g "rg-hub-shared" -n "pip-vgw-hub-shared-swedencentral-001-01"
az network public-ip delete -g "rg-hub-shared" -n "pip-vgw-hub-shared-swedencentral-001-02"
az network public-ip delete -g "rg-hub-shared" -n "vgw-hub-shared-swedencentral-001-pip3"
Dealokovat virtuální servery.
az vm deallocate -g "rg-spoke-app1-dev" -n "vm-conntest-app1-dev-swedencentral-001" --subscription "<app1-subscription-id>"
az vm deallocate -g "rg-spoke-app2-dev" -n "vm-conntest-app2-dev-swedencentral-001" --subscription "<app2-subscription-id>"
Případně můžeme smazat všechny vytvořené resources najednou příkazem:
./scripts/cleanup.ps1

Závěr

Nasadili jsme VPN Gateway v konfiguraci Point-to-Site (P2S) s ověřováním přes Entra ID. Dále jsme nasadili DNS Private Resolver, díky kterému mohou uživatelé připojení přes VPN používat privátní DNS názvy místo konkrétních IP adres.

Odkazy