steer-obfs — серверная половина «WireGuard поверх TCP»#
Ставится на тот же VPS, где живёт WireGuard. Принимает поддельный TCP от роутеров и отдаёт разобранные датаграммы локальному WireGuard; обратно — так же. Ключей, конфигурации туннеля и доступа к нему не требует: для него это просто UDP-порт на localhost.
роутер VPS
wg0 ──udp──► steer obfs ──поддельный TCP──► steer obfs-server ──udp──► wg (51820)
Каталог самодостаточен: в нём нет ничего, кроме установщика, юнита и этой страницы, и он переносится в отдельный репозиторий целиком, если серверную часть захочется выпускать отдельно от ядра. Единственная связь с ядром — исходники, из которых собирается тот же бинарник.
Настройка на стороне роутера — блок obfs у выхода kind: interface; поля и требования к MTU
описаны в ../docs/contract-v1.md §1.
Установка#
Готовым архивом — так проще и компилятор на сервере не нужен:
# со страницы релизов: steer-obfs-<версия>-<x86_64|aarch64>.tar.gz
tar xzf steer-obfs-<версия>-x86_64.tar.gz
cd obfs-x86_64
sudo sh install.sh --port 4567 --forward 127.0.0.1:51820
Если страница релизов не открывается или архив не скачивается — скорее всего, у провайдера этого
сервера закрыт githubusercontent.com: прямая ссылка релиза перенаправляет именно туда. Те же
архивы лежат в ветке
dist-vps, которую отдают хосты, не затронутые
такой блокировкой. Установщик хаба (xs_install.sh) ходит по обоим адресам сам и называет каждый,
который не ответил.
Бинарник в архиве статический (musl), собран из тех же исходников обфускации (obfs.c,
obfsmain.c), что модуль steer-obfs в пакете для роутера: отдельного серверного кода нет и быть
не должно — две реализации означали бы две обфускации, расходящиеся в мелочах на проводе. В пакете
роутера тот же код разложен по libsteer.so и модулю, а здесь он в одном файле без библиотек.
Статика означает, что дистрибутив и версия libc на VPS не имеют значения.
Из исходников — если своей архитектуры в релизе нет:
git clone https://github.com/splify2/steer && cd steer
sudo sh server/install.sh --port 4567 --forward 127.0.0.1:51820
Установщик один на оба пути: лежит рядом готовый бинарник — берёт его, нет — собирает системным
cc (внешних зависимостей у базовой сборки нет вовсе). Кладёт его в /usr/local/sbin/steer, пишет
/etc/default/steer-obfs и поднимает systemd-юнит steer-obfs. Повторный запуск — обновление на
месте.
Настройки живут в /etc/default/steer-obfs, а не в юните: systemctl edit не понадобится, а
обновление установщиком юнит перезапишет.
Проверить:
systemctl status steer-obfs
journalctl -u steer-obfs -f
Что нужно открыть#
- TCP на порт обфускации (в примере 4567) — со стороны интернета. Это единственное, что видно снаружи; UDP-порт WireGuard наружу открывать больше не нужно и лучше закрыть: смысл затеи в том, чтобы снаружи не было видно UDP.
- Порт WireGuard остаётся слушать на
127.0.0.1или на всех адресах — сюда приходит уже локальный трафик.
Правило против RST ставит сам процесс (таблица nft inet steer_obfs) и снимает его при
остановке. Оно нужно потому, что сокета на этом порту у ядра нет, и на входящий сегмент оно
ответило бы RST, обрывая сессию. Если на сервере нет nft, поставьте эквивалент вручную:
iptables -I OUTPUT -p tcp --sport 4567 --tcp-flags RST RST -j DROP
MTU#
Внешний конверт — 20 байт IP плюс 20 байт TCP, сам WireGuard — ещё 32. Значит
MTU интерфейса wg = MTU канала − 72 (1428 при обычных 1500)
и он обязан совпадать на обеих сторонах туннеля. Расхождение не ломает связь целиком: маленькие пакеты ходят, большие пропадают — самый трудный в диагностике случай.
Совместимость#
Формат на проводе совместим с phantun: вместо этого
сервера может стоять phantun_server, а вместо клиента на роутере — phantun_client. Отличия
нашей стороны — случайный начальный номер, MSS в SYN и регулярные подтверждения — это поля,
которые вторая сторона игнорирует.
Разница в требованиях к системе: phantun_server работает через TUN и требует ip_forward,
DNAT на адрес tun-пира и правило NAT. Здесь ничего этого нет — сырой сокет и одно правило.
Чего этот слой не делает#
Не шифрует (это делает WireGuard) и не защищает от активного зондирования: поток без ретрансмиссий и без обновлений окна отличим от настоящего TCP при целенаправленном анализе. Задача — пройти там, где UDP режут или пропускают по белому списку протоколов, а не спрятаться от исследователя.