Виртуальные сети и NSG

Разбираемся, как выглядит ваш собственный кусочек сети внутри дата-центра Microsoft: VNet, подсети, NSG-файрвол и схема, в которой база данных недоступна из интернета в принципе.

Virtual Network (VNet) — изолированная виртуальная сеть внутри Azure, где вы сами выбираете диапазон IP-адресов, режете его на подсети и решаете, кто с кем имеет право разговаривать.

Зачем это на практике

Пока вы поднимаете одну виртуалку «посмотреть», сеть кажется формальностью: Azure сам создаст VNet, сам выдаст адрес, всё заработает. Проблемы начинаются на втором ресурсе. Появляется база данных — и вопрос «а кто может к ней подключиться?» перестаёт быть теоретическим. По умолчанию сервис с публичным IP виден всему интернету, а интернет очень любознателен: боты находят открытый порт PostgreSQL за считанные минуты и начинают перебирать пароли.

Правильный ответ почти всегда один и тот же: наружу торчит только то, что обязано торчать наружу. Веб-приложение слушает 443-й порт — да, он открыт. База данных, кэш Redis, внутренний API, очередь — всё это живёт в приватной подсети и доступно только соседям по VNet. Такую границу в Azure рисуют двумя инструментами: VNet с подсетями (кто где физически находится) и NSG (кому что разрешено).

VNet и подсети: разметка адресов

VNet создаётся в одном регионе и в одной подписке. Вы задаёте адресное пространство в нотации CIDR — например, 10.20.0.0/16, это 65 536 адресов из приватного диапазона RFC 1918. Дальше этот кусок режется на подсети: 10.20.1.0/24 для веба, 10.20.2.0/24 для базы и так далее.

az group create --name rg-shop --location westeurope

# VNet сразу с первой подсетью
az network vnet create \
  --resource-group rg-shop \
  --name vnet-shop \
  --address-prefix 10.20.0.0/16 \
  --subnet-name snet-web \
  --subnet-prefix 10.20.1.0/24

# вторая подсеть — под базу
az network vnet subnet create \
  --resource-group rg-shop \
  --vnet-name vnet-shop \
  --name snet-db \
  --address-prefix 10.20.2.0/24

Здесь важна одна неочевидная деталь: Azure забирает себе 5 адресов в каждой подсети — первый (адрес сети), следующие три (шлюз и два внутренних DNS) и последний (broadcast). Поэтому в подсети /24 у вас не 256 полезных адресов, а 251. А модная попытка сэкономить и взять /29 (8 адресов) оставит вам целых три — это ловушка, в которую регулярно попадают на первом же масштабировании.

Второй момент: адресные пространства разных VNet не должны пересекаться, если вы когда-нибудь захотите их соединить (peering, VPN, подключение к офису). Поднять две сети 10.0.0.0/16 легко — а вот связать их потом уже нельзя, и переделка означает пересоздание ресурсов. Заведите себе привычку сразу разводить сети по разным диапазонам: 10.10.0.0/16 — dev, 10.20.0.0/16 — prod, и так далее.

Публичные и приватные IP

Приватный IP выдаётся из диапазона подсети, живёт вместе с сетевым интерфейсом и виден только внутри VNet (и связанных с ней сетей). Публичный IP — это отдельный ресурс Azure, за который вам выставляют счёт, даже если он ни к чему не привязан.

СвойствоПриватный IPПубличный IP
Откуда берётсяиз CIDR подсетиотдельный ресурс Microsoft.Network/publicIPAddresses
Кто видитресурсы VNet и связанных сетейвесь интернет
Стоимостьбесплатнопорядка 3–4 $ в месяц за адрес Standard
Типичное применениебаза, кэш, внутренний APIбалансировщик, Application Gateway, публичный веб

Про исходящий трафик тоже стоит знать заранее: первые 100 ГБ в месяц наружу бесплатны, дальше идёт оплата за гигабайт. А «неявный» выход в интернет без публичного IP Microsoft сворачивает — для новых развёртываний правильный путь наружу это NAT Gateway (порядка 33 $ в месяц плюс плата за обработанные данные). Учтите это в смете, а не постфактум.

NSG: файрвол на входе

Network Security Group (NSG) — набор правил «разрешить/запретить», который вешается на подсеть, на сетевой интерфейс (NIC) или сразу на оба. Каждое правило описывает: направление (входящее/исходящее), источник, назначение, порт, протокол, действие и приоритет — число от 100 до 4096.

Логика простая и жёсткая: правила проверяются по возрастанию приоритета, и первое совпавшее выигрывает. Дальше проверка не идёт. Если правило Deny с приоритетом 200 совпало — правило Allow с приоритетом 300 уже никого не спасёт.

az network nsg create --resource-group rg-shop --name nsg-web

# пускаем HTTPS из интернета
az network nsg rule create \
  --resource-group rg-shop \
  --nsg-name nsg-web \
  --name allow-https \
  --priority 100 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes Internet \
  --destination-port-ranges 443

# привязываем NSG к подсети
az network vnet subnet update \
  --resource-group rg-shop \
  --vnet-name vnet-shop \
  --name snet-web \
  --network-security-group nsg-web

Обратите внимание на --source-address-prefixes Internet. Это не литерал, а service tag — символическое имя для набора адресов, который поддерживает сам Microsoft. Кроме Internet есть VirtualNetwork, AzureLoadBalancer, Storage, Sql и десятки других. Использовать теги вместо захардкоженных диапазонов — почти всегда правильное решение: адреса Azure меняются, а тег остаётся.

В каждом NSG уже есть правила по умолчанию с приоритетами в районе 65000, их нельзя удалить, но можно перебить своими:

ПравилоПриоритетЧто делает
AllowVnetInBound65000разрешает весь трафик внутри VNet
AllowAzureLoadBalancerInBound65001пускает health-пробы балансировщика
DenyAllInBound65500запрещает всё остальное на вход
AllowInternetOutBound65001разрешает выход в интернет

Вывод из таблицы важный: снаружи по умолчанию не пускают никого, а изнутри наружу — пускают всех. Первое хорошо, второе — повод задуматься, если вы работаете с чувствительными данными.

Схема «веб снаружи, база внутри»

Соберём каноническую двухслойную топологию, которую вы будете повторять от проекта к проекту.

ПодсетьCIDRЧто живётВход разрешён
snet-web10.20.1.0/24веб-серверы, балансировщик443 из Internet
snet-db10.20.2.0/24PostgreSQL, Redis5432 только из 10.20.1.0/24
az network nsg create --resource-group rg-shop --name nsg-db

# база принимает подключения ТОЛЬКО из подсети веба
az network nsg rule create \
  --resource-group rg-shop \
  --nsg-name nsg-db \
  --name allow-pg-from-web \
  --priority 100 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes 10.20.1.0/24 \
  --destination-port-ranges 5432

# явный запрет всего остального (страховка и документация замысла)
az network nsg rule create \
  --resource-group rg-shop \
  --nsg-name nsg-db \
  --name deny-all-inbound \
  --priority 4000 \
  --direction Inbound \
  --access Deny \
  --protocol '*' \
  --source-address-prefixes '*' \
  --destination-port-ranges '*'

az network vnet subnet update --resource-group rg-shop --vnet-name vnet-shop --name snet-db --network-security-group nsg-db

У базы нет публичного IP вообще. Даже если завтра кто-то угадает пароль, ему просто некуда его вводить: до порта 5432 из интернета не доехать. Если база — не виртуалка, а управляемый сервис (Azure Database for PostgreSQL, Storage, Key Vault), тот же эффект даёт Private Endpoint: сервису выдаётся приватный адрес внутри вашей подсети, а публичный доступ выключается. Стоит это порядка 7–8 $ в месяц за эндпоинт плюс копейки за трафик — дёшево за то, чтобы убрать сервис из интернета.

А как же администратору попасть на машину без открытого SSH? Правильные варианты: Azure Bastion (доступ через браузер, без публичных IP на виртуалках) или Just-in-Time access из Microsoft Defender for Cloud, который открывает 22-й порт вашему IP на 3 часа и сам его закрывает.

Как это работает

NSG — это не отдельная железка и не виртуалка с iptables, за которую вы платите. Это правила, которые применяет SDN-стек на хосте-гипервизоре, прямо на пути пакета к вашей виртуальной сетевой карте. Поэтому сам NSG бесплатен и не создаёт узкого места: фильтрация распределена по всем хостам.

Три механизма, которые надо держать в голове:

  • NSG stateful. Разрешили входящий 443 — ответный трафик уйдёт автоматически, обратное исходящее правило писать не нужно. Соединение отслеживается целиком.
  • Двойная проверка. Для входящего трафика сначала применяется NSG подсети, потом NSG сетевой карты. Для исходящего — наоборот. Пакет должен пройти обе проверки. Классический «мистический» баг: правило есть, а трафик не идёт, потому что второй NSG о нём не знает.
  • Внутри подсети тоже фильтруется. Частое заблуждение — что NSG подсети работает только «на границе». Нет: трафик между двумя виртуалками одной подсети тоже проходит через правила.

Когда картина не сходится, не гадайте — спросите Azure, какие правила реально действуют на интерфейс:

az network nic list-effective-nsg --resource-group rg-shop --name nic-web-1 -o table

Частые ошибки

  • Открытый 22/3389 для 0.0.0.0/0. Самая массовая дыра в облаке. Боты находят порт за минуты. Используйте Bastion или JIT.
  • Путаница с приоритетами. Добавили Allow с приоритетом 300, а Deny с приоритетом 200 уже совпал раньше — правило не работает. Всегда смотрите на порядок чисел, а не на порядок в списке.
  • Пересекающиеся адресные пространства. Два 10.0.0.0/16 невозможно объединить peering'ом. Планируйте адресацию до того, как что-то создано.
  • Слишком узкие подсети. Помните про 5 служебных адресов; /29 оставит вам три штуки.
  • Деньги на забытых ресурсах. Публичный IP Standard тарифицируется, даже когда ни к чему не привязан. Azure Bastion в базовом SKU — это порядка 140 $ в месяц: включили «на посмотреть», забыли выключить, получили счёт. NAT Gateway и peering тоже платные, причём за peering платят обе стороны трафика.
  • Ожидать от NSG защиты уровня приложения. NSG работает с IP и портами, он не видит SQL-инъекцию в теле запроса. Для этого нужен Application Gateway с WAF или Azure Firewall.

Итоги

  • VNet — ваша приватная сеть в регионе; подсети режут её адресное пространство, Azure забирает 5 адресов из каждой.
  • Публичный IP — отдельный платный ресурс; всё, что не обязано смотреть в интернет, живёт без него.
  • NSG — stateful-файрвол на подсети и/или NIC; правила от 100 до 4096, первое совпавшее выигрывает, дефолт запрещает вход и разрешает выход.
  • Рабочая схема: веб в публичной подсети с 443, база — в приватной, доступна только из подсети веба; для PaaS-сервисов — Private Endpoint.
  • Сами VNet и NSG бесплатны; деньги едят публичные IP, Bastion, NAT Gateway и трафик peering.
Проверьте себя
1. На подсети висит NSG с правилом Deny (приоритет 200) на порт 5432 из любого источника и правилом Allow (приоритет 300) на 5432 из подсети веба. Что произойдёт с трафиком от веба к базе?
AТрафик пройдёт: Allow всегда сильнее Deny
BТрафик будет заблокирован: правило с меньшим приоритетом совпадает первым
CТрафик пройдёт: правила внутри одной VNet не проверяются
DAzure не даст создать такую пару правил
2. Сколько адресов доступно вашим ресурсам в подсети с диапазоном 10.20.1.0/24?
A256
B254
C251
D250