NAT на Linux-сервере позволяет внутренним клиентам выходить во внешнюю сеть через один WAN-интерфейс. Для рабочей схемы нужны три условия: ядро Linux должно пересылать IPv4-пакеты, клиенты должны использовать адрес Linux-сервера как шлюз по умолчанию, а nftables должен изменять исходный адрес в цепочке postrouting.
Для динамического внешнего адреса применяйте MASQUERADE. Для закрепленного публичного IPv4-адреса используйте SNAT. DNAT решает обратную задачу: направляет входящий трафик с внешнего адреса и порта на внутренний сервер.
В примерах ниже внешний интерфейс называется eth0, внутренний интерфейс eth1, LAN имеет адресное пространство 192.168.10.0/24, а Linux-шлюз использует адрес 192.168.10.1. Перед загрузкой правил сопоставьте эти значения с реальной схемой и проверьте конфигурацию командой nft -c.
Короткий ответ: минимальный рабочий NAT для выхода в интернет
Минимальная конфигурация состоит из параметра net.ipv4.ip_forward=1, разрешения состояния forward для направления LAN - WAN, разрешения обратных пакетов и правила MASQUERADE в таблице NAT. Клиенты в сети 192.168.10.0/24 должны отправлять трафик на 192.168.10.1.
Минимальный пример для динамического внешнего адреса
Включите пересылку IPv4 до загрузки правил:
sysctl -w net.ipv4.ip_forward=1
Добавьте в существующий файл nftables минимальные таблицы фильтрации и NAT:
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth0 ip saddr 192.168.10.0/24 ct state new,established,related accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 masquerade
}
}
Проверьте синтаксис и примените конфигурацию:
nft -c -f /etc/nftables.conf
nft -f /etc/nftables.conf
После этого клиент с адресом из сети 192.168.10.0/24 должен использовать шлюз 192.168.10.1. Правило MASQUERADE заменит его исходный адрес на текущий адрес интерфейса eth0. Если провайдер выдает адрес через DHCP, PPPoE или другой динамический механизм, это обычно подходящий вариант.
Проверьте выход с клиента сначала по IP-адресу, затем через DNS. Для лабораторного стенда с отдельными сетевыми интерфейсами можно арендовать VDS или VPS в облаке, но сетевые интерфейсы, маршруты и ограничения провайдера нужно проверить отдельно.
Что заменить в примере перед применением
eth0замените на реальный WAN-интерфейс, через который командаip route get 1.1.1.1отправляет внешний трафик.eth1замените на интерфейс внутренней сети или на конкретный VLAN-интерфейс.192.168.10.0/24замените на подсеть клиентов.192.168.10.1замените на адрес Linux-сервера в LAN.- Для статической схемы вместо MASQUERADE укажите публичный адрес в правиле SNAT.
- Для DNAT отдельно укажите внешний IP, внешний TCP-порт, адрес внутреннего сервера и его порт.
Имена интерфейсов могут появляться через NetworkManager, Netplan или systemd-networkd. WAN может быть обычным Ethernet-интерфейсом, VLAN, PPPoE-устройством или интерфейсом виртуальной машины. Нельзя переносить правило с eth0 на другой сервер без проверки имени интерфейса и таблицы маршрутизации.
Схема сети и проверки перед настройкой
Путь пакета в базовой схеме выглядит так: клиент в LAN, интерфейс eth1, цепочка forward, интерфейс eth0, внешний шлюз. NAT меняет адреса пакета, но не поднимает интерфейсы, не выдает адреса клиентам и не добавляет маршрут по умолчанию.
Тестовая топология и соглашения статьи
| Компонент | Пример | Назначение |
|---|---|---|
| WAN-интерфейс | eth0 | Выход к провайдеру или внешнему маршрутизатору |
| LAN-интерфейс | eth1 | Подключение внутренних клиентов |
| LAN-подсеть | 192.168.10.0/24 | Источники исходящего трафика |
| Адрес Linux-шлюза | 192.168.10.1 | Шлюз по умолчанию для клиентов |
| Внутренний сервер | 192.168.10.20 | Пример цели DNAT |
Если в инфраструктуре есть несколько VLAN, каждому L3-сегменту нужен адрес шлюза на Linux-сервере. Для сети 192.168.20.0/24 это может быть VLAN-интерфейс с адресом 192.168.20.1. В NAT и forward нужно явно добавить эту подсеть.
Проверка интерфейсов и таблицы маршрутизации
Начните с состояния интерфейсов и адресов:
ip -br addr
ip link show
ip route
ip route get 1.1.1.1
Ожидаемый результат включает адрес на LAN-интерфейсе, адрес или динамическую конфигурацию на WAN-интерфейсе и маршрут default через внешний шлюз. Команда ip route get 1.1.1.1 должна показать интерфейс eth0 и исходный адрес, который ядро выбрало для внешнего назначения.
Проверьте доступность внешнего шлюза с самого маршрутизатора:
ping -c 3 1.1.1.1
ip neigh show dev eth0
Если Linux-сервер сам не достигает внешней сети, NAT не исправит проблему. Сначала проверьте кабель или виртуальный коммутатор, адрес WAN, default route, ARP и фильтрацию локального трафика.
Адреса клиентов и шлюз по умолчанию
На внутреннем клиенте проверьте адрес, маршрут и соседей:
ip -br addr
ip route
ip neigh show
ping -c 3 192.168.10.1
В выводе ip route должна присутствовать строка default via 192.168.10.1. Если клиент получает параметры через DHCP, адрес Linux-сервера нужно указать как option router. При статической настройке проверьте маску: для 192.168.10.0/24 это 255.255.255.0.
Доступность шлюза по ARP отделяет проблему локального сегмента от проблемы маршрутизации. Если команда ping до 192.168.10.1 не проходит, проверяйте VLAN, access-порт, trunk, маску и состояние интерфейса. Правила NAT на этом этапе еще не нужны для диагностики.
DNS проверяется отдельно. Клиент может достигать внешнего IP-адреса и при этом не разрешать имена из-за неверного resolver, блокировки UDP 53 или недоступности TCP 53 для крупных ответов.
Если внутренняя сеть разделена на VLAN
Linux должен иметь VLAN subinterface или иной L3-интерфейс для каждой маршрутизируемой сети. Коммутатор передает соответствующие теги через trunk, а клиентский access-порт принимает один нужный VLAN.
Например, для VLAN 20 с сетью 192.168.20.0/24 недостаточно создать правило MASQUERADE по интерфейсу. Нужно убедиться, что Linux имеет адрес 192.168.20.1, знает маршрут этой сети, а клиенты используют этот адрес как шлюз.
ip -br addr
ip route show
ip route get 1.1.1.1
В NAT ограничивайте правило исходной подсетью. Физический интерфейс сам по себе не описывает все сети, которые могут через него проходить. Для нескольких VLAN перечисляйте разрешенные подсети явно или используйте именованный набор nftables.
Подробный разбор обычной маршрутизации между внутренними сетями приведен в статье о маршрутизации между подсетями на Linux-сервере. NAT стоит добавлять после проверки L3-связности и обратных маршрутов.
Включение IPv4 forwarding и разрешение трафика в nftables
У Linux-шлюза есть три отдельные функции. Параметр net.ipv4.ip_forward разрешает ядру пересылать IPv4 между интерфейсами. Цепочка forward решает, какие проходящие пакеты пропустить. Цепочка NAT меняет адрес источника или назначения для соединения.
Временное и постоянное включение forwarding
Для быстрой проверки примените параметр до перезагрузки:
sysctl -w net.ipv4.ip_forward=1
sysctl net.ipv4.ip_forward
Для постоянной настройки создайте файл /etc/sysctl.d/99-router.conf со строкой:
net.ipv4.ip_forward = 1
Загрузите параметры и проверьте результат:
sysctl --system
sysctl net.ipv4.ip_forward
Ожидаемое значение равно 1. Этот параметр относится к IPv4. IPv6 forwarding управляется отдельными параметрами и правилами firewall.
Минимальная политика forward для исходящего трафика
Для маршрутизатора с политикой drop разрешите возврат уже установленных соединений и новый трафик из нужной LAN-подсети через WAN:
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth0 ip saddr 192.168.10.0/24 ct state new,established,related accept
}
Правило ct state established,related accept пропускает ответы на соединения, начатые из LAN, и связанные потоки. Направление LAN - WAN ограничено входным интерфейсом, выходным интерфейсом и исходной подсетью.
Безусловное правило iifname eth1 oifname eth0 accept подходит для краткого лабораторного теста, но расширяет разрешенный трафик. В рабочей сети задавайте источник, назначение, протокол или порт, если это соответствует политике доступа.
Проверка порядка и конфликтов правил
До изменения конфигурации сохраните текущий ruleset в отдельный файл и изучите его:
nft list ruleset
nft list tables
Проверьте, кто управляет firewall. firewalld, Docker, libvirt, NetworkManager и ручные вызовы nft могут создавать собственные таблицы и цепочки. Правило с политикой drop в другой базовой цепочке может блокировать пакет раньше, чем он достигнет нужного разрешения.
После тестового соединения снова выведите ruleset и проверьте счетчики. Рост счетчика на LAN - WAN в forward при отсутствии роста в postrouting указывает на несовпадение исходной подсети, WAN-интерфейса или NAT-цепочки.
Порядок обработки пакета, включая этапы prerouting, routing decision, forward и postrouting, разобран в материале о взаимодействии nftables и таблицы маршрутизации Linux.
SNAT в nftables, MASQUERADE в Linux и DNAT: что выбрать
SNAT и MASQUERADE меняют адрес источника, поэтому применяются для исходящих соединений, обычно в postrouting. DNAT меняет адрес назначения, обычно в prerouting, и нужен для публикации внутреннего сервиса или перенаправления входящего трафика.
| Механизм | Когда использовать | Пример |
|---|---|---|
| SNAT | Внешний IPv4-адрес закреплен | snat to 203.0.113.5 |
| MASQUERADE | Внешний адрес меняется или выдается динамически | masquerade |
| DNAT | Нужно направить входящий порт на внутренний узел | dnat to 192.168.10.20:443 |
NAT использует conntrack. Для нового соединения ядро создает запись и выбирает трансляцию. Последующие пакеты потока проходят по сохраненному состоянию, поэтому NAT-цепочка обычно не увеличивает счетчик на каждом пакете.
SNAT в nftables для статического публичного адреса
Если провайдер закрепил адрес 203.0.113.5, правило может выглядеть так:
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 snat to 203.0.113.5
}
}
Ограничение по oifname и исходной подсети исключает случайную трансляцию другого трафика. Адрес 203.0.113.5 должен быть назначен WAN-интерфейсу или маршрутизироваться провайдером через этот Linux-шлюз.
Ответы внешних узлов должны возвращаться на этот адрес. Если upstream-маршрутизатор не знает обратный путь или другой узел уже использует тот же публичный адрес, соединения будут обрываться независимо от синтаксиса правила.
MASQUERADE в Linux для динамического адреса
MASQUERADE автоматически берет текущий адрес выходного интерфейса и подходит для DHCP, PPPoE, мобильных каналов и других подключений с меняющимся IPv4.
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 masquerade
}
}
Ограничьте правило исходной подсетью и WAN-интерфейсом. Универсальная запись oifname eth0 masquerade может трансформировать трафик дополнительных сетей, контейнеров или виртуальных машин, если они используют этот интерфейс.
Для постоянного публичного адреса SNAT обычно дает более явную конфигурацию. MASQUERADE сохраняет удобство при смене адреса, но после изменения WAN-состояния старые conntrack-записи могут потребовать повторного установления соединения.
DNAT для публикации внутреннего сервиса
Пример направляет входящие TCP-соединения на внешний адрес 203.0.113.5 и порт 443 к серверу 192.168.10.20:443:
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname eth0 ip daddr 203.0.113.5 tcp dport 443 dnat to 192.168.10.20:443
}
}
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth0 oifname eth1 ip daddr 192.168.10.20 tcp dport 443 ct state new,established accept
}
}
DNAT меняет адрес назначения до принятия решения о маршруте. После трансляции пакет должен попасть в цепочку forward, где разрешение ограничено внешним интерфейсом, внутренним адресом и портом.
Внутренний сервер должен слушать порт 443, разрешать соединения в своем локальном firewall и использовать Linux-шлюз или другой маршрут, через который ответы возвращаются к маршрутизатору. Только наличие строки dnat не публикует сервис полностью.
Полные варианты проброса портов, включая HTTP, HTTPS, SSH, conntrack и hairpin NAT, собраны в руководстве по DNAT в nftables.
Когда NAT не нужен
Между внутренними сетями, VLAN или площадками с корректными маршрутами лучше применять обычную маршрутизацию и фильтрацию. Каждая сеть должна знать обратный маршрут через нужный шлюз.
Лишний NAT усложняет аудит: внутренний сервер видит адрес трансляции вместо реального клиента, журналы становятся менее информативными, а диагностика сервисов требует анализа conntrack. Для межсегментного доступа сначала настройте маршруты и правила forward, затем добавляйте NAT только при конкретной необходимости.
Рабочие примеры NAT в nftables для типовых сценариев
Следующие фрагменты показывают отдельные схемы. Таблицы и цепочки с одинаковыми именами нужно объединить в один ruleset. Нельзя без проверки загружать каждый фрагмент как отдельный файл: существующая таблица или цепочка может получить конфликт имен.
Один внутренний сегмент и динамический WAN
Для одного LAN-сегмента используйте такой базовый набор:
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth0 ip saddr 192.168.10.0/24 ct state new,established,related accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 masquerade
}
}
На клиентах укажите 192.168.10.1 как шлюз. DNS-сервер можно выдать через DHCP или задать вручную, но его доступность нужно проверить отдельным запросом.
Перед загрузкой выполните:
nft -c -f /etc/nftables.conf
nft -f /etc/nftables.conf
nft list chain inet filter forward
nft list chain ip nat postrouting
Несколько внутренних сетей или VLAN
Для двух разрешенных подсетей можно использовать набор адресов:
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth0 ip saddr { 192.168.10.0/24, 192.168.20.0/24 } ct state new,established,related accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 masquerade
oifname eth0 ip saddr 192.168.20.0/24 masquerade
}
}
Отдельные правила для каждой сети проще читать при небольшом количестве VLAN. Набор адресов удобнее при расширении списка, но его нужно поддерживать вместе с адресацией и политиками доступа.
До проверки NAT убедитесь, что Linux видит оба L3-интерфейса:
ip -br addr
ip route show table main
ip route get 1.1.1.1 from 192.168.20.10
Каждый VLAN должен иметь собственный шлюз. Правило NAT не заменяет маршрутизацию между коммутатором, Linux и клиентской подсетью.
Статический внешний адрес и SNAT
Для сети с фиксированным публичным адресом примените SNAT:
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth0 ip saddr 192.168.10.0/24 snat to 203.0.113.5
}
}
Проверьте три условия: адрес 203.0.113.5 назначен или маршрутизируется к этому серверу, upstream знает обратный путь, а правило forward разрешает исходящие соединения. Если внешний адрес добавлен как secondary address, проверьте его командой ip addr show dev eth0.
Для диагностики сравните маршрут и выбранный источник:
ip route get 1.1.1.1
ip addr show dev eth0
nft list chain ip nat postrouting
Проброс HTTPS на внутренний сервер
Полная схема для опубликованного HTTPS включает DNAT, forward и корректный обратный путь:
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname eth0 ip daddr 203.0.113.5 tcp dport 443 dnat to 192.168.10.20:443
}
}
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth0 oifname eth1 ip daddr 192.168.10.20 tcp dport 443 ct state new,established accept
}
}
Проверьте прослушивание сервиса:
ss -lntup
ip route show
nft list chain ip nat prerouting
nft list chain inet filter forward
Сервис должен слушать адрес 192.168.10.20 или 0.0.0.0, а firewall внутреннего сервера должен разрешать TCP 443. Если сервер использует другой default gateway, ответы могут уйти в обход Linux и соединение не завершится.
Доступ из LAN к сервису по его внешнему адресу
Запрос из LAN к публичному адресу называют hairpin NAT. Внешнее DNAT-правило с условием iifname eth0 его не обработает, поэтому для внутреннего клиента нужен отдельный путь.
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat;
iifname eth1 ip daddr 203.0.113.5 tcp dport 443 dnat to 192.168.10.20:443
}
chain postrouting {
type nat hook postrouting priority srcnat;
oifname eth1 ip saddr 192.168.10.0/24 ip daddr 192.168.10.20 tcp dport 443 snat to 192.168.10.1
}
}
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth1 ip saddr 192.168.10.0/24 ip daddr 192.168.10.20 tcp dport 443 ct state new,established accept
}
}
Дополнительный SNAT заставляет внутренний сервер отправить ответ через Linux-шлюз. Без него сервер может ответить клиенту напрямую, и conntrack не увидит симметричный поток.
Для одной внутренней сети проще использовать split DNS: внутри имя сервиса разрешается в 192.168.10.20, снаружи в публичный адрес. Такая схема снижает количество NAT-правил и упрощает журналы.
Сохранение NAT-конфигурации после перезагрузки
Временная команда nft add rule меняет активное состояние ядра. После перезагрузки эти правила исчезнут, если их не сохранить в конфигурационном файле и не подключить системную службу.
Проверка и сохранение файла nftables
Для файла /etc/nftables.conf используйте последовательность:
nft -c -f /etc/nftables.conf
nft -f /etc/nftables.conf
systemctl enable --now nftables
systemctl status nftables
Команда nft -c проверяет синтаксис без применения правил. Сервис загрузит файл при старте системы. Перед перезапуском сохраните текущий ruleset:
nft list ruleset > /root/nftables-backup.conf
Если на сервере уже работает firewalld, не подключайте параллельно независимый файл с конфликтующими базовыми цепочками. Выберите один источник управления правилами или четко разделите таблицы и зоны.
Постоянный IPv4 forwarding
Проверьте, что параметр записан в /etc/sysctl.d/99-router.conf:
grep net.ipv4.ip_forward /etc/sysctl.d/99-router.conf
sysctl --system
sysctl net.ipv4.ip_forward
Значение 1 нужно сохранять вместе с правилами forward и NAT. Само включение forwarding расширяет возможность пересылки пакетов между интерфейсами, поэтому политика forward должна ограничивать направления и состояния соединений.
Сохранение интерфейсов, адресов и маршрутов
nftables не назначает адреса интерфейсам. NetworkManager хранит профили подключений и маршруты в своих настройках, Netplan генерирует конфигурацию для выбранного backend, а systemd-networkd использует файлы сетевых юнитов.
После перезагрузки проверьте конфигурацию в таком порядке:
- Убедитесь, что появились WAN- и LAN-интерфейсы.
- Проверьте адрес Linux-шлюза в каждой внутренней сети.
- Проверьте VLAN ID и состояние trunk.
- Проверьте default route через внешний шлюз.
- Проверьте
net.ipv4.ip_forward. - Проверьте загруженные таблицы и счетчики nftables.
NAT не заработает, если служба загрузила правила раньше сетевого профиля, а внешний маршрут еще отсутствует. После старта системы сначала проверяйте интерфейсы и маршруты, затем состояние nftables.
Команды управления маршрутами, включая policy routing и несколько таблиц, приведены в шпаргалке по маршрутизации Linux.
Проверка работы NAT от клиента до внешнего сервиса
Диагностируйте путь по участкам: сам Linux-сервер, LAN-клиент, forward, postrouting, conntrack, внешний ответ и DNS. Один успешный ping не подтверждает работу всех TCP-сервисов, потому что ICMP часто фильтруют отдельно.
Проверка с самого Linux-сервера
Сначала проверьте WAN без участия NAT:
ip -br addr
ip route
ip route get 1.1.1.1
ping -c 3 1.1.1.1
curl -4 --interface eth0 -I $CHECK_ENDPOINT
dig +short $CHECK_DOMAIN
Замените переменные на известный TCP-ресурс и доменное имя. Если сервер не достигает внешнего IP, исправляйте WAN-адрес, default route, внешний шлюз или локальный firewall. Правила NAT клиента в этом случае не меняют причину.
Проверка с внутреннего клиента
На клиенте подтвердите правильный шлюз:
ip route
ip route get 1.1.1.1
ping -c 3 192.168.10.1
ping -c 3 1.1.1.1
curl -4 -I $CHECK_ENDPOINT
dig +short $CHECK_DOMAIN
Порядок проверок дает локальный ориентир. Ошибка до 192.168.10.1 указывает на LAN, VLAN или адресацию. Доступный шлюз при недоступном внешнем IP указывает на forwarding, forward-фильтр, маршрут, NAT или обратный трафик. Доступный IP при ошибке dig указывает на отдельную проблему DNS.
Для TCP-порта используйте curl или nc:
nc -vz $CHECK_HOST 443
Счетчики nftables и состояние conntrack
Выведите правила вместе со счетчиками:
nft -a list ruleset
nft list chain inet filter forward
nft list chain ip nat postrouting
nft list chain ip nat prerouting
conntrack -L
Счетчик forward должен расти при новых попытках клиента выйти через WAN. Счетчик postrouting должен расти для новых соединений, которые совпали с правилом MASQUERADE или SNAT. NAT-цепочка обрабатывает первый пакет потока, поэтому число пакетов в NAT-счетчике может быть меньше числа пакетов в filter.
После изменения правила создайте новое соединение. Существующая запись conntrack может продолжать использовать старое решение NAT. Команду очистки состояния применяйте выборочно и с учетом активных соединений, особенно на рабочем шлюзе.
Проверка пакетов через tcpdump
Снимайте трафик с фильтром по клиенту и порту:
tcpdump -ni eth1 host 192.168.10.50
tcpdump -ni eth0 host 1.1.1.1
Во второй команде уберите начальный пробел перед tcpdump. На eth1 исходный адрес должен совпадать с адресом клиента, например 192.168.10.50. На eth0 после SNAT или MASQUERADE должен отображаться внешний адрес. Ответы должны появляться на WAN и затем приходить на LAN.
Для TCP-проверки можно сузить захват:
tcpdump -ni eth1 host 192.168.10.50 and port 443
tcpdump -ni eth0 port 443
Если SYN виден на LAN, но не виден на WAN, ищите проблему в forward или маршруте. Если SYN уходит с WAN, но SYN-ACK не возвращается, проверяйте SNAT, upstream и внешний firewall. Если ответ приходит на WAN, но не появляется на LAN, проверяйте conntrack, обратное разрешение forward и локальный firewall.
Диагностика: NAT работает частично или не работает
Сопоставляйте симптом с конкретным участком пути. Это быстрее, чем менять одновременно forwarding, NAT и DNS.
Клиент не видит Linux-шлюз
- Проверьте, поднят ли LAN-интерфейс командой
ip link show dev eth1. - Проверьте адрес шлюза командой
ip addr show dev eth1. - Сверьте маску клиента и сервера.
- Для VLAN проверьте VLAN ID на subinterface и передачу тега через trunk.
- Проверьте ARP через
ip neigh show dev eth1.
Ожидаемый результат: клиент получает MAC-адрес Linux-шлюза и успешно отправляет ему ICMP. Пока этот результат не достигнут, анализировать MASQUERADE рано.
Шлюз доступен, но внешний IP недоступен
Проверьте forwarding и правила:
sysctl net.ipv4.ip_forward
ip route get 1.1.1.1 from 192.168.10.50
nft list chain inet filter forward
nft list chain ip nat postrouting
Если счетчик forward не растет, пакет не совпадает с интерфейсами или не достигает цепочки. Если forward растет, а postrouting нет, проверьте исходную подсеть, WAN-интерфейс и таблицу NAT. Если оба счетчика растут, переходите к tcpdump и проверке обратного трафика.
IP-адреса доступны, но доменные имена не разрешаются
Сравните IP-доступ и DNS-запрос:
ping -c 3 1.1.1.1
dig $CHECK_DOMAIN
dig @192.168.10.1 $CHECK_DOMAIN
cat /etc/resolv.conf
Проверьте, какой resolver настроен на клиенте, доступен ли DNS по UDP 53 и TCP 53, а также разрешены ли эти направления политикой forward. Если DNS-сервис работает на маршрутизаторе, проверьте его bind-адрес и локальный firewall. Снимок tcpdump -ni eth1 port 53 покажет запрос и ответ в LAN.
DNS не доказывает неисправность NAT сам по себе. Запрос к IP-адресу и разрешение имени проходят через разные сервисы и правила.
Пакеты уходят, но ответы не возвращаются
Проверьте исходный адрес на WAN через tcpdump. При SNAT он должен совпадать с адресом, который провайдер маршрутизирует к Linux-серверу. При MASQUERADE он должен совпадать с текущим адресом eth0.
Для входящих ответов проверьте:
nft list chain inet filter forward
conntrack -L
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.eth0.rp_filter
ip route show
Строгий rp_filter может отбросить асимметричный трафик, если обратный маршрут не совпадает с ожидаемым интерфейсом. Меняйте этот параметр только после подтверждения причины и проверки policy routing. Сначала исправьте архитектуру маршрутов и upstream, если это возможно.
DNAT создан, но опубликованный порт недоступен
Проверяйте DNAT по всей цепочке:
- Внешний клиент обращается к правильному публичному адресу и TCP-порту.
- Счетчик
preroutingрастет при новой попытке. - После DNAT пакет совпадает с разрешением в
forward. - Сервис слушает
192.168.10.20:443, что видно в выводеss -lntup. - Локальный firewall внутреннего сервера разрешает TCP 443.
- Default gateway сервера возвращает ответы через Linux-шлюз.
Тест из той же LAN может давать другой результат из-за hairpin NAT. Для проверки внешней публикации используйте отдельную внешнюю точку. Если внешний тест работает, а внутренний нет, настройте split DNS или отдельные hairpin-правила.
Ограничение доступа и контроль безопасности
NAT не заменяет firewall. Он меняет адреса и порты, а решение о разрешении трафика принимает filter-цепочка. Базовая политика для маршрутизатора должна явно описывать разрешенные направления и состояния соединений.
Ограничение исходящего трафика по подсети и интерфейсу
Правило MASQUERADE ограничивайте исходной сетью и WAN-интерфейсом:
oifname eth0 ip saddr 192.168.10.0/24 masquerade
Для нескольких VLAN перечислите каждую разрешенную сеть. Если через Linux проходят контейнеры, виртуальные машины или служебные сегменты, проверьте, должны ли они использовать тот же NAT. Источник 0.0.0.0/0 применяйте только при осознанной необходимости.
Минимально необходимая политика forward
Начните с default deny и добавляйте правила под реальные задачи:
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname eth1 oifname eth0 ip saddr 192.168.10.0/24 ct state new,established,related accept
}
Если исходящий доступ нужно ограничить, замените широкое разрешение правилами по протоколам и портам. Для веб-доступа нужны TCP 80 и 443, для DNS обычно UDP 53 и TCP 53, для NTP UDP 123. Набор зависит от рабочих задач и политики компании.
Управление Linux-сервером, доступ к DNS, обновлениям и внутренним сервисам разделяйте с помощью отдельных правил. Логи отказов ограничивайте, например limit rate 5/second, чтобы всплеск трафика не создал лишнюю нагрузку на диск и CPU.
Безопасная публикация сервисов через DNAT
Публикуйте конкретный адрес и порт:
iifname eth0 oifname eth1 ip daddr 192.168.10.20 tcp dport 443 ct state new,established accept
Не пробрасывайте наружу SSH, панели управления и другие административные интерфейсы без ограничения источников, многофакторной защиты и отдельного контроля доступа. Если доступ нужен из нескольких доверенных адресов, добавьте условие по ip saddr.
Проверяйте публикацию с внешней точки и контролируйте журналы внутреннего сервиса. Счетчик DNAT показывает совпадение правила, но не подтверждает, что приложение приняло соединение.
IPv6 и границы применения NAT
Приведенные правила относятся к IPv4. В IPv6 обычно используют глобальную адресацию, маршрутизацию и фильтрацию без классического NAT. IPv6 forwarding и firewall настраиваются отдельно.
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl net.ipv6.conf.all.forwarding
Не переносите IPv4-правила SNAT и MASQUERADE в IPv6 без отдельного проектного решения. Для IPv6 проверьте префиксы, объявления маршрутов, обратную связность и политику inet6 или ip6 в nftables.