VPC и правила файрвола
Разбираемся, как в Google Cloud устроена сеть: где живут виртуальные машины, кто может до них достучаться и почему один неаккуратный флаг открывает базу данных всему интернету.
VPC (Virtual Private Cloud) — ваша собственная виртуальная сеть внутри Google Cloud: изолированное адресное пространство, в котором ресурсы видят друг друга по приватным IP, а всё остальное решают правила файрвола.
Когда вы создаёте виртуальную машину, она не висит в вакууме. У неё есть сетевая карта, приватный IP-адрес, соседи по подсети и набор правил, которые разрешают или запрещают трафик. В своём датацентре за это отвечал бы админ с железным свитчом; в облаке — вы, парой команд gcloud. И это одновременно и удобно, и опасно: правило, которое открывает SSH всему миру, пишется на десять символов короче, чем правило, которое открывает его только вам.
Зачем вообще думать о сети
Типичный сценарий: приложение на виртуальной машине, база данных рядом, и очень не хочется, чтобы база торчала наружу. Практических задач ровно три:
- Изоляция. База должна отвечать только приложению, а не всему интернету. В облаке за это отвечает не «отдельный сервер за забором», а сеть и правила файрвола.
- Контролируемый вход. Веб-порты 80/443 открыты всем, SSH — только вам, всё остальное закрыто по умолчанию.
- Контролируемый выход. Машины без внешнего IP должны уметь скачивать пакеты и обновления — но не быть доступными снаружи.
Хорошая новость: сама VPC, подсети и правила файрвола в Google Cloud ничего не стоят. Платите вы за трафик наружу (egress) и за некоторые сетевые сервисы вроде Cloud NAT и балансировщиков. Входящий трафик бесплатен.
Как устроена VPC: глобальная сеть и региональные подсети
Здесь Google отличается от AWS, и это важно понять сразу. В GCP VPC — глобальная: одна сеть охватывает все регионы планеты. Внутри неё живут подсети (subnets), и вот они уже региональные — у каждой свой диапазон адресов и свой регион.
Что это даёт на практике: машина в europe-west1 и машина в us-central1, находящиеся в одной VPC, общаются по приватным адресам, без выхода в интернет и без VPN-туннелей между регионами. Никаких peering-плясок, как в других облаках.
# Создаём VPC с ручным режимом подсетей (custom) — так делают в проде.
# auto-режим создаёт подсети сразу во всех регионах, а это лишние адреса и лишний риск.
gcloud compute networks create app-vpc --subnet-mode=custom
# Подсеть для веб-слоя в Бельгии
gcloud compute networks subnets create web-subnet \
--network=app-vpc \
--region=europe-west1 \
--range=10.10.0.0/24
# Подсеть для базы данных — отдельный диапазон
gcloud compute networks subnets create db-subnet \
--network=app-vpc \
--region=europe-west1 \
--range=10.20.0.0/24
10.10.0.0/24 — это CIDR-нотация: диапазон приватных адресов, где /24 означает, что первые 24 бита адреса зафиксированы, а под хосты остаётся 8 бит. Считаем, сколько машин влезет (Google резервирует в каждой подсети 4 адреса — сетевой, шлюз и два служебных):
import ipaddress
subnet = ipaddress.ip_network("10.10.0.0/24")
print("Подсеть:", subnet)
print("Всего адресов:", subnet.num_addresses)
print("Доступно для VM:", subnet.num_addresses - 4)
# Диапазон, из которого приходит Google IAP — пригодится ниже
iap = ipaddress.ip_network("35.235.240.0/20")
for ip in ["35.235.243.17", "203.0.113.9"]:
addr = ipaddress.ip_address(ip)
print(ip, "-> из диапазона IAP" if addr in iap else "-> чужой адрес")
Результат:
Подсеть: 10.10.0.0/24
Всего адресов: 256
Доступно для VM: 252
35.235.243.17 -> из диапазона IAP
203.0.113.9 -> чужой адрес
Приватные и публичные адреса
У каждой VM всегда есть внутренний (приватный) IP из её подсети. Внешний (публичный) IP — опция, и по умолчанию его лучше не давать.
| Что | Внутренний IP | Внешний IP |
| Кто видит | только ресурсы вашей VPC | весь интернет |
| Нужен ли | всегда, выдаётся автоматически | только если сервис публичный |
| Стоит ли денег | нет | да, почасово — и зарезервированный, но неиспользуемый статический IP стоит дороже используемого |
| Выход в интернет | через Cloud NAT | напрямую |
Машина без внешнего IP не может сама сходить в интернет — а ей это нужно, чтобы поставить пакеты или сходить в чужой API. Для этого есть Cloud NAT: шлюз, который выпускает трафик наружу, но не пускает никого внутрь. Это ровно та схема, которую вы хотите для бэкенда.
gcloud compute routers create nat-router \
--network=app-vpc --region=europe-west1
gcloud compute routers nats create app-nat \
--router=nat-router --region=europe-west1 \
--auto-allocate-nat-external-ips \
--nat-all-subnet-ip-ranges
Cloud NAT — платный: берут почасовую плату за шлюз плюс за обработанные гигабайты. Для учебного проекта это копейки, но забытый NAT в пустом проекте всё равно капает в счёт.
Правила файрвола: главное — теги
Файрвол в GCP работает на уровне VPC, но применяется к каждой машине отдельно. Правило состоит из четырёх частей: направление (ingress — входящий, egress — исходящий), приоритет, кого касается (target) и откуда/куда (source/destination) плюс порты.
Ключевая идея, которую новички упускают: цель правила задаётся не IP-адресом машины, а сетевым тегом — произвольной меткой вроде web или db. Вы вешаете тег на VM, и правило автоматически на неё распространяется. Пересоздали машину, добавили десять новых — правила менять не нужно, достаточно повесить тот же тег.
# HTTP/HTTPS — всему интернету, но только машинам с тегом web
gcloud compute firewall-rules create allow-web \
--network=app-vpc --direction=INGRESS --priority=1000 \
--action=ALLOW --rules=tcp:80,tcp:443 \
--source-ranges=0.0.0.0/0 --target-tags=web
# Postgres — только от машин с тегом web к машинам с тегом db.
# Источник — не адрес, а ТЕГ: так правило переживает пересоздание VM.
gcloud compute firewall-rules create allow-web-to-db \
--network=app-vpc --direction=INGRESS --priority=1000 \
--action=ALLOW --rules=tcp:5432 \
--source-tags=web --target-tags=db
# SSH — только из диапазона Google IAP, а не из 0.0.0.0/0
gcloud compute firewall-rules create allow-ssh-iap \
--network=app-vpc --direction=INGRESS --priority=1000 \
--action=ALLOW --rules=tcp:22 \
--source-ranges=35.235.240.0/20 --target-tags=ssh-allowed
Тег на машину вешается при создании (или потом через gcloud compute instances add-tags):
gcloud compute instances create web-1 \
--zone=europe-west1-b --subnet=web-subnet \
--tags=web,ssh-allowed \
--no-address # без внешнего IP: наружу — через Cloud NAT
# Заходим по SSH через IAP-туннель: внешний IP не нужен вообще
gcloud compute ssh web-1 --zone=europe-west1-b --tunnel-through-iap
Типичная безопасная схема
- Веб-слой (тег
web): принимает 80/443 из0.0.0.0/0. Обычно — за балансировщиком, тогда трафик пускают только из диапазонов health-check и балансировщика130.211.0.0/22и35.191.0.0/16. - Слой данных (тег
db): принимает 5432 только от тегаweb. Внешнего IP нет. - Доступ администратора: SSH только через IAP (
35.235.240.0/20) или через один bastion-хост. Порт 22 в интернет не открыт нигде. - Выход наружу: Cloud NAT на приватную подсеть.
Как это работает
Файрвол GCP — не отдельная «железка на входе в сеть», а распределённый фильтр: правила применяются прямо на виртуальном сетевом интерфейсе каждой VM, ещё до того, как пакет доедет до гостевой ОС. Отсюда три следствия, которые надо держать в голове:
- Правила stateful. Разрешили входящее соединение — ответный трафик пойдёт автоматически, обратное правило писать не нужно.
- Есть неявные правила. В любой VPC действуют два невидимых правила с приоритетом 65535: разрешить весь исходящий и запретить весь входящий. То есть по умолчанию сеть закрыта на вход — и всё, что вы пишете, это исключения из запрета.
- Приоритет решает всё. Число от 0 до 65535, по умолчанию 1000; меньше — важнее. Правила проверяются от самого приоритетного; первое совпавшее применяется, дальше движок не смотрит. Если приоритеты равны и правила конфликтуют, побеждает
DENY.
Проверить, что реально применится к машине, можно так:
gcloud compute firewall-rules list \
--format="table(name,network,direction,priority,sourceRanges.list(),targetTags.list(),allowed[].map().firewall_rule().list())"
Частые ошибки
- Сеть
defaultи её подарки. В новом проекте автоматически создаётся сетьdefaultс правиламиdefault-allow-ssh(tcp:22 из0.0.0.0/0!),default-allow-rdp,default-allow-icmpиdefault-allow-internal. Люди поднимают VM «по-быстрому», она попадает вdefault— и SSH-порт уже смотрит в интернет. Боты находят его за минуты. Для реального проекта создавайте свою VPC, а изdefaultлишние правила удаляйте. --source-ranges=0.0.0.0/0на админ-порт. Самая дорогая опечатка в облаке. Открытый 22/3389/5432/6379/27017 для всего интернета — это не «риск», это вопрос дней. Скомпрометированную VM обычно используют для майнинга, и счёт за неё приходит вам.- Забыли тег. Правило написано на
--target-tags=web, а на машине тега нет. Трафик не идёт, а вы час дебажите nginx. Первое, что проверяем при «сайт не открывается»:gcloud compute instances describe web-1 --format="value(tags.items)". - Правило создали не в той VPC. Правила принадлежат конкретной сети. Забыли
--network=app-vpc— правило легло вdefaultи на ваши машины не действует. - Пересекающиеся диапазоны подсетей. Внутри одной VPC CIDR-диапазоны подсетей не должны пересекаться, и особенно больно это выстреливает потом, при VPN или peering с офисной сетью, где тоже
10.0.0.0/8. Планируйте адресацию заранее. - Ошибки, стоящие денег. Внешние IP тарифицируются, причём зарезервированный и никем не используемый статический адрес стоит дороже работающего — Google так штрафует за удержание дефицитных адресов. Второй счёт-сюрприз — egress: исходящий трафик в интернет и между регионами платный (входящий — нет). Гоняете гигабайты между
europe-west1иus-central1— платите за каждый. - Логи файрвола выключены. По умолчанию отброшенные пакеты нигде не видно. Включайте
--enable-loggingна важных правилах — но помните, что логи идут в Cloud Logging и объём тоже стоит денег.
Итоги
- VPC в GCP — глобальная, подсети — региональные; машины из разных регионов одной VPC общаются по приватным адресам.
- Входящий трафик закрыт неявным правилом
deny— всё, что вы пишете, это осознанные исключения. - Цель правила задавайте сетевым тегом, а не IP: правила переживут пересоздание машин.
- Приоритет 0–65535, меньше — важнее; при равенстве побеждает
DENY. Правила stateful — обратное правило не нужно. - Бэкенду не нужен внешний IP: выход наружу — через Cloud NAT, вход админа — через IAP-туннель.
- Сама VPC и правила бесплатны; деньги едят внешние IP, egress-трафик и Cloud NAT.