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

120 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2026-04-17
type: decision
tags: [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 и перезаписывал метку: `0x00100000``0x0001bd22`.
Затем `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)
```bash
# было:
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; }'
```
Одной командой:
```bash
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`
```bash
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`.
## Диагностика на будущее
```bash
# Быстрый тест: метка жива после всех 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`