Сетевые основы для DevOps: NAT, маршрутизация, порты и почему «не ходит»
Разберём базовые сетевые механики на примерах: как мыслить про маршруты, NAT и доступность сервисов в инфраструктуре.
Содержание
Сетевые основы для DevOps: NAT, маршрутизация, порты и почему «не ходит»
DevOps почти всегда упирается в сеть раньше, чем хотелось бы: сервис «поднялся» — а снаружи его не видно, контейнер «слушает» — но подключение зависает, firewall настроен «как в статье» — и всё равно не работает. В таких ситуациях чаще всего проблема не в приложении, а в базовой механике маршрутизации, адресации и трансляции (NAT), в том, как именно пакеты проходят через инфраструктуру.
Эта статья — практичный разбор сетевых основ, которые нужны DevOps ежедневно: как мыслить про маршруты, как работает NAT, что означают порты в контексте доступности и почему типовые ошибки приводят к фразам вроде «оно же должно ходить».
Маршрутизация: почему «IP есть — а связь нет»
Что такое маршрут и почему он важнее «соседей»
В любой IP-сети отправка пакета — это не «магия адреса назначения». У хоста есть таблица маршрутизации: набор правил вида «для сети X отправляй через интерфейс Y или шлюз Z». Именно она определяет, куда пойдёт пакет, когда вы обращаетесь к dstIP.
Если маршрут отсутствует, пакет уйдёт в никуда — чаще всего будет ICMP host unreachable или просто дроп на уровне ОС/устройства (в зависимости от реализации и политики). Поэтому первая мысль DevOps при проблеме “не ходит” — не “какой порт”, а “есть ли путь до адреса”.
Признак: пинг/трейс до хоста не проходит, а лог приложения молчит.
Как читать таблицу маршрутизации (на Linux)
На Linux удобно смотреть текущие маршруты:
ip route show
Пример типичной таблицы:
default via 192.168.1.1 dev eth0— всё неизвестное отправлять через шлюз192.168.10.0/24 dev eth1 scope link— сеть напрямую через интерфейс eth110.0.0.0/8 via 192.168.10.1 dev eth1— доступ к 10/8 через другой роутер
Ключевой вывод: если вы обращаетесь к адресу из другой подсети, хост должен знать шлюз по пути. В облаках и контейнерах это часто меняется динамически: неправильный subnet, отсутствие route в VPC/VNet, неверно настроенная таблица в Kubernetes CNI — и “не ходит”.
Три частых сценария, когда маршруты ломаются
-
Неправильная подсеть сервиса
Например, вы развернули контейнер в10.10.2.0/24, но клиент находится в10.10.1.0/24, а маршруты между этими подсетями не добавлены. -
Сервис слушает не на том интерфейсе
Даже при правильном маршруте, если процесс привязан только к127.0.0.1(или конкретному адресу), внешние пакеты не попадут в обработчик. Это отдельно от маршрутизации, но ошибка часто «маскируется» и выглядит как сетевой сбой. -
Асимметрия маршрутов
Пакеты могут уходить через один путь, а ответы возвращаться через другой (или вообще не находить обратный путь). NAT и политики firewall усиливают этот эффект: TCP может “установить соединение” на одной стороне и сломаться на обратном пути.
Порты: что они на самом деле означают
Порт — не сервис, а направление для доставки
Порт — это часть 5-тупла (source IP, source port, destination IP, destination port, protocol), по которому ОС понимает, как доставить пакет в конкретный сокет/процесс.
Для DevOps важно различать:
- слушает ли приложение (
LISTENна конкретном адресе и порте) - пропускает ли firewall/ACL (на узле и между узлами)
- направляется ли трафик к приложению (маршрутизация + NAT/порт-маппинг)
Проверка “слушает ли” (Linux)
Увидеть, что процесс реально слушает:
ss -ltnp
Ищите строку с вашим портом. Обратите внимание на адрес:
127.0.0.1:8080— доступ только локально0.0.0.0:8080— слушает на всех интерфейсах10.0.1.23:8080— слушает на конкретном интерфейсе
Если вы ожидаете доступ с другого хоста, “127.0.0.1” почти гарантированно будет причиной «не ходит».
Firewall и ACL: почему вы видите “открытый порт” не там, где нужно
Нередко порт “открыт” на приложении, но на пути трафик фильтруется:
iptables/nftablesна хосте- security group / network ACL в облаке
- firewall между подсетями/VPC
- правила на уровне Kubernetes (NetworkPolicy)
Показательная диагностика: tcpdump/ss на стороне сервера: если SYN приходит, но не отвечает — значит, дальше уже firewall или приложение не может обработать/не получает пакет.
NAT: адреса меняются — и это ломает ожидания
Зачем вообще нужен NAT
Network Address Translation — механизм, который меняет адреса (и часто порты) в пакетах при прохождении через устройство (маршрутизатор/edge). Чаще всего NAT используют, чтобы:
- предоставить множество внутренних адресов, выходящих наружу через ограниченное число публичных IP (маскарадинг)
- опубликовать сервис с приватного IP во внешнюю сеть (DNAT/port forwarding)
- разрулить пересечения адресных пространств (в сложных сетях)
С NAT важно понимать: ваш клиент видит один адрес, сервер — другой, а обратные пакеты должны найти корректную трансляцию.
SNAT vs DNAT: две стороны одной медали
Обычно NAT описывают так:
-
DNAT (Destination NAT): меняется назначение
Внешний запрос к публичному IP:port переводится на внутренний IP:port. -
SNAT (Source NAT): меняется источник
Внутренний хост при выходе в интернет заменяет свой source IP на публичный адрес.
Часто на практике “публикация сервиса” использует DNAT + обратное соответствие на стороне NAT-устройства.
Пример: публикуем сервис из приватной сети во внешнюю
Допустим, у вас есть внутренняя машина 10.0.1.10 с веб-сервисом на 8080. NAT-гейтвей с публичным IP 203.0.113.10 должен проксировать входящие соединения.
На Linux (упрощённо) можно представить логику так:
# DNAT: входящие на 203.0.113.10:80 направить на 10.0.1.10:8080
iptables -t nat -A PREROUTING -p tcp -d 203.0.113.10 --dport 80 -j DNAT --to-destination 10.0.1.10:8080
# SNAT/MASQUERADE для возвратов (если нужно)
iptables -t nat -A POSTROUTING -p tcp -d 10.0.1.10 --dport 8080 -j MASQUERADE
Теперь внешний клиент подключается к 203.0.113.10:80, NAT меняет назначения и направляет на внутренний сервер. Но если вы неправильно настроили правила обратного пути (или firewall не разрешает), соединение “вроде бы пришло” — но ответа нет.
Почему NAT часто ломает “почему не ходит”
Классические причины:
-
Нет состояния (conntrack) или неверные правила возврата
NAT-устройство должно корректно сопоставлять пакеты запроса/ответа. Если вы фильтруете трафик до NAT или между цепочками, состояние может не установиться. -
Проблемы с протоколами, которые передают IP/порт внутри payload
Например, активный FTP или некоторые нестандартные протоколы требуют ALG/специальной поддержки. Для DevOps это неожиданно, но встречается. -
NAT и “привязка к IP” на сервере
Сервер может ожидать конкретный source IP для аутентификации или для роутинга. NAT превращает источник в другой адрес — и система падает логически, хотя сеть “формально” может быть настроена. -
Асимметрия маршрутов
Внутренний путь туда один, обратно — другой. С NAT это проявляется особенно ярко: обратный пакет не находит запись в трансляции.
Где NAT неявен: контейнеры и облака
NAT часто “прячется” в платформах:
- Docker по умолчанию использует iptables для маршрутизации/маскарадинга между bridge-сетью и наружной сетью.
- В Kubernetes NodePort/LoadBalancer реализуются через цепочки NAT/прокси.
- Cloud provider почти всегда делает SNAT при выходе из VPC через Internet Gateway.
Отсюда типичная ситуация: в вашей локальной сети curl работает, а в интеграции “не ходит” — потому что другой сегмент инфраструктуры включает NAT и меняет поведение.
Общая модель доступности сервиса: от клиента до приложения
Удобнее всего мыслить доступность как цепочку из пяти уровней:
- DNS/адресация: клиент получает правильный IP?
- Маршрут до адреса: есть ли путь до destination IP?
- Фильтрация: разрешён ли трафик на пути (firewall/ACL)?
- Трансляция (NAT/порт-маппинг): если есть NAT — он корректно переписывает адреса и порты, и возврат находит состояние?
- Приложение и сокеты: процесс слушает адрес/порт и отвечает?
Когда “не ходит”, DevOps обычно перескакивает через пункты 2–4 и упирается в приложение — но реальная проблема почти всегда на одном из верхних уровней (маршрут/фильтрация/NAT).
Как диагностировать проблему: практический чеклист
Ниже — порядок, который экономит часы. Логика простая: сначала проверяем путь и адреса, потом порты, потом — адресацию/трансляцию.
Шаг 1. Проверить достижимость IP-уровня
ping(если ICMP разрешён)traceroute/tracepath- попытка TCP-соединения с таймаутом
Например, с клиента:
# Проверка TCP доступности порта
timeout 5 bash -c '</dev/tcp/10.0.1.10/8080' && echo OK || echo FAIL
Если даже TCP не устанавливается — смотрим маршруты и firewall между сетями.
Шаг 2. На сервере — факт “LISTEN”
ss -ltnp | grep 8080
Если сервер слушает на 127.0.0.1, а доступ нужен извне — проблема в адресе привязки, а не в сети “как таковой”.
Шаг 3. Поймать пакеты на сервере
На сервере включите временный capture:
sudo tcpdump -ni any 'tcp port 8080'
Что вы увидите:
- SYN приходят, но нет SYN/ACK → firewall/правила приложений/локальная фильтрация
- пакеты не приходят → маршрут/ACL/NAT/балансировщик на пути
- SYN/ACK уходят, но клиент всё равно “не ходит” → обратный путь, conntrack, асимметрия
Шаг 4. Если есть NAT — проверяем трансляции
На Linux-гейтвей (если вы управляете им):
sudo conntrack -L | grep 8080
Или смотреть правила iptables/nftables в таблицах nat/filter.
Тонкость: conntrack может “молчать” из-за отсутствия модулей/правил или если трафик фильтруется раньше, чем попадает в цепочки NAT.
Шаг 5. Проверить “внешний” и “внутренний” порт отдельно
С NAT/порт-выводом часто возникает путаница:
- Клиент подключается к
80, а внутренний сервис на8080 - В логах приложения “видит” порт клиента как
someRandom(source port), но это нормально - ACL настроены на один порт, а трафик реально приходит на другой
Соберите факты: какой порт клиент вызывает, какой порт у сервиса слушается, и что делает NAT/прокси между ними.
Типовые ошибки DevOps при настройке сети
Ошибка 1. Перепутать “доступность” и “маршрутизацию”
Сервис может быть “слушающим”, но без маршрута клиент не достучится. Наоборот, маршрут может быть, но без порта/фильтрации соединения не будет.
Правильный подход: сначала маршрут и reachability, потом порт.
Ошибка 2. Забыть про интерфейсы и binding
Приложение привязано к localhost. В контейнерах это особенно коварно: разработчик тестировал внутри, а публикацию сделал извне.
Решение — слушать 0.0.0.0 (или конкретный IP интерфейса), а не 127.0.0.1.
Ошибка 3. Настроить firewall “внутри”, но забыть про внешнюю подсеть
Например, вы открыли 8080/tcp на сервере, но security group на уровне балансировщика/узла не пропускает входящие.
Признак: на сервере трафика нет вообще (tcpdump пустой).
Ошибка 4. Неправильные правила NAT/порт-форвардинга
Классические случаи:
- DNAT настроен, но нет корректных правил возврата (MASQUERADE/SNAT там, где нужно)
- дропается
ESTABLISHED,RELATEDна цепочке filter - перепутаны протоколы (
tcpvsudp) или порты
Ошибка 5. Игнорировать асимметрию маршрутов
В облаках часто есть несколько путей: через NAT-гейтвей, через peering, через локальные маршруты. Если один путь для запроса и другой для ответа — stateful firewall/NAT может оборвать соединение.
NAT и маршруты в облаках и Kubernetes: что знать именно DevOps
Cloud VPC/VNet: маршрутизация как ресурс
В облаках маршруты часто реализуются через отдельные сущности:
- route tables в VPC/VNet
- gateways/internet gateways
- peering и propagation
DevOps сталкивается с тем, что “на EC2/VM локально всё ок”, но из соседней подсети пакеты не возвращаются, потому что в route table отсутствует нужный next-hop.
Kubernetes: почему “NodePort не работает” не всегда про порт
NodePort/LoadBalancer/Ingress зависят от того, какие правила пакеты проходят через:
- kube-proxy (iptables/ipvs)
- CNI (маршруты между pod-сетями)
- external traffic policy
- service type и его параметры
- NetworkPolicy
Отсюда распространённая ситуация: порт открыт на Pod’е, но политика сети в кластере дропает трафик на уровне pod/pod или namespace/endpoint.
Сеть в Kubernetes — это набор взаимодействующих слоёв, и NAT может встречаться на разных стадиях.
Как сформировать “сетевую интуицию” DevOps
Хорошая интуиция в сетях строится не на запоминании команд, а на привычке отвечать на три вопроса:
-
Куда пакет должен попасть дальше?
Это вопрос о маршруте. -
Что происходит с адресами по пути?
Это вопрос о NAT/порт-маппинге. -
Кто решает, можно ли трафику проходить?
Это вопрос о firewall/ACL/политиках.
Сформулировав это для конкретного случая, вы почти всегда быстро локализуете проблему. Например:
- “клиент не видит сервис” → маршрут/ACL
- “сервер слушает, но tcpdump пустой” → NAT/маршрут/ACL
- “пакеты на сервер приходят, но ответа нет” → filter/local policy
- “ответ вроде есть, но клиент таймаутит” → обратный путь/conntrack/asymmetry
Выводы
Сетевые проблемы в DevOps редко сводятся к “сломался конкретный порт” или “не запускается приложение”. В большинстве случаев причина находится в одном из базовых узлов цепочки: маршрутизация, адресация, NAT/порт-трансляция и фильтрация, а уже затем — в настройках процесса (binding/listen) и протокола.
Если вам нужно систематизировать это мышление, полезный следующий шаг — пройти материал, который отдельно раскладывает NAT, маршрутизацию и принципы работы сетевых уровней на практических примерах. Например, можно посмотреть курс по сетевым основам и отработать диагностику на типовых сценариях: [ /course/ ].
Главное — не пытаться чинить сеть “вслепую”. Делайте проверку по уровням: путь → порт → фильтрация → NAT → сокеты/ответ. Это подход, который почти всегда окупается быстрее любых догадок.
Комментарии
Пока нет комментариев