114 lines
6.1 KiB
Markdown
114 lines
6.1 KiB
Markdown
# 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`
|