Desafio 47: Hub-spoke com encadeamento de tráfego via NVA
90-120 minutos | ~$0,50/hora (múltiplas VMs + balanceador de carga) | Peso no exame: 15-20%
Cenário
Sua empresa adotou uma topologia de rede hub-spoke. Todo o tráfego spoke-para-spoke e spoke-para-internet deve ser inspecionado por um Dispositivo Virtual de Rede (NVA) baseado em Linux executando iptables na VNet hub. Você deve implantar duas instâncias de NVA atrás de um balanceador de carga interno para alta disponibilidade, configurar Rotas Definidas pelo Usuário (UDR) para encadear o tráfego através do NVA e implementar microssegmentação com Application Security Group (ASG) nos spokes.
Um requisito crítico é que o tráfego retornando do ambiente local via gateway VPN também deve atravessar o NVA -- prevenindo roteamento assimétrico.
Visão geral da arquitetura
Tarefa 1: Implantar a topologia hub-spoke
Azure CLI
# Variables
RG="rg-hubspoke-lab"
LOCATION="eastus"
HUB_VNET="vnet-hub"
SPOKE1_VNET="vnet-spoke1"
SPOKE2_VNET="vnet-spoke2"
# Create resource group
az group create --name $RG --location $LOCATION
# Create hub VNet with subnets
az network vnet create \
--resource-group $RG \
--name $HUB_VNET \
--address-prefixes 10.0.0.0/16 \
--subnet-name nva-subnet \
--subnet-prefixes 10.0.1.0/24 \
--location $LOCATION
az network vnet subnet create \
--resource-group $RG \
--vnet-name $HUB_VNET \
--name GatewaySubnet \
--address-prefixes 10.0.255.0/27
# Create spoke VNets
az network vnet create \
--resource-group $RG \
--name $SPOKE1_VNET \
--address-prefixes 10.1.0.0/16 \
--subnet-name workload-subnet \
--subnet-prefixes 10.1.1.0/24 \
--location $LOCATION
az network vnet create \
--resource-group $RG \
--name $SPOKE2_VNET \
--address-prefixes 10.2.0.0/16 \
--subnet-name workload-subnet \
--subnet-prefixes 10.2.1.0/24 \
--location $LOCATION
# Create hub-to-spoke1 peering (hub side)
az network vnet peering create \
--resource-group $RG \
--name hub-to-spoke1 \
--vnet-name $HUB_VNET \
--remote-vnet $SPOKE1_VNET \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--allow-gateway-transit true
# Create spoke1-to-hub peering (spoke side)
az network vnet peering create \
--resource-group $RG \
--name spoke1-to-hub \
--vnet-name $SPOKE1_VNET \
--remote-vnet $HUB_VNET \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--use-remote-gateways false
# Create hub-to-spoke2 peering (hub side)
az network vnet peering create \
--resource-group $RG \
--name hub-to-spoke2 \
--vnet-name $HUB_VNET \
--remote-vnet $SPOKE2_VNET \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--allow-gateway-transit true
# Create spoke2-to-hub peering (spoke side)
az network vnet peering create \
--resource-group $RG \
--name spoke2-to-hub \
--vnet-name $SPOKE2_VNET \
--remote-vnet $HUB_VNET \
--allow-vnet-access true \
--allow-forwarded-traffic true \
--use-remote-gateways false
Azure PowerShell
$rg = "rg-hubspoke-lab"
$location = "eastus"
New-AzResourceGroup -Name $rg -Location $location
# Create hub VNet
$nvaSub = New-AzVirtualNetworkSubnetConfig -Name "nva-subnet" -AddressPrefix "10.0.1.0/24"
$gwSub = New-AzVirtualNetworkSubnetConfig -Name "GatewaySubnet" -AddressPrefix "10.0.255.0/27"
$hubVnet = New-AzVirtualNetwork -Name "vnet-hub" -ResourceGroupName $rg `
-Location $location -AddressPrefix "10.0.0.0/16" -Subnet $nvaSub, $gwSub
# Create spoke VNets
$spoke1Sub = New-AzVirtualNetworkSubnetConfig -Name "workload-subnet" -AddressPrefix "10.1.1.0/24"
$spoke1Vnet = New-AzVirtualNetwork -Name "vnet-spoke1" -ResourceGroupName $rg `
-Location $location -AddressPrefix "10.1.0.0/16" -Subnet $spoke1Sub
$spoke2Sub = New-AzVirtualNetworkSubnetConfig -Name "workload-subnet" -AddressPrefix "10.2.1.0/24"
$spoke2Vnet = New-AzVirtualNetwork -Name "vnet-spoke2" -ResourceGroupName $rg `
-Location $location -AddressPrefix "10.2.0.0/16" -Subnet $spoke2Sub
# Create peerings
Add-AzVirtualNetworkPeering -Name "hub-to-spoke1" `
-VirtualNetwork $hubVnet -RemoteVirtualNetworkId $spoke1Vnet.Id `
-AllowForwardedTraffic -AllowGatewayTransit
Add-AzVirtualNetworkPeering -Name "spoke1-to-hub" `
-VirtualNetwork $spoke1Vnet -RemoteVirtualNetworkId $hubVnet.Id `
-AllowForwardedTraffic
Add-AzVirtualNetworkPeering -Name "hub-to-spoke2" `
-VirtualNetwork $hubVnet -RemoteVirtualNetworkId $spoke2Vnet.Id `
-AllowForwardedTraffic -AllowGatewayTransit
Add-AzVirtualNetworkPeering -Name "spoke2-to-hub" `
-VirtualNetwork $spoke2Vnet -RemoteVirtualNetworkId $hubVnet.Id `
-AllowForwardedTraffic
Etapas no portal
- Crie um grupo de recursos chamado rg-hubspoke-lab em East US.
- Crie vnet-hub (10.0.0.0/16) com as sub-redes: nva-subnet (10.0.1.0/24) e GatewaySubnet (10.0.255.0/27).
- Crie vnet-spoke1 (10.1.0.0/16) com a sub-rede workload-subnet (10.1.1.0/24).
- Crie vnet-spoke2 (10.2.0.0/16) com a sub-rede workload-subnet (10.2.1.0/24).
- Para cada emparelhamento, navegue até a VNet, selecione Peerings, clique em Add e habilite Allow forwarded traffic e Allow gateway transit no lado do hub.
Tarefa 2: Implantar VMs NVA com encaminhamento de IP
O encaminhamento de IP deve ser habilitado em dois níveis para que um NVA funcione:
- Nível da NIC do Azure -- a configuração
--ip-forwarding truena interface de rede - Nível do sistema operacional --
sysctl net.ipv4.ip_forward=1dentro da VM Linux
Esquecer qualquer um dos níveis é uma causa frequente de o tráfego não fluir através do NVA.
Azure CLI
# Create NVA1
az vm create \
--resource-group $RG \
--name vm-nva1 \
--image Ubuntu2404 \
--size Standard_B2s \
--vnet-name $HUB_VNET \
--subnet nva-subnet \
--private-ip-address 10.0.1.4 \
--admin-username azureuser \
--generate-ssh-keys \
--no-wait
# Create NVA2
az vm create \
--resource-group $RG \
--name vm-nva2 \
--image Ubuntu2404 \
--size Standard_B2s \
--vnet-name $HUB_VNET \
--subnet nva-subnet \
--private-ip-address 10.0.1.5 \
--admin-username azureuser \
--generate-ssh-keys \
--no-wait
# Enable IP forwarding on NVA1 NIC (Azure level)
az network nic update \
--resource-group $RG \
--name vm-nva1VMNic \
--ip-forwarding true
# Enable IP forwarding on NVA2 NIC (Azure level)
az network nic update \
--resource-group $RG \
--name vm-nva2VMNic \
--ip-forwarding true
Configurar encaminhamento de IP no nível do sistema operacional
Conecte-se via SSH em cada VM NVA e execute:
# Enable IP forwarding (immediate)
sudo sysctl -w net.ipv4.ip_forward=1
# Make persistent across reboots
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Configure iptables for NAT and forwarding
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -j ACCEPT
sudo iptables -A FORWARD -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Persist iptables rules
sudo apt-get install -y iptables-persistent
sudo netfilter-persistent save
Azure PowerShell
# Get the NIC and enable IP forwarding
$nic1 = Get-AzNetworkInterface -Name "vm-nva1VMNic" -ResourceGroupName $rg
$nic1.EnableIPForwarding = $true
Set-AzNetworkInterface -NetworkInterface $nic1
$nic2 = Get-AzNetworkInterface -Name "vm-nva2VMNic" -ResourceGroupName $rg
$nic2.EnableIPForwarding = $true
Set-AzNetworkInterface -NetworkInterface $nic2
Tarefa 3: Criar Rotas Definidas pelo Usuário
Azure CLI
# Create route table for spoke subnets
az network route-table create \
--resource-group $RG \
--name rt-spoke-to-nva \
--location $LOCATION \
--disable-bgp-route-propagation true
# Route all traffic to NVA (using ILB frontend IP for HA)
az network route-table route create \
--resource-group $RG \
--route-table-name rt-spoke-to-nva \
--name default-to-nva \
--address-prefix 0.0.0.0/0 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
# Route spoke1 traffic to NVA
az network route-table route create \
--resource-group $RG \
--route-table-name rt-spoke-to-nva \
--name spoke1-to-nva \
--address-prefix 10.1.0.0/16 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
# Route spoke2 traffic to NVA
az network route-table route create \
--resource-group $RG \
--route-table-name rt-spoke-to-nva \
--name spoke2-to-nva \
--address-prefix 10.2.0.0/16 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
# Associate route table with spoke subnets
az network vnet subnet update \
--resource-group $RG \
--vnet-name $SPOKE1_VNET \
--name workload-subnet \
--route-table rt-spoke-to-nva
az network vnet subnet update \
--resource-group $RG \
--vnet-name $SPOKE2_VNET \
--name workload-subnet \
--route-table rt-spoke-to-nva
# Create route table for GatewaySubnet (prevents asymmetric routing)
az network route-table create \
--resource-group $RG \
--name rt-gateway-to-nva \
--location $LOCATION
az network route-table route create \
--resource-group $RG \
--route-table-name rt-gateway-to-nva \
--name spoke1-via-nva \
--address-prefix 10.1.0.0/16 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
az network route-table route create \
--resource-group $RG \
--route-table-name rt-gateway-to-nva \
--name spoke2-via-nva \
--address-prefix 10.2.0.0/16 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
az network vnet subnet update \
--resource-group $RG \
--vnet-name $HUB_VNET \
--name GatewaySubnet \
--route-table rt-gateway-to-nva
Azure PowerShell
# Create route table for spokes
$rtSpoke = New-AzRouteTable -Name "rt-spoke-to-nva" -ResourceGroupName $rg `
-Location $location -DisableBgpRoutePropagation
Add-AzRouteConfig -RouteTable $rtSpoke -Name "default-to-nva" `
-AddressPrefix "0.0.0.0/0" -NextHopType "VirtualAppliance" `
-NextHopIpAddress "10.0.1.10" | Set-AzRouteTable
# Associate with spoke1 subnet
$spoke1Vnet = Get-AzVirtualNetwork -Name "vnet-spoke1" -ResourceGroupName $rg
Set-AzVirtualNetworkSubnetConfig -VirtualNetwork $spoke1Vnet `
-Name "workload-subnet" -AddressPrefix "10.1.1.0/24" `
-RouteTableId $rtSpoke.Id | Set-AzVirtualNetwork
# Create GatewaySubnet route table (asymmetric routing prevention)
$rtGw = New-AzRouteTable -Name "rt-gateway-to-nva" -ResourceGroupName $rg `
-Location $location
Add-AzRouteConfig -RouteTable $rtGw -Name "spoke1-via-nva" `
-AddressPrefix "10.1.0.0/16" -NextHopType "VirtualAppliance" `
-NextHopIpAddress "10.0.1.10" | Set-AzRouteTable
Tarefa 4: Implantar balanceador de carga interno para alta disponibilidade do NVA
Azure CLI
# Create internal load balancer
az network lb create \
--resource-group $RG \
--name ilb-nva \
--sku Standard \
--vnet-name $HUB_VNET \
--subnet nva-subnet \
--frontend-ip-name fe-nva \
--private-ip-address 10.0.1.10 \
--backend-pool-name bp-nva
# Create health probe
az network lb probe create \
--resource-group $RG \
--lb-name ilb-nva \
--name probe-nva \
--protocol Tcp \
--port 22 \
--interval 5 \
--threshold 2
# Create HA ports rule (forwards ALL traffic)
az network lb rule create \
--resource-group $RG \
--lb-name ilb-nva \
--name rule-ha-ports \
--protocol All \
--frontend-port 0 \
--backend-port 0 \
--frontend-ip-name fe-nva \
--backend-pool-name bp-nva \
--probe-name probe-nva \
--enable-floating-ip false
# Add NVA NICs to backend pool
az network nic ip-config update \
--resource-group $RG \
--nic-name vm-nva1VMNic \
--name ipconfig1 \
--lb-address-pools bp-nva \
--lb-name ilb-nva
az network nic ip-config update \
--resource-group $RG \
--nic-name vm-nva2VMNic \
--name ipconfig1 \
--lb-address-pools bp-nva \
--lb-name ilb-nva
Azure PowerShell
# Create internal LB
$feIP = New-AzLoadBalancerFrontendIpConfig -Name "fe-nva" `
-PrivateIpAddress "10.0.1.10" `
-SubnetId ($hubVnet.Subnets | Where-Object Name -eq "nva-subnet").Id
$bePool = New-AzLoadBalancerBackendAddressPoolConfig -Name "bp-nva"
$probe = New-AzLoadBalancerProbeConfig -Name "probe-nva" `
-Protocol Tcp -Port 22 -IntervalInSeconds 5 -ProbeCount 2
$lbRule = New-AzLoadBalancerRuleConfig -Name "rule-ha-ports" `
-FrontendIpConfiguration $feIP -BackendAddressPool $bePool `
-Probe $probe -Protocol All -FrontendPort 0 -BackendPort 0
New-AzLoadBalancer -Name "ilb-nva" -ResourceGroupName $rg `
-Location $location -Sku Standard `
-FrontendIpConfiguration $feIP -BackendAddressPool $bePool `
-Probe $probe -LoadBalancingRule $lbRule
Tarefa 5: Configurar microssegmentação baseada em ASG nos spokes
Azure CLI
# Create ASGs
az network asg create \
--resource-group $RG \
--name asg-web \
--location $LOCATION
az network asg create \
--resource-group $RG \
--name asg-app \
--location $LOCATION
az network asg create \
--resource-group $RG \
--name asg-db \
--location $LOCATION
# Create NSG with ASG-based rules
az network nsg create \
--resource-group $RG \
--name nsg-spoke1-workload \
--location $LOCATION
# Allow web tier to app tier on port 8080
az network nsg rule create \
--resource-group $RG \
--nsg-name nsg-spoke1-workload \
--name allow-web-to-app \
--priority 100 \
--direction Inbound \
--source-asgs asg-web \
--destination-asgs asg-app \
--destination-port-ranges 8080 \
--protocol Tcp \
--access Allow
# Allow app tier to db tier on port 1433
az network nsg rule create \
--resource-group $RG \
--nsg-name nsg-spoke1-workload \
--priority 110 \
--name allow-app-to-db \
--direction Inbound \
--source-asgs asg-app \
--destination-asgs asg-db \
--destination-port-ranges 1433 \
--protocol Tcp \
--access Allow
# Deny all other intra-subnet traffic
az network nsg rule create \
--resource-group $RG \
--nsg-name nsg-spoke1-workload \
--name deny-all-inbound \
--priority 4000 \
--direction Inbound \
--source-address-prefixes "*" \
--destination-address-prefixes "*" \
--destination-port-ranges "*" \
--protocol "*" \
--access Deny
# Associate NSG with subnet
az network vnet subnet update \
--resource-group $RG \
--vnet-name $SPOKE1_VNET \
--name workload-subnet \
--network-security-group nsg-spoke1-workload
Quebra & conserta
Cenário 1: Tráfego não flui através do NVA
Sintoma: VMs no spoke1 não conseguem alcançar VMs no spoke2, mesmo com o emparelhamento configurado e as UDRs apontando para o NVA.
Causa raiz: O encaminhamento de IP está habilitado na NIC do Azure, mas não dentro do sistema operacional Linux.
Diagnóstico:
# Check Azure NIC level
az network nic show \
--resource-group $RG \
--name vm-nva1VMNic \
--query "enableIPForwarding"
# SSH into NVA and check OS level
cat /proc/sys/net/ipv4/ip_forward
# Returns 0 if disabled
Correção:
# Inside the NVA VM
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
Cenário 2: Roteamento assimétrico a partir do ambiente local
Sintoma: Clientes locais conseguem iniciar conexões com VMs nos spokes, mas os pacotes de resposta seguem um caminho diferente (contornando o NVA). A inspeção stateful no NVA descarta o tráfego de retorno.
Causa raiz: O GatewaySubnet não possui uma UDR apontando os prefixos dos spokes para o NVA. O gateway envia o tráfego diretamente para o spoke via emparelhamento em vez de passar pelo NVA.
Correção:
# Create and associate route table on GatewaySubnet
az network route-table create \
--resource-group $RG \
--name rt-gateway-to-nva \
--location $LOCATION
az network route-table route create \
--resource-group $RG \
--route-table-name rt-gateway-to-nva \
--name spoke1-via-nva \
--address-prefix 10.1.0.0/16 \
--next-hop-type VirtualAppliance \
--next-hop-ip-address 10.0.1.10
az network vnet subnet update \
--resource-group $RG \
--vnet-name $HUB_VNET \
--name GatewaySubnet \
--route-table rt-gateway-to-nva
Cenário 3: Tráfego spoke-para-spoke falhando
Sintoma: O tráfego do spoke1 alcança o NVA, mas nunca chega ao spoke2.
Causa raiz: O emparelhamento do hub para o spoke2 não possui --allow-forwarded-traffic true. Como o tráfego chega ao NVA do hub (encaminhado do spoke1), o emparelhamento hub-para-spoke2 o descarta.
Correção:
az network vnet peering update \
--resource-group $RG \
--name hub-to-spoke2 \
--vnet-name $HUB_VNET \
--set allowForwardedTraffic=true
Verificação de conhecimento
1. Um NVA implantado no Azure não está encaminhando tráfego entre sub-redes. A NIC do Azure tem o encaminhamento de IP habilitado. Qual é a causa mais provável?
2. Qual tipo de próximo salto da UDR você deve usar ao rotear tráfego para um NVA?
3. Você tem uma topologia hub-spoke com um gateway VPN no hub. O tráfego on-premises para VMs spoke ignora o NVA no caminho de retorno. O que você deve fazer?
4. Qual configuração de peering de VNet deve ser habilitada no lado do hub para permitir tráfego spoke-to-spoke através de um NVA?
5. Você implanta dois NVAs atrás de um Standard Load Balancer interno para alta disponibilidade. Qual configuração de regra de balanceamento permite que TODOS os protocolos e portas sejam encaminhados?
6. Por que você deve definir --disable-bgp-route-propagation true nas tabelas de rotas dos spokes?
Limpeza
az group delete --name $RG --yes --no-wait
Remove-AzResourceGroup -Name "rg-hubspoke-lab" -Force -AsJob
Este laboratório implanta múltiplas VMs (NVAs + VMs de carga de trabalho) e um Standard Load Balancer interno. O custo estimado é de aproximadamente $0,50/hora. Exclua o grupo de recursos imediatamente após concluir o laboratório para evitar cobranças inesperadas.