L3/L4 NAT, ACL, firewall — безопасность на сетевом уровне

Этот модуль — про то, как сеть переписывает адреса (NAT) и решает, что пропустить, а что выбросить (ACL, firewall). Это повседневная работа инженера и прямой мост в безопасность и облако: Security Groups в AWS, iptables/nftables в Linux, Network Policies в Kubernetes — всё это родом отсюда.

Заявка из очереди

«Заявка #53101. Бухгалтерии нужен доступ к серверу 1С (10.0.0.10) из дома по HTTPS. Публичный адрес офиса один — 203.0.113.1. Настроить доступ снаружи, при этом гостевой Wi-Fi (192.168.66.0/24) не должен иметь доступа к 1С вообще. Вчерашняя попытка коллеги закончилась тем, что у всего офиса отвалился интернет — откатили». Здесь всё содержание модуля в одной заявке: DNAT (публикация сервера), SNAT (офис ходит в мир через один адрес), ACL (отрезать гостей) — и цена ошибки в порядке правил. Разберём по частям и в конце закроем заявку без жертв.

Что узнаешь — после урока ты сможешь
Вспомни из прошлых модулей

Модуль 4: приватные диапазоны RFC1918 (10/8, 172.16/12, 192.168/16) не маршрутизируются в интернете; маска /24 = 255.255.255.0 — сегодня встретишь её «перевёртыш» (wildcard). Модуль 5: у каждого пакета есть путь туда и обратно — NAT живёт ровно на этом стыке. Порты TCP/UDP: 443 — HTTPS, 80 — HTTP; приложение на сервере «слушает» порт, клиент приходит с временного порта (49152+). Если порты — тёмный лес, задержись на этой фразе: IP находит дом, порт находит квартиру.

1. Зачем нужен NAT

IPv4-адреса закончились. Внутри компаний используют приватные диапазоны RFC1918 (10/8, 172.16/12, 192.168/16), которые не маршрутизируются в интернете. Чтобы тысячи внутренних хостов вышли наружу через горстку публичных адресов, на границе их адреса транслируются — это и есть NAT (Network Address Translation).

Вид NATЧто делаетГде
Static NAT1:1 фиксированно (внутр. IP ↔ внешн. IP)сервер должен быть доступен извне по постоянному адресу
Dynamic NATиз пула внешних адресов, по мере надобностиредко; когда внешних адресов почти столько же
PAT / NAT overloadмного внутр. → один внешн. IP, различая по портам99% домашних и офисных выходов в интернет
PAT (overload): сотни хостов выходят через один публичный IP, различаясь портами
10.0.0.5:51001 10.0.0.6:49234 10.0.0.7:60880 NATPAT Интернет 203.0.113.1:1024 203.0.113.1:1025 ... Таблица трансляций хранит соответствие «внутр. IP:порт ↔ внешн. IP:порт» для обратного пути.
Роутер помнит, какой ответ кому вернуть, по уникальной паре внешний-IP:порт. Это и есть «overload».
У PAT есть физический предел: на один внешний адрес — ~64 тысячи портов на протокол. Для офиса это много, для оператора с CGNAT — мало: порты кончаются (port exhaustion), новые соединения не открываются, старые живут. Симптом: «интернет есть, но новые вкладки не грузятся в час пик». Поэтому у NAT есть и таймауты: молчащая трансляция удаляется (TCP — часы, UDP — минуты).

2. SNAT против DNAT

SNAT (Source NAT)

Переписывает адрес источника. Применяется к трафику изнутри наружу: «спрячь приватный src за публичный». PAT — это разновидность SNAT.

DNAT (Destination NAT)

Переписывает адрес назначения. Применяется к трафику снаружи внутрь: «запрос на публичный IP:443 переадресуй на внутренний веб-сервер». Это port-forwarding / publish сервиса.

Запомни связку: выходишь в интернет → SNAT (прячем источник). Публикуешь сервис наружу → DNAT (перенаправляем назначение). В облаке: NAT Gateway = SNAT, Load Balancer / Elastic IP на инстанс = DNAT.

3. Разбор руками: NAT для заявки #53101 — обе половины

Настроим границу офиса: весь офис выходит в мир через 203.0.113.1 (PAT), а сервер 1С публикуется снаружи по 443 (static NAT с портом — то самое «пробросить порт»):

# 0. Разметить, где «внутри», а где «снаружи» — без этого NAT не работает R1(config)# interface gi0/1 R1(config-if)# ip nat inside # LAN офиса R1(config)# interface gi0/0 R1(config-if)# ip nat outside # линк к провайдеру # 1. PAT: весь офис (10.0.0.0/24) наружу через адрес интерфейса R1(config)# ip access-list standard OFFICE-LAN R1(config-std-nacl)# permit 10.0.0.0 0.0.0.255 R1(config)# ip nat inside source list OFFICE-LAN interface gi0/0 overload # 2. Публикация 1С: снаружи 203.0.113.1:443 → внутрь 10.0.0.10:443 R1(config)# ip nat inside source static tcp 10.0.0.10 443 203.0.113.1 443

Теперь — главная команда диагностики NAT. Учись читать её вывод построчно:

R1# show ip nat translations Pro Inside global Inside local Outside local Outside global tcp 203.0.113.1:443 10.0.0.10:443 --- --- tcp 203.0.113.1:443 10.0.0.10:443 198.51.100.7:52121 198.51.100.7:52121 tcp 203.0.113.1:1025 10.0.0.6:49234 142.250.74.14:443 142.250.74.14:443
частая ошибка джуна Перепутать inside/outside на интерфейсах или забыть пометить один из них. Симптом: конфиг NAT «идеальный», а show ip nat translations — пустая. NAT срабатывает только на пути «inside-интерфейс → outside-интерфейс»; непомеченные интерфейсы для него не существуют.

4. Hairpin NAT — «изнутри по внешнему IP не открывается»

Классическая боль (и гарантированный звонок после закрытия заявки #53101): снаружи https://203.0.113.1 работает, а из внутренней сети по этому же публичному адресу — нет. Причина: пакет идёт хост → роутер → и должен «развернуться обратно» внутрь (DNAT) и при этом подмениться источник (SNAT), иначе сервер ответит напрямую внутреннему хосту, минуя NAT, и сессия не сойдётся. Решение — hairpin NAT (NAT loopback): роутер делает и DNAT, и SNAT для такого «разворота».

Hairpin: пакет «разворачивается» на NAT-устройстве (форма шпильки)
внутр. хост NATDNAT+SNAT внутр. сервер к 203.0.113.10 развернулся внутрь сервера
Лучше вообще не ходить наружу за «своими» — используй split-DNS (внутренний DNS отдаёт приватный IP).

5. Что NAT ломает и почему это НЕ безопасность

важно для собеса NAT — это НЕ firewall. Да, побочно он скрывает внутренние адреса, но защищает не NAT, а сопутствующая stateful-логика. Полагаться на NAT как на защиту — ошибка. Тем более в IPv6, где NAT обычно не нужен — там защищает именно firewall.

6. ACL — список контроля доступа

ACL (Access Control List) — упорядоченный список правил «permit/deny» по полям пакета. Роутер проверяет пакет правилами сверху вниз и применяет первое совпавшее — остальные не смотрит. В конце любого ACL — невидимый deny any: что явно не разрешено, то запрещено.

Тип ACLПо чему фильтрует
Standard (1–99)только source IP
Extended (100–199)source+dest IP, протокол, порты, флаги — полноценно
Namedто же, но с именем (читаемо, можно редактировать по строкам)
ACL обрабатывается сверху вниз, до первого совпадения
пакет 10 permit tcp any host 10.0.0.10 eq 443 20 deny ip 192.168.66.0 0.0.0.255 any 30 permit ip any any (невидимое) deny ip any any совпало → permit, стоп не совпало нигде → drop
Порядок правил критичен: специфичное — выше, общее — ниже. Иначе правило «никогда не сработает».

Wildcard-маска — это НЕ маска подсети

ACL использует wildcard-маску — по сути «инвертированную» маску подсети. 0 = бит должен совпасть, 1 = бит неважен. Для /24 маска подсети 255.255.255.0, а wildcard — 0.0.0.255. Удобный трюк: wildcard = 255.255.255.255 − маска подсети.

Хочу описатьWildcard
один хост 10.0.0.50.0.0.0 (или ключевое слово host)
вся /24 10.0.0.00.0.0.255
любой адрес255.255.255.255 (или any)
# named extended ACL для заявки #53101: гости не ходят к 1С, всё остальное живёт R1(config)# ip access-list extended LAN-POLICY R1(config-ext-nacl)# deny ip 192.168.66.0 0.0.0.255 host 10.0.0.10 # гости → 1С: нельзя R1(config-ext-nacl)# permit ip any any # всё остальное: можно R1(config)# interface gi0/2 R1(config-if)# ip access-group LAN-POLICY in # на входе гостевого сегмента
Где применять extended ACL? Классическое правило: extended — ближе к источнику (режем мусор сразу), standard — ближе к назначению (т.к. фильтрует только по src и слишком рано отрезал бы лишнее).

А теперь — что сломал вчера коллега из заявки. Он написал ACL из одной строки deny ip 192.168.66.0 0.0.0.255 host 10.0.0.10 и повесил его на внешний интерфейс. Два фатальных промаха: во-первых, за его deny сработал невидимый deny any — и весь офисный трафик наружу умер («отвалился интернет»). Во-вторых, гостевой трафик к 1С через внешний интерфейс и не ходит — фильтр стоял не на том пути. Правильно: явный permit ip any any в конце и точка применения на входе гостевого сегмента.

Диагностика ACL: счётчики совпадений

У ACL есть встроенный «свидетель» — счётчик срабатываний каждой строки. Это первый инструмент при любом «после ACL что-то отвалилось»:

R1# show access-lists LAN-POLICY Extended IP access list LAN-POLICY 10 deny ip 192.168.66.0 0.0.0.255 host 10.0.0.10 (3782 matches) # гости реально ломятся! 20 permit ip any any (120994 matches)

Счётчик строки 10 растёт — правило живёт и работает. Если жалоба «мне заблокировало», а счётчики deny-строк стоят на месте — блокирует не этот ACL: ищи другой ACL, firewall или вообще другую причину. Обнулить счётчики перед экспериментом: clear access-list counters.

7. Stateful firewall — умнее, чем ACL

Обычный ACL без памяти: смотрит каждый пакет отдельно. Чтобы разрешить «исходящий запрос + ответ на него», пришлось бы вручную открывать обратные порты — дыра. Stateful firewall ведёт таблицу соединений (conntrack): разрешил исходящее соединение — ответный трафик пропускается автоматически, потому что он «принадлежит установленной сессии».

Stateful: ответ проходит, потому что сессия уже в таблице
внутр. хост Firewallconntrack:85→server :443ESTABLISHED сервер SYN (исходящий, разрешён) SYN-ACK (ответ — проходит сам) Не нужно вручную открывать обратный порт — firewall «помнит» сессию и пропускает ответ.
Это фундамент любого современного firewall — и Cisco ASA/ZBFW, и Linux iptables/nftables, и облачных SG.
обратная сторона памяти Раз firewall «помнит» сессии — он и ломается от асимметрии: если ответ вернулся другим путём (мимо него), сессии в таблице нет, и ответ дропается как чужой. Эта механика подробно всплывёт в модуле 12 на живом инциденте. И вторая цена памяти: таблица соединений конечна — DDoS из миллионов полуоткрытых сессий переполняет её (SYN flood), поэтому у firewall есть лимиты и таймауты сессий.

Zone-Based Firewall (ZBFW) и CoPP

Zone-based firewall — современная модель Cisco: интерфейсы группируются в зоны (inside, outside, dmz), а политика описывает, что разрешено между парами зон. По умолчанию между зонами — запрет. Намного чище, чем развешивать ACL по интерфейсам.

CoPP (Control Plane Policing) — отдельная защита: ограничивает трафик, идущий на сам процессор роутера (CPU): OSPF/BGP-hello, SSH, SNMP, ICMP к роутеру. Без CoPP флуд на control plane может «положить» устройство, даже если оно справляется с транзитом. Это часть защиты инфраструктуры.

8. Плейбук: «проброс не работает»

Заявку закрыли, а бухгалтер из дома «не подключается». Идём по цепочке, от дешёвого к дорогому:

Сервис вообще жив?
Изнутри, мимо всякого NAT: telnet 10.0.0.10 443 с соседней машины. Не открывается — чини сервер (служба не запущена, локальный firewall), NAT ни при чём.
Правило NAT дежурит?
show ip nat translations | include 443 — есть ли статическая строка? Нет — правило не применилось (опечатка, не тот интерфейс помечен inside/outside).
Пакеты снаружи доходят до роутера?
Пусть бухгалтер подключается, а ты смотри: появилась ли динамическая строка трансляции с её адресом? Появилась — NAT сработал, иди дальше. Нет — пакет не дошёл или убит раньше: ACL на внешнем интерфейсе (смотри счётчики!), или провайдер режет входящие на этот порт.
Трансляция есть, соединения нет?
Значит, пакет ушёл внутрь и потерялся: локальный firewall сервера (самое частое — Windows Firewall пускает только «свою» подсеть), либо у сервера неверный шлюз — ответ уходит не через NAT-роутер (асимметрия, сессия не собирается).
Снаружи работает, изнутри по внешнему IP — нет?
Это не поломка, это hairpin (раздел 4): включай NAT loopback или, лучше, split-DNS. Предупреди пользователей заранее — сэкономишь себе заявку.

9. Мост в DevOps — здесь начинается твоя security-карьера

Это самый «переносимый» модуль трека: те же концепции ты увидишь каждый день в облаке и Linux.

Сетевой концептАналог в DevOps
Stateful firewall / conntrackLinux iptables/nftables (conntrack), firewalld
SNAT/PATAWS NAT Gateway, Linux MASQUERADE, Docker bridge NAT
DNAT / port-forwardk8s Service/NodePort, LoadBalancer, iptables -j DNAT, docker run -p
ACL (stateless)AWS Network ACL (на уровне subnet, stateless!)
Stateful allow-listAWS Security Group (stateful, per-ENI)
Zone policyk8s NetworkPolicy (что какому поду можно)
# Linux: PAT (как роутер) — MASQUERADE $ iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE # Linux: stateful allow — пускаем ответы established (тот же conntrack) $ iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT $ iptables -A INPUT -p tcp --dport 443 -j ACCEPT $ iptables -A INPUT -j DROP # неявный deny, как в ACL # смотрим таблицу соединений (как show в firewall) $ conntrack -L
🌉 Прямая дорога в DevSecOps

Понял ACL и stateful firewall здесь — понимаешь AWS Security Groups (stateful) против NACL (stateless), знаешь, почему SG достаточно открыть только входящий порт, а NACL — оба направления. Это буквально вопросы с собеседований по облаку. А docker run -p 8080:80 — это тот же DNAT-проброс, что ты настроил в разделе 3, только написанный Docker'ом в iptables за тебя.

10. Мини-лаба: NAT и firewall у тебя дома

Твой домашний роутер — полноценный NAT + stateful firewall. Исследуй его за 20 минут:

Докажи, что ты за PAT
Сравни ipconfig (свой адрес — наверняка 192.168.x.x) и адрес на 2ip.ru (публичный). Разные — ты за NAT. Открой 2ip.ru с телефона по домашнему Wi-Fi: публичный адрес тот же — вы оба за одним PAT, различаетесь только портами.
Найди таблицу трансляций роутера
В веб-интерфейсе роутера поищи «NAT connections» / «активные соединения» (на многих прошивках есть). Это твой домашний show ip nat translations: сотни строк «внутренний IP:порт ↔ внешний порт» — от каждого телефона, телевизора и вкладки браузера.
Сделай свой первый DNAT-проброс
В настройках роутера («Port Forwarding» / «Виртуальные серверы») пробрось внешний порт 8080 на свой ПК (порт 8080). На ПК подними что-нибудь слушающее (например, python -m http.server 8080). Проверь с телефона через LTE (не Wi-Fi!): http://твой-публичный-IP:8080. Работает — ты только что сделал руками то, что настроил в разделе 3. Потом удали проброс — не оставляй дырок.
Проверь hairpin
Пока проброс жив, открой тот же http://публичный-IP:8080 с ПК внутри домашней сети. Открылось — твой роутер умеет NAT loopback. Нет — ты вживую поймал hairpin-проблему из раздела 4.
Потрогай stateful в Linux (если есть WSL/VM)
sudo apt install conntrack → открой пару сайтов → sudo conntrack -L | head: перед тобой живая таблица соединений — тот самый conntrack, на котором стоят и iptables, и облачные Security Groups.

11. Словарик урока

ТерминПо-английскиСмысл в одну строку
NATnetwork address translationподмена адресов в пакете на границе сетей
PAT / overload / masqueradeport address translationмного внутренних адресов за одним внешним, различение по портам
SNAT / DNATsource / destination NATподмена источника (выход наружу) / назначения (публикация внутрь)
Проброс портаport forwardingDNAT-правило «внешний порт → внутренний хост:порт»
Hairpin / NAT loopbackдоступ изнутри к своему сервису по внешнему адресу через «разворот» на NAT
Таблица трансляцийNAT translationsпамять NAT: кто под каким внешним портом вышел (show ip nat translations)
Исчерпание портовport exhaustionкончились свободные внешние порты PAT — новые соединения не открываются
ALGapplication layer gateway«помощник» NAT для протоколов с адресами в данных (FTP, SIP); частый источник глюков
ACLaccess control listупорядоченный список permit/deny; первое совпадение побеждает, в конце неявный deny
Wildcard-маскаwildcard maskинвертированная маска для ACL: 0 = бит должен совпасть, 1 = неважен
Счётчики ACLACL hit countersсколько пакетов совпало с каждой строкой (show access-lists) — главный свидетель
Stateful / conntrackconnection trackingfirewall с памятью сессий: ответы разрешённых соединений проходят сами
ZBFWzone-based firewallполитика «что можно между зонами», а не ACL на каждом интерфейсе
CoPPcontrol plane policingлимит трафика на CPU роутера — защита самого устройства от флуда

12. Вопросы с собеседования

❓ В чём разница SNAT и DNAT?
SNAT переписывает источник (выход наружу, прячем приватный IP). DNAT — назначение (публикация сервиса извне, port-forward). PAT — это SNAT с различением по портам.
❓ Stateless ACL против stateful firewall?
ACL смотрит каждый пакет отдельно (для ответа надо открывать обратный порт вручную). Stateful ведёт таблицу соединений и пропускает ответный трафик автоматически. AWS NACL = stateless, Security Group = stateful — классический вопрос.
❓ Что в конце каждого ACL?
Невидимый deny any. Что явно не разрешено — запрещено. Поэтому хотя бы одно permit обязательно, иначе ACL заблокирует весь трафик.
❓ NAT — это безопасность?
Нет. NAT транслирует адреса; «скрытие» внутренних IP — побочный эффект. Защищает stateful-логика/firewall, а не сам NAT. В IPv6 NAT обычно не нужен — защищает firewall.
❓ Настроил проброс, снаружи не работает. Первые три проверки?
1) Сервис жив изнутри (telnet внутренний-IP порт). 2) Статическая трансляция в таблице (show ip nat translations) и появляется ли динамическая при попытке клиента. 3) ACL на внешнем интерфейсе — счётчики совпадений. Дальше — шлюз сервера и его локальный firewall.

13. Частые ошибки джунов

ошибка 1 Неверный порядок ACL. Общее правило permit ip any any стоит выше специфичного deny — и deny никогда не срабатывает. Специфичное — наверх.
ошибка 2 Забыли неявный deny. Написали один permit (или один deny!) — и заблокировали всё остальное, включая нужное (DNS, ответы). Ровно так коллега из заявки #53101 «уронил интернет офису».
ошибка 3 Путают wildcard и маску подсети. Пишут 255.255.255.0 вместо 0.0.0.255 — ACL ловит не то. Wildcard инвертирован: 0 = совпасть, 1 = неважно.
ошибка 4 Полагаются на NAT как на защиту. Открыли проброс «на всякий» — и сервис торчит наружу без firewall. NAT не фильтрует намерения.
ошибка 5 Забыли ip nat inside/outside на интерфейсах. Конфиг «правильный», трансляций ноль. NAT работает только между помеченными интерфейсами.
ошибка 6 Забыли про CoPP. Флуд на сам роутер (ICMP/SSH/SNMP) грузит CPU, и устройство «тупит», хотя транзит идёт. Защищай control plane отдельно.

14. Задачи: поставь диагноз

Задача 1. После включения ACL из двух строк (deny гостям к серверу + permit ip any any) гости всё равно открывают сервер. Счётчик deny-строки — 0. Где ошибка?

Счётчик 0 = трафик гостей не проходит через этот ACL: он применён не на том интерфейсе или не в том направлении (in/out). Проверь точку применения: фильтровать гостей надо на входе (in) их сегмента. Вторая частая причина — гости попадают под более раннюю permit-строку (порядок!).

Задача 2. show ip nat translations пуст, хотя правило PAT настроено и офис жалуется «нет интернета». Что забыли?

Скорее всего, ip nat inside / ip nat outside на интерфейсах — без этих меток NAT не срабатывает вовсе. Проверь также, жив ли ACL, на который ссылается правило NAT (permit на офисную подсеть), и есть ли маршрут наружу.

Задача 3. Проброс RDP настроен, снаружи не работает. Трансляция при подключении появляется. На сервере captured: SYN приходит, SYN-ACK уходит. Что не так?

Пакеты доходят и сервер отвечает — но ответ не возвращается клиенту. Смотри шлюз сервера: если default gateway указывает не на NAT-роутер, SYN-ACK уходит другим путём с приватным источником и гибнет. Классическая асимметрия — та же механика, что ломает stateful firewall.

Задача 4. Клиенты за CGNAT оператора жалуются: вечером новые сайты не открываются, старые вкладки работают. Что происходит?

Port exhaustion: на внешний адрес CGNAT — ~64k портов, вечером они кончаются. Существующие трансляции живут (старые вкладки работают), новые не создаются. Решение оператора: больше внешних адресов в пуле, агрессивнее таймауты, лимит портов на абонента.

Задача 5. Из офиса не работает только телефония через SIP-провайдера: звонок устанавливается, но «тишина в обе стороны». Что подозревать на NAT-роутере?

SIP ALG: NAT-помощник криво переписывает адреса внутри SIP-сообщений, сигнализация проходит, а RTP-поток (голос) едет на неверные адреса/порты. Стандартное лечение — отключить SIP ALG на роутере (провайдеры телефонии сами просят это в своих инструкциях).

Задача 6. В AWS security group разрешён входящий 443 — сервис работает. В NACL сабнета разрешили только входящий 443 — и всё сломалось. Почему?

NACL — stateless: он не помнит сессий, поэтому надо явно разрешить и исходящие ответы — а они уходят на эфемерные порты клиента (1024–65535). SG — stateful, ему хватает одного входящего правила. Это прямое следствие разницы ACL vs stateful firewall.

Мост к следующему модулю

Ты умеешь настраивать NAT и ACL — на Cisco. Но завтра перед тобой окажется Juniper или MikroTik, и команды будут другими, а концепты — теми же. Следующий модуль — «один и тот же NAT/ACL/OSPF на трёх вендорах»: научишься переносить знание между синтаксисами и выживать в любом CLI.