Files
knowledge-base/decisions/2026-04-17-peredelki-podkop-stability-fix.md

6.2 KiB
Raw Permalink Blame History

date, type, tags
date type tags
2026-04-17 decision
decision

2026-04-17: Стабилизация Podkop на Переделках

Проблема

Обход блокировок на OpenWrt Переделки (100.70.197.125) не работал: iPhone/iPad не открывали Instagram, YouTube и т.д. DNS резолвил в FakeIP (198.18.0.x), но соединения к FakeIP адресам висели в SYN_SENT / UNREPLIED.

Корневая причина: конфликт fwmark с NetBird

OpenWrt + Podkop + NetBird VPN — три разные таблицы nftables, и обе — Podkop и NetBird — вешают chain на hook prerouting priority mangle (-150).

ip netbird netbird-mangle-prerouting:

iifname != "wt0" ct state new ip saddr 192.168.2.0/24 meta mark set 0x0001bd22

inet PodkopTable mangle:

iifname @interfaces ip daddr 198.18.0.0/15 meta l4proto tcp meta mark set 0x00100000

При одинаковом приоритете порядок выполнения не гарантирован. По факту на этой системе netbird выполнялся после podkop и перезаписывал метку: 0x001000000x0001bd22.

Затем PodkopTable.proxy (priority dstnat, -100) проверял условие:

meta mark & 0x00100000 == 0x00100000

— которое уже не выполнялось. tproxy не срабатывал, пакеты шли через forward → WAN masquerade и терялись.

Счётчики при этом обманчивы: mangle растёт (правило срабатывает), а proxy tproxy почти не растёт.

Решение

Сдвинуть PodkopTable.mangle на priority -140 (mangle + 10) — выполняется после netbird, восстанавливая метку 0x00100000 перед proxy chain.

Патч /usr/bin/podkop (строка 311)

# было:
nft add chain inet "$NFT_TABLE_NAME" mangle '{ type filter hook prerouting priority -150; policy accept; }'
# стало:
nft add chain inet "$NFT_TABLE_NAME" mangle '{ type filter hook prerouting priority -140; policy accept; }'

Одной командой:

ssh root@100.70.197.125  # 1qaz!QAZ
cp /usr/bin/podkop /usr/bin/podkop.bak-20260417
sed -i '311s/priority -150/priority -140/' /usr/bin/podkop
podkop restart

mangle_output (строка 312, hook output) оставлен -150 — там конфликта нет.

Сопутствующие правки (сделаны ранее)

  1. disable_quic=1 — блокировать HTTP/3 чтобы браузеры не обходили FakeIP через UDP/443
  2. /etc/init.d/sing-box enable — автозапуск после ребута
  3. shutdown_correctly=1
uci set podkop.settings.disable_quic='1'
uci set podkop.settings.shutdown_correctly='1'
uci commit podkop
/etc/init.d/sing-box enable

Результат

  • TCP tproxy: 5584 пакета / 409 KB за ~1 мин
  • UDP tproxy (QUIC): 58 пакетов
  • AWG transfer: 60 MiB received через туннель
  • iPhone 192.168.2.160: 14 ASSURED conntrack соединений

Защита от повторной поломки (guard)

Патч /usr/bin/podkop слетит при opkg upgrade podkop. Поставлен трёхслойный guard:

/usr/sbin/podkop-prio-guard

Проверяет и чинит:

  1. Строку 311 в /usr/bin/podkop (если -150 → восстанавливает -140)
  2. Runtime chain PodkopTable.mangle (если priority mangle → пересоздаёт с priority -140)

Триггеры запуска

  • cron каждые 2 минуты: */2 * * * * /usr/sbin/podkop-prio-guard (crontab root)
  • после ребута: (sleep 30 && /usr/sbin/podkop-prio-guard) & в /etc/rc.local
  • ручной запуск: /usr/sbin/podkop-prio-guard — см. logread -l 50 | grep podkop-prio

Протестированные сценарии восстановления

Сценарий Приоритет после Guard восстанавливает за
podkop restart -140 (сохраняется патчем) не требуется
Патч слетел + podkop restart (имитация opkg upgrade) -150 ≤ 2 мин (cron)
Руками nft delete chain + mangle на -150 -150 ≤ 2 мин (cron)
Ребут роутера зависит от порядка procd sleep 30 после inet-up

Важное на будущее

  1. Конфликт priority при co-existence Podkop + NetBird — если в сети присутствует NetBird (или любой другой nft-wrapper-VPN с hook prerouting priority mangle), Podkop нужно сдвигать на -140 или позже. Это не описано в документации Podkop.
  2. Не верь только счётчику mangle — если proxy.tproxy counter сильно отстаёт, метка где-то перезаписывается.
  3. После opkg upgrade podkop окно поломки до 2 минут (до следующего cron). Для нулевого downtime — вручную: /usr/sbin/podkop-prio-guard && podkop restart.
  4. podkop apply команды не существует — для перегенерации правил: podkop restart.
  5. На OpenWrt Переделки нет conntrack CLI и timeout — только /proc и builtin.
  6. Лог работы guard: logread | grep podkop-prio-guard.

Диагностика на будущее

# Быстрый тест: метка жива после всех mangle chains?
nft list chain inet PodkopTable proxy | grep packets
# Если TCP/UDP tproxy counter = 0 при активном LAN трафике → конфликт mangle

# Перечисление всех prerouting chains с приоритетами
nft list chains | grep -A1 prerouting

Теги

#niikn #peredelki #podkop #netbird #nftables #fwmark #tproxy #amneziawg #fix