Termux — удобная среда для администрирования и отладки сетевых сценариев прямо на Android. Однако «тонкое управление» сетью часто упирается в два вопроса:
- Как описать контролируемые правила firewall (фильтрацию трафика) через Netfilter/NFTables.
- Как организовать NAT для контейнеров/виртуальных сетей, чтобы трафик из изолированного пространства мог выходить в нужные подсети.
В этой статье мы сфокусируемся на создании кастомных правил nftables и на практическом подходе к правилам NAT для сценариев «контейнер за виртуальным интерфейсом» — с акцентом на безопасность, проверку и воспроизводимость.
Важно про ограничения Android и Termux
На Android права суперпользователя и работа с системными сетевыми подсистемами могут быть ограничены политиками ядра и конкретного устройства. В большинстве сценариев:
- Без повышенных привилегий вы не сможете надежно управлять таблицами nftables на уровне ядра.
- Некоторые интерфейсы (например, bridge/внутренние виртуальные) могут быть недоступны без дополнительных компонент.
- Ни один «обход блокировок» в рамках настройки сети рассматриваться не будет. Мы говорим только о корректной локальной настройке и управлении маршрутизацией.
Если вы работаете в управляемой лабораторной среде или на устройстве с возможностью запускать нужные сетевые операции, ниже — структура и примеры.
Предпосылки и подготовка окружения
Для воспроизводимости проверьте наличие необходимых пакетов. В Termux базово часто доступен nft через репозитории или системные сборки.
pkg update
pkg install nftables iproute2 iptables 2>/dev/null || trueДалее желательно убедиться, что:
- Есть бинарник
nft. - Система поддерживает nftables.
command -v nft && nft --version
cat /proc/net/netfilter/nf_tables 2>/dev/null || trueМодель: firewall и NAT в nftables
В nftables логика строится вокруг таблиц и цепочек. Типовой принцип:
- Таблица фильтрации (например,
filter) управляет тем, что разрешать/блокировать. - Таблица NAT (например,
nat) управляет трансляцией адресов (SNAT/DNAT/masquerade).
Важный момент: при разработке правил всегда начинайте с минимального набора, затем добавляйте исключения и логирование (с умом), чтобы избежать «самоблокировки».
Определение виртуального интерфейса (контейнерной сети)
В лабораторном сценарии у контейнера или виртуальной подсети обычно есть интерфейс или символьная привязка. В терминах nftables нам важны:
- имя интерфейса (например,
eth0в контейнере, или виртуальныйvethXна хосте); - подсеть контейнеров (например,
10.10.0.0/24).
Посмотрите доступные интерфейсы:
ip addr show
ip route showПредположим (как пример для структуры), что контейнеры подключены к виртуальному интерфейсу:
- интерфейс:
veth0 - подсеть:
10.10.0.0/24 - интерфейс выхода в интернет/локальную сеть:
rmnet0(примерно; у вас может быть другой)
Эти значения замените на ваши фактические.
Создание таблиц и цепочек firewall
Начнем с базовой политики: запрет по умолчанию и явные разрешения. Такой подход часто безопаснее.
Создадим таблицу inet filter и цепочки для входа/выхода/пересылки. Для сетей контейнеров чаще всего используется forward, так как трафик проходит через хост.
nft delete table inet filter 2>/dev/null || true
nft add table inet filter
nft 'add chain inet filter input { type filter hook input priority 0; policy drop; }'
nft 'add chain inet filter forward { type filter hook forward priority 0; policy drop; }'
nft 'add chain inet filter output { type filter hook output priority 0; policy drop; }'
echo "Chains created"Теперь добавим базовые правила для localhost и уже установленных соединений (чтобы не «убить» саму диагностику и ответные пакеты):
nft 'add rule inet filter input ct state established,related accept'
nft 'add rule inet filter forward ct state established,related accept'
nft 'add rule inet filter output ct state established,related accept'
# Разрешим петлю (loopback)
nft 'add rule inet filter input iifname "lo" accept'
nft 'add rule inet filter output oifname "lo" accept'
# Разрешим ICMP (по необходимости)
nft 'add rule inet filter input ip protocol icmp accept'
nft 'add rule inet filter output ip protocol icmp accept'Разрешение трафика из контейнеров
Предположим, контейнерная подсеть 10.10.0.0/24 и трафик с неё должен:
- идти в определенную сторону (например, наружу),
- и/или разрешаться определенные протоколы/порты.
Пример: разрешим контейнерам доступ к DNS (UDP/TCP 53) и к вебу (TCP 80/443) через forward. Параметры можно менять.
# Разрешить forward из контейнерной подсети
# (замените интерфейс и подсеть на ваши)
nft 'add rule inet filter forward ip saddr 10.10.0.0/24 tcp dport {80,443} accept'
nft 'add rule inet filter forward ip saddr 10.10.0.0/24 udp dport 53 accept'
nft 'add rule inet filter forward ip saddr 10.10.0.0/24 tcp dport 53 accept'
# Дополнительно можно разрешить весь outbound из контейнеров (осторожно)
# nft 'add rule inet filter forward ip saddr 10.10.0.0/24 accept'
echo "Forward rules added"Для входа к контейнерам обычно задают правила отдельно (например, разрешить доступ с локальной сети к контейнеру на конкретный порт). В этом примере мы оставим input по умолчанию drop и фокусируемся на forward.
Построение таблицы NAT (masquerade / SNAT)
Задача NAT в контейнерных сценариях обычно сводится к тому, чтобы:
- адрес контейнеров был трансформирован в адрес выхода хоста;
- ответный трафик корректно возвращался в контейнер.
Для типового «контейнеры за хостом» часто используют masquerade на выходном интерфейсе.
Создадим таблицу NAT в семействе ip (или inet — но ниже используем ip для простоты).
nft delete table ip nat 2>/dev/null || true
nft add table ip nat
nft 'add chain ip nat postrouting { type nat hook postrouting priority 100; policy accept; }'
# Маскарадинг для трафика контейнеров, выходящего на внешний интерфейс
# Замените oifname и подсеть при необходимости
nft 'add rule ip nat postrouting ip saddr 10.10.0.0/24 oifname "rmnet0" masquerade'
echo "NAT masquerade rule added"Если вы используете фиксированный SNAT, можно задать явный адрес вместо masquerade (актуально при стабильном IP). Но в мобильных/динамических средах чаще удобнее masquerade.
DNAT для сервисов контейнеров (публикация портов)
Если вы хотите, чтобы хост или внешний интерфейс публиковал сервис контейнера (например, контейнер слушает TCP 8080), то нужна DNAT в цепочке prerouting.
Например:
- адрес хоста на входе: условно
A.B.C.D(или правило по интерфейсу); - порт входа:
18080; - контейнерный IP:
10.10.0.10; - порт контейнера:
8080.
Пример DNAT через prerouting (с привязкой к интерфейсу):
nft 'add chain ip nat prerouting { type nat hook prerouting priority -100; policy accept; }'
# Публикация TCP 18080 на контейнер TCP 8080
# Замените oifname на интерфейс, откуда приходит трафик (например, локальный)
nft 'add rule ip nat prerouting iifname "rmnet0" tcp dport 18080 dnat to 10.10.0.10:8080'
echo "DNAT rule added"После DNAT требуется корректная фильтрация в таблице filter для forward, чтобы пакеты реально проходили.
Дополнение firewall под DNAT: разрешение доступа к контейнеру
Разрешим forward на контейнерный IP и порт:
nft 'add rule inet filter forward ip daddr 10.10.0.10 tcp dport 8080 ct state new,established accept'
# При необходимости ограничьте источники
# nft 'add rule inet filter forward ip saddr 192.168.1.0/24 ip daddr 10.10.0.10 tcp dport 8080 accept'
echo "Firewall updated for DNAT"Локальная диагностика и проверка состояния
Перед тестом убедитесь, что:
- таблицы существуют;
- цепочки и правила загрузились;
- нет неожиданных drop.
Проверка:
nft list tables
nft list table inet filter
nft list table ip natДля контроля по счетчикам (packets/bytes) удобно включать правила с счетчиками через стандартный синтаксис. Иногда достаточно посмотреть счетчики текущих правил:
nft -a list table inet filter
nft -a list table ip natОтдельно полезно диагностировать маршрутизацию и доступность DNS/портов из «контейнерного сегмента» (или из процесса, который вы имитируете как клиент).
Порядок внесения изменений без «самоблокировки»
Практика, которая экономит время:
- Сначала создайте цепочки с осознанной политикой (в debug-сценариях временно можно использовать accept вместо drop).
- Убедитесь, что хотя бы
established,relatedразрешены. - Добавляйте разрешения постепенно: сначала ICMP/DNS/базовые порты.
- Только после успешной проверки — ужесточайте политики.
Если нужно, можно временно очистить правила:
nft flush table inet filter 2>/dev/null || true
nft flush table ip nat 2>/dev/null || trueПро локальные VPN и виртуальные сегменты (только для построения сети)
Иногда для формирования локальной сети между устройствами используют VPN, но строго в сценариях создания локального сегмента, а не для обхода ограничений. В таком случае правила nftables применяются к интерфейсам и подсетям, которые создаются VPN-решением, и принцип тот же: фильтрация + NAT/маршрутизация под конкретные подсети. Перед применением правил определите имена интерфейсов и подсети через ip addr и используйте их в правилах.
Типовые ошибки
- Нет правила для forward: input работает, но трафик через хост блокируется.
- DNAT есть, но фильтрация не разрешает: пакеты не доходят до контейнера.
- Неверный интерфейс в
oifname/iifname— masquerade не срабатывает. - Отсутствие разрешения DNS: приложения «молчат», потому что не резолвится домен.
Заключение
Тонкое управление сетью в Termux через Netfilter/NFTables — это мощный инструмент для лабораторных и инженерных задач: вы можете задать строгие firewall‑политики и собрать NAT‑сценарии для контейнеров и виртуальных сегментов. Ключ к успеху — поэтапное внедрение правил, корректная настройка forward под контейнеры, а также аккуратная проверка таблиц и счетчиков.
Если вам нужна помощь с проектированием безопасной сетевой конфигурации, отладкой nftables‑политик под вашу топологию или подготовкой лабораторного стенда, обращайтесь в РыбинскЛАБ — поможем настроить и довести до стабильной работы.