Martin Rylko
  • Služby
  • Blog
  • O mně
  • Kontakt
  • Spolupráce
Martin Rylko

Senior Cloud Architect & DevOps Engineer. Specializace na Microsoft Azure, IaC, Cloud Security a AI.

Navigace

  • Služby
  • Blog
  • O mně
  • Kontakt

Spolupráce

Hledáte zkušeného architekta pro Váš Azure projekt? Ozvěte se.

rylko@cloudmasters.cz

© 2026 Martin Rylko. Všechna práva vyhrazena.

Buduji v cloudu. Nasazuji přes Azure Static Web Apps.

Domů/Blog/Azure Landing Zone Networking: Hub-Spoke s Firewallem
Všechny článkyRead in English

Azure Landing Zone Networking: Hub-Spoke s Firewallem

15. 4. 2025 5 min
#Azure#Landing Zone#Networking#Hub-Spoke#Bicep

Po nasazení základů Landing Zone z prvního dílu přijde fáze, která rozhodne o tom, jestli budete mít infrastrukturu pod kontrolou, nebo jestli za půl roku budete zjišťovat, proč osm týmů provozuje osm různých firewallů s osmi různými konfiguracemi DNS. V českém enterprise prostředí, kde se navíc řeší NIS2 a požadavky na viditelnost síťového provozu, je centralizovaná hub-spoke architektura prakticky nutnost.

Náročnost: 3-5 dní na kompletní hub-spoke nasazení včetně pravidel firewallu Náklady: cca 850 $/měsíc (Azure Firewall Basic: 650 $, VPN Gateway: 140 $, Private DNS: 25 $, peering: cca 35 $) Předpoklady: Dokončený základ Landing Zone (1. díl), Azure subscription s rolí Contributor na connectivity subscription, VS Code s Bicep rozšířením

Co se změnilo v roce 2025

Tři zásadní novinky mění pravidla hry pro hub-spoke nasazení.

Azure Firewall Basic SKU je v GA. Dříve byla nejlevnější varianta Standard za zhruba 912 $/měsíc. Basic vychází na přibližně 650 $ a nabízí stejné L3/L4 filtrování -- jen s limitem propustnosti 250 Mbps a bez IDPS signatur. Pro české středně velké firmy s jednotkami spoke VNetů to většinou bohatě stačí.

Azure Virtual Network Manager je obecně dostupný. Končí éra ručního peeringu přes Bicep smyčky. AVNM umožňuje definovat hub-spoke nebo mesh topologie deklarativně a automaticky spravuje peering. Nové spoke VNety se díky dynamickému členství skupin (na základě tagů) propeerují samy.

Private DNS Resolver nahrazuje conditional forwardery. Provozovat BIND nebo Windows DNS servery v hub VNetu pro on-premises DNS rezoluci už nemá smysl. Azure DNS Private Resolver poskytuje inbound a outbound endpointy přímo v hub VNetu za zlomek provozní náročnosti.

Proč na tom záleží

Bez sdíleného hubu si každý aplikační tým řeší síťování po svém. Viděl jsem to u jednoho výrobního podniku v Brně, kde šest vývojových týmů provozovalo infrastrukturu nezávisle:

PřístupMěsíční nákladyProvozní režie
Sdílený hub-spoke (1 firewall)cca 850 $Centrální tým spravuje pravidla
Firewall na každý spoke (6 týmů)cca 5 500 $Každý tým spravuje svá pravidla
Bez firewallu (přímý internet)cca 50 $Nulová viditelnost, neprošlo auditem

Varianta s per-spoke firewally měla navíc šest různých sad pravidel, šest různých log konfigurací a šest týmů, které DNS řešily každý jinak. Když auditor NIS2 požadoval přehled veškerého egress provozu za 90 dní, trvalo tři dny jen shromáždění logů.

Hub-spoke toto centralizuje: jeden firewall, jedna DNS konfigurace, jedna sada route tabulek, jedno místo kam se podívat, když něco nefunguje.

Implementace: Hub-Spoke v Bicep modulech

Architektura se skládá ze čtyř Bicep modulů: hub VNet, spoke VNet(y), Azure Firewall s policy a Private DNS zóny.

Hub VNet modul

// modules/network/hub-vnet.bicep
// Nasazení hub virtuální sítě s požadovanými subnety
 
@description('Azure region pro hub nasazení')
param location string = 'westeurope'
 
@description('Identifikátor prostředí')
param environmentType string = 'prod'
 
@description('Adresní prostor hub VNetu')
param hubAddressPrefix string = '10.0.0.0/16'
 
resource hubVnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: 'vnet-hub-${location}-001'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [hubAddressPrefix]
    }
    subnets: [
      {
        name: 'AzureFirewallSubnet'
        properties: {
          addressPrefix: '10.0.1.0/26'
        }
      }
      {
        name: 'GatewaySubnet'
        properties: {
          addressPrefix: '10.0.2.0/27'
        }
      }
      {
        name: 'AzureBastionSubnet'
        properties: {
          addressPrefix: '10.0.3.0/26'
        }
      }
      {
        name: 'snet-dns-inbound-${location}'
        properties: {
          addressPrefix: '10.0.4.0/28'
          delegations: [
            {
              name: 'Microsoft.Network.dnsResolvers'
              properties: {
                serviceName: 'Microsoft.Network/dnsResolvers'
              }
            }
          ]
        }
      }
    ]
  }
}
 
output hubVnetId string = hubVnet.id
output hubVnetName string = hubVnet.name
output firewallSubnetId string = hubVnet.properties.subnets[0].id

Název AzureFirewallSubnet je povinný -- Azure odmítne jakýkoliv jiný název subnetu pro firewall. Totéž platí pro GatewaySubnet. Při prvním nasazení Landing Zone jsem si tím prošel: pojmenoval jsem subnet snet-firewall a dostal jsem chybu, která neukazovala na název subnetu, ale na neplatnou subnet konfiguraci.

Spoke VNet modul s peeringem

// modules/network/spoke-vnet.bicep
// Nasazení spoke VNetu a konfigurace obousměrného peeringu s hubem
 
@description('Identifikátor spoke, např. app01, data01')
param spokeName string
 
@description('Resource ID hub VNetu pro peering')
param hubVnetId string
 
@description('Název hub VNetu pro referenci peeringu')
param hubVnetName string
 
param location string = 'westeurope'
param spokeAddressPrefix string
 
resource spokeVnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: 'vnet-spoke-${spokeName}-${location}-001'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [spokeAddressPrefix]
    }
    subnets: [
      {
        name: 'snet-default-${spokeName}'
        properties: {
          addressPrefix: spokeAddressPrefix
          routeTable: {
            id: spokeRouteTable.id
          }
        }
      }
    ]
  }
}
 
// Směrování veškerého provozu přes hub firewall
resource spokeRouteTable 'Microsoft.Network/routeTables@2023-11-01' = {
  name: 'rt-spoke-${spokeName}-${location}'
  location: location
  properties: {
    disableBgpRoutePropagation: true
    routes: [
      {
        name: 'route-to-firewall'
        properties: {
          addressPrefix: '0.0.0.0/0'
          nextHopType: 'VirtualAppliance'
          nextHopIpAddress: '10.0.1.4' // Privátní IP Azure Firewallu
        }
      }
    ]
  }
}
 
// Spoke -> Hub peering
resource spokeToHub 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2023-11-01' = {
  parent: spokeVnet
  name: 'peer-${spokeName}-to-hub'
  properties: {
    remoteVirtualNetwork: {
      id: hubVnetId
    }
    allowForwardedTraffic: true
    allowGatewayTransit: false
    useRemoteGateways: true
  }
}
 
output spokeVnetId string = spokeVnet.id

To disableBgpRoutePropagation: true na route tabulce je něco, co zapomenete přesně jednou. Bez toho BGP routy z VPN Gateway přepíšou vaše user-defined routy a provoz obejde firewall. Logy firewallu budou ukazovat nulový provoz, zatímco všechno běží -- až do bezpečnostního auditu.

Azure Firewall s Policy

// modules/network/firewall.bicep
// Nasazení Azure Firewall Basic s kolekcemi aplikačních a síťových pravidel
 
param location string = 'westeurope'
param firewallSubnetId string
param skuTier string = 'Basic'
 
resource fwPublicIp 'Microsoft.Network/publicIPAddresses@2023-11-01' = {
  name: 'pip-fw-hub-${location}-001'
  location: location
  sku: {
    name: 'Standard'
  }
  properties: {
    publicIPAllocationMethod: 'Static'
  }
}
 
resource fwPolicy 'Microsoft.Network/firewallPolicies@2023-11-01' = {
  name: 'fwpol-hub-${location}-001'
  location: location
  properties: {
    sku: {
      tier: skuTier
    }
    threatIntelMode: 'Alert'
  }
}
 
resource networkRuleCollection 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-11-01' = {
  parent: fwPolicy
  name: 'rcg-network-baseline'
  properties: {
    priority: 200
    ruleCollections: [
      {
        ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
        name: 'rc-allow-spoke-to-spoke'
        priority: 210
        action: {
          type: 'Allow'
        }
        rules: [
          {
            ruleType: 'NetworkRule'
            name: 'allow-rfc1918'
            sourceAddresses: ['10.0.0.0/8']
            destinationAddresses: ['10.0.0.0/8']
            destinationPorts: ['*']
            ipProtocols: ['TCP', 'UDP']
          }
        ]
      }
    ]
  }
}
 
resource appRuleCollection 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-11-01' = {
  parent: fwPolicy
  name: 'rcg-application-baseline'
  dependsOn: [networkRuleCollection]
  properties: {
    priority: 300
    ruleCollections: [
      {
        ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
        name: 'rc-allow-azure-management'
        priority: 310
        action: {
          type: 'Allow'
        }
        rules: [
          {
            ruleType: 'ApplicationRule'
            name: 'allow-azure-management'
            sourceAddresses: ['10.0.0.0/8']
            protocols: [
              {
                protocolType: 'Https'
                port: 443
              }
            ]
            targetFqdns: [
              'management.azure.com'
              'login.microsoftonline.com'
              '*.blob.core.windows.net'
            ]
          }
        ]
      }
    ]
  }
}
 
resource firewall 'Microsoft.Network/azureFirewalls@2023-11-01' = {
  name: 'fw-hub-${location}-001'
  location: location
  properties: {
    sku: {
      name: 'AZFW_VNet'
      tier: skuTier
    }
    firewallPolicy: {
      id: fwPolicy.id
    }
    ipConfigurations: [
      {
        name: 'fw-ipconfig'
        properties: {
          subnet: {
            id: firewallSubnetId
          }
          publicIPAddress: {
            id: fwPublicIp.id
          }
        }
      }
    ]
  }
}
 
output firewallPrivateIp string = firewall.properties.ipConfigurations[0].properties.privateIPAddress

Důležitý detail: dependsOn: [networkRuleCollection] na kolekcí aplikačních pravidel. Firewall policy rule collection groups se nasazují paralelně a Azure vrátí conflict error, pokud se dvě kolekce pokusí zapsat současně. V malém testovacím nasazení se to neprojeví, ale v CI/CD pipeline to padá pravidelně.

Výsledky z praxe

Po nasazení hub-spoke topologie pro středně velkou českou SaaS firmu se čtyřmi spoke VNety (aplikace, data, sdílené služby, staging) vypadá výstup z Azure CLI takto:

$ az network firewall show \
    --name fw-hub-westeurope-001 \
    --resource-group rg-connectivity-prod \
    --query '{name:name, sku:sku.tier, provisioningState:provisioningState, privateIp:ipConfigurations[0].privateIPAddress, threatIntelMode:threatIntelMode}' \
    --output table

Name                      Sku    ProvisioningState    PrivateIp    ThreatIntelMode
------------------------  -----  -------------------  -----------  -----------------
fw-hub-westeurope-001     Basic  Succeeded            10.0.1.4     Alert

Měsíční účet za celý hub networking stack se ustálil na:

ZdrojMěsíční náklady
Azure Firewall Basic648,00 $
VPN Gateway (VpnGw1)138,70 $
Private DNS Zones (4 zóny)24,00 $
VNet Peering (4 spoke, cca 500 GB)35,00 $
Public IP (Standard, statická)3,65 $
Celkem849,35 $

Nejzákeřnější problém, na který jsme narazili: chyba SubnetNotInSameVnet při zakládání peeringu. Bicep deployment se pokusil vytvořit peering dříve, než se subnet spoke VNetu plně zprovoznil. Řešením bylo přidat explicitní dependsOn na peering resource odkazující na spoke VNet -- implicitní závislost přes parent: spokeVnet nestačila, protože subnety jsou inline resources.

Klíčové poznatky

  • Začněte s Azure Firewall Basic, pokud nepotřebujete IDPS nebo TLS inspekci. SKU lze upgradovat bez nutnosti redeploymentu.
  • Vždy vypněte BGP route propagation na spoke route tabulkách. Bez toho BGP routy z VPN Gateway přepíšou vaše UDR a provoz tiše obejde firewall.
  • Používejte Private DNS Resolver místo DNS serverů. Provozní režie údržby BIND nebo Windows DNS forwarderů v hub VNetu se už nevyplatí.
  • Pro NIS2 compliance je centrální firewall s jednotnými logy zásadní -- auditní stopa egress provozu z jednoho místa výrazně zjednodušuje reporting.
  • Hub rozpočtujte jako sdílený platformní náklad, ne jako účet pro jednotlivé aplikační týmy. Jakmile začnete firewall náklady dělit per-spoke, týmy budou hledat cesty jak hub obejít.

Se základy z prvního dílu a funkční hub-spoke sítí máte infrastrukturu pod kontrolou. Dalším krokem je governance vrstva -- Azure Policy a compliance dashboardy, které pokryjeme v třetím dílu série. Pokud chcete urychlit cestu ke cloudové infrastruktuře, náš konzultační tým pro cloudovou architekturu pokrývá celý životní cyklus Landing Zone nasazení.

Tagy:#Azure#Landing Zone#Networking#Hub-Spoke#Bicep
LinkedInX / Twitter

O autorovi

Martin Rylko

Martin Rylko

Senior Cloud Architect & DevOps Engineer

Více než 14 let v IT – od on-premises datacenter a Hyper-V clusteringu po cloudovou infrastrukturu v Microsoft Azure. Specializuji se na Landing Zones, IaC automatizaci, Kubernetes a bezpečnostní compliance.

Email LinkedInCelý profil

Nejcastejsi dotazy

Kolik stojí Azure Firewall v hub-spoke Landing Zone?▾
Azure Firewall Basic SKU začíná přibližně na $282/měsíc (fixní náklad za nasazení) plus poplatky za zpracování dat. Standard SKU stojí asi $912/měsíc. Pro většinu počátečních Landing Zone nasazení doporučuji začít s Basic SKU a upgradovat na Standard, až budete potřebovat IDPS nebo TLS inspekci. Premium přidává dalších ~$500/měsíc za enterprise funkce.
Kdy je lepší hub-spoke a kdy Azure Virtual WAN?▾
Hub-spoke s vlastním hub VNetem vám dává plnou kontrolu nad routingem, pravidly firewallu a DNS -- ideální když potřebujete granulární síťové politiky a máte tým na správu. Virtual WAN je lepší při 10+ pobočkách nebo potřebě automatizovaného site-to-site VPN meshe. Pro většinu Landing Zone projektů s 2-5 spoke subskripcemi je klasický hub-spoke jednodušší a levnější.
Existují limity na VNet peering v Azure?▾
Každý VNet podporuje až 500 peering spojení, což pro většinu Landing Zones bohatě stačí. Skutečným omezením je plánování adresního prostoru -- překrývající se CIDR rozsahy mezi peerovanými VNety selžou. Doporučuji plánovat /16 pro hub a /20 na spoke, což dává prostor pro 4 096 hostů na spoke a 65 536 adres v hubu.
Jak řešit DNS překlad mezi spokes v hub-spoke topologii?▾
Nasaďte Azure Private DNS Zones propojené s hub VNetem a nakonfigurujte spoke VNety, aby používaly hub jako DNS server (nebo Azure Firewall DNS proxy). Tím centralizujete DNS překlad pro Private Endpoints a vlastní domény. Každý spoke by měl forwardovat DNS dotazy do hubu místo provozování vlastní DNS infrastruktury.

Mohlo by vás zajímat

Azure Landing Zone v Bicepu: Enterprise nasazení

Nasaďte enterprise-ready Azure Landing Zone pomocí Bicep modulů. Hub-spoke síťová architektura, governance politiky a integrace do CI/CD pipeline.

Číst

Azure Landing Zone Governance: Policy ve velkém

Azure Policy governance pro Landing Zones ve velkém měřítku. Vlastní definice politik, přiřazení iniciativ, compliance dashboardy a nákladové guardrails.

Číst

Bicep CI/CD: GitHub Actions pipeline pro Azure

Produkční deployment pipeline pro Bicep v GitHub Actions. What-if náhledy, schvalování prostředí, OIDC autentizace a rollback strategie.

Číst