Miroslav Holec
Premium

Zamezení odchozího trafficu z VNetu do Internetu vyjma Azure služeb

Miroslav Holec   2. října 2017

Tento článek je již velmi zastaralý. Článek nemusí popisovat aktuální stav technologie, ideální řešení a můj současný pohled na dané téma.

Virtuální sítě a virtuální síťová rozhraní v Azure mohou mít na sebe napojeny tzv. Network Security Groups. Skupina se skládá z řady bezpečnostních pravidel, která povolují nebo zakazují definovaný síťový provoz. V určitých případech můžeme chtít zakázat odchozí provoz do Internetu, čímž se však odřízneme i od celé řady Azure služeb, které nemáme ve stejné síti. V tomto článku přiblížím problém a nastíním řešení.

Seznámení s NSG a NSG Rules

NSG (Network Security Group) je sada bezpečnostních pravidel. Každé samostatné pravidlo povoluje nebo zakazuje provoz dle konfigurace. Ta se skládá například z IP adresy, protokolu nebo typu služby (Virtuální síť, Internet, Load Balancer). Příklad pravidel je pěkně vidět na následující ukázce:

Ukázka NSG Rules

Pravidla se aplikují postupně dle nastavené priority. Nejprve se uplatňují pravidla s vyšším číslem až po ta nejnižší. Svá vlastní pravidla může správce definovat s prioritou 0-4096. Na úplném konci seznamu pak nalezneme tzv. Default Rules, která jsou definována vždy a mají nízkou prioritu (číslo přes 60000).

Ukázka vlastniho pravidla

Tato pravidla nelze odstranit ani měnit, ale lze je logicky přepsat vlastními pravidly s vyšší prioritou. Příkladem budiž dvě pravidla níže. S nízkou prioritou Default pravidlo je přepsáno vlastním pravidlem. Tak lze například zakázat veškerý Outbound traffic do Internetu:

Zakazani konektivity outbound inet

Kompletní sadu pravidel NSG lze připojit na Virtuální sítě nebo na Virtuální síťová rozhraní (NIC). V praxi lze tak aplikovat sadu pravidel pro virtuální síť a další specifická pravidla si definovat například pro virtuální počítače (každý virtuální stroj může mít v jeden okamžik jednu NIC). Více o infrastruktuře kolem virtuálních počítačů jsem popsal nedávno v článku:

Omezení trafficu do Internetu a problém dostupnosti Azure služeb

V ideálním případě bychom mohli založit virtuální síť a tu od Internetu zcela odříznout. Problém je v tom, že některé Azure služby do naší virtuální sítě neumístíme a odříznutím konektivity směrem ven ze sítě bychom se odřízli i od těchto služeb. Proto musíme aplikovat pravidla dle jednoduché logiky:

  1. Defaultně je povolená veškerá konektivita ven (toto pravidlo nelze smazat)
  2. Přidáme proto pravidlo, kterým veškerou konektivitu zakážeme (tím v podstatě přebijeme pravidlo č.1)
  3. Přidáme sadu dalších pravidel, kterými povolíme konektivitu směrem na některé IP adresy Azure služeb (tím přebijeme pravidlo č.2)

Nepříjemné je, že my nikdy nevíme, jaké IP adresy které služby budou mít. Často nás to ani nezajímá, protože pracujeme s DNS (například Azure Storage). V praxi tedy není jiná možnost, než si zajistit konektivitu tak, že povolíme zcela všechny rozsahy IP adres zcela všech Azure služeb v rámci zvoleného regionu. Seznam rozsahů si můžeme stáhnout v podobě XML:

Seznam IP adres datovych center a služeb v Azure

Omezení NSG na 200 pravidel

Nemilé je bohužel to, že těchto rozsahů je jen pro region West Europe přes 400 a NSG je omezena na 200 pravidel. Tento problém lze vyřešit pouze kontaktem Azure supportu a žádostí o navýšení počtu pravidel. Na požadavek tak lze dostat povolení až na 500 pravidel. Více o limitech v Azure se lze dočíst na stránce:

Návrh: Automatizace s Azure PS + VSTS Release Management

Druhá nepříjemnost je ta, že samotná představa ručního naklikání všech 400 pravidel samozřejmě není reálná. Nehledě na to, že rozsahy se mohou měnit nebo vznikat nové. Chceme automatizovat. A to je moment, kdy na scénu přichází Azure PowerShell. Při hledání řešení jsem vycházel ze zkušeností, které sdílel Keyth Mayer v článku:

Jeho řešení je interaktivní skript, který se po přihlášení do Azure doptává na konkrétní Subscription, Resource Group až po NSG a následně založí sadu pravidel pro danou NSG a provede update. Já jsem nicméně potřeboval chování upravit o možnost opakovaného spouštění nad předem známou konfigurací. Pro opakované spouštění mi přitom přijde ideální VSTS Release Management, kde jako trigger poslouží obyčejný scheduler s rozumnou rekurencí.

Řešení: Automatická aktualizace NSG Rules + kontinuální update

Řešení je z high-level pohledu velmi jednoduché:

  1. Pomocí PowerShellu napíšu skript, který všechno zařídí
  2. Založím VSTS Release Definition, která se bude skládat z jediného kroku: odpálení skriptu z kroku č. 1

1. PowerShell skript

Myšlenka skriptu je ve zkratce taková, že nejprve odstraním všechna pravidla vytvořená automatizací z minulosti, poté stáhnou XML s aktuálními rozsahy IP adres a následně tato rozsahy přidám jako nová pravidla k NSG. Znamená to, že NSG se nikdy nemění. Update pravidel se posílá na samotný konec jen pokud nedošlo k žádné chybě, čili nemusím se obávat, že se cokoliv provede "napůl". Samotný skript vypadá takto:

$subscriptionId = 'xxx'
$nsgName = 'xxx'
$rgName = 'xxx'

Select-AzureRmSubscription -SubscriptionId $subscriptionId
$nsg = Get-AzureRmNetworkSecurityGroup -Name $nsgName -ResourceGroupName $rgName

# Download current list of Azure Public IP ranges
$downloadUri = "https://www.microsoft.com/en-in/download/confirmation.aspx?id=41653"
$downloadPage = Invoke-WebRequest -Uri $downloadUri -UseBasicParsing
$xmlFileUri = ($downloadPage.RawContent.Split('"') -like "https://*PublicIps*")[0]

$response = Invoke-WebRequest -Uri $xmlFileUri -UseBasicParsing

# Get list of regions & public IP ranges
[xml]$xmlResponse = [System.Text.Encoding]::UTF8.GetString($response.Content)

$regions = $xmlResponse.AzurePublicIpAddresses.Region

#$selectedRegions = $regions.Name | Out-GridView -Title "Select Azure Datacenter Regions ..." -PassThru
$ipRange = ( $regions | where-object Name -In "europewest" ).IpRange

$rulePriority = 300
$counter = 1

ForEach ($rule in $nsg.SecurityRules | where-object Direction -Eq 'Outbound') {
    If($rule.Name -like '*AllowAzureOutbound_*'){
        Remove-AzureRmNetworkSecurityRuleConfig -Name $rule.Name -NetworkSecurityGroup $nsg

        Write-Host("REMOVED NSG RULE " + $rule.Name)
    }
}

ForEach ($subnet in $ipRange.Subnet) {

    $rulePriority++
    $counter++

    $ruleName = "AllowAzureOutbound_" + $subnet.Replace("/","-")

    $nsgRule = New-AzureRmNetworkSecurityRuleConfig `
            -Name $ruleName `
            -Description "Allow outbound to Azure $subnet" `
            -Access Allow `
            -Protocol * `
            -Direction Outbound `
            -Priority $rulePriority `
            -SourceAddressPrefix VirtualNetwork `
            -SourcePortRange * `
            -DestinationAddressPrefix "$subnet" `
            -DestinationPortRange *

    $nsg.SecurityRules += ,$nsgRule

    Write-Host("ADDED NSG RULE " + $subnet)

    If ($counter -gt 490)
    {
        break
    }
}

If (!$error) {
    Set-AzureRmNetworkSecurityGroup -NetworkSecurityGroup $nsg
} else {
    Write-Host("NOTHING CHANGED BECAUSE OF ERROR")
}

Samotný (plně funkční) skript je třeba brát s rezervou, protože nejsem PowerShell guru a pravděpodobně by se dal napsat mnohem elegantněji a defenzivněji.

2. VSTS Release Definition

Samotná Release Definition bude obsahovat jediné prostředí, v rámci kterého se provede jeden jediný task typu Azure PowerShell. Ten si zajistí připojení do Azure Subscription a spustí skript z kroku 1.

Release Definition s Taskem Azure PS

Vypadá to hezky a jednoduše, ale má to drobný háček. Současná verze tasku Azure PowerShell umožňuje vložit pouze inline skript o délce maximálně 500 znaků. Zde nezbývá, než trochu hackovat, otevřít v prohlížeči Developer konzoli a breaknout klientskou validaci. Nechápu na co tam je, protože ta serverová naštěstí bez problému projde.