qwdtt-cli
Консольный клиент к протоколу qWDTT: VPN поверх TURN-инфраструктуры звонков VK.
Трафик уходит на ваш VPS через TURN-relay ВКонтакте и для сети выглядит как медиапоток
звонка WebRTC, а не как подключение к VPN-серверу.
Это только клиент. Установка и настройка серверной части, панель управления, импорт
подписок и сканирование QR остаются в Android-приложении
qWDTT — здесь их нет и не будет.
Чтобы подключиться, у вас уже должны быть адрес сервера, пароль подключения и хотя бы
одна ссылка на звонок VK (хеш звонка) — те же, что вводятся в приложении. Либо ссылка
qwdtt://config?… или wdtt://… из приложения или от бота сервера: в ней всё это сразу.
Клиент работает на переднем плане: пока запущен qwdtt-cli connect, туннель поднят.
Службы и автозапуска нет. Первый Ctrl+C останавливает туннель и убирает за собой,
второй убивает процесс.
Если нужен графический интерфейс, посмотрите PWDTT;
чем они отличаются — в разделе «Сравнение с PWDTT».
Быстрый старт без командной строки
Набирать команды не обязательно: qwdtt-cli, запущенный без аргументов, ведёт вопросами.
- Скачайте архив для своей системы (раздел «Установка») и распакуйте его.
- Запустите
qwdtt-cli:
- Windows — дважды щёлкните по
qwdtt-cli.exe в распакованной папке. Откроется окно
консоли с меню. Если Windows предупредит о программе из интернета — «Подробнее» →
«Выполнить в любом случае».
- Linux — откройте терминал в распакованном каталоге и наберите
./qwdtt-cli.
- Профиля ещё нет — меню предложит его создать (Enter). Дальше:
- если у вас есть ссылка
qwdtt://config?… или wdtt://… (Android-приложение qWDTT →
экспорт профиля, или бот сервера), вставьте её: адрес, пароль и ссылки на звонки qwdtt-cli возьмёт
из неё. Ссылку при вставке не видно — так и задумано: в ней ваш пароль;
- если ссылки нет, нажмите Enter и ответьте на вопросы: имя профиля (Enter —
home), адрес сервера, пароль подключения (дважды) и ссылки на звонки VK. Адрес и
пароль даёт тот, кто настроил сервер.
- Выберите, что пускать через туннель: весь трафик компьютера (Enter) или только
программы, где указан прокси SOCKS5
127.0.0.1:1080. Первому режиму нужны права
администратора — qwdtt-cli попросит их сам: на Windows появится окно «Разрешить этому
приложению вносить изменения?», и подключение откроется в новом окне; на Linux sudo
спросит пароль вашей учётной записи. Если ваша учётная запись Windows без прав
администратора, qwdtt-cli скажет об этом и предложит второй режим.
- В меню нажмите Enter — «Подключиться». Когда в строке состояния появится «туннель
работает», можно пользоваться интернетом.
Остановить — Ctrl+C (снова откроется меню; в отдельном окне с правами администратора
на Windows — Enter закроет окно) или закрыть окно. Выйти из меню — 0.
Ссылка на звонок VK выглядит как https://vk.com/call/join/…: такую ссылку даёт
звонок VK, к которому присоединяются по ссылке. Обычно ссылки выдаёт тот же, кто дал
пароль. Звонки со временем закрываются — тогда qwdtt-cli скажет, что ссылки больше не работают,
и предложит ввести новые. Проверить ссылки и убрать закрытые можно и сами — пункт
«Обновить ссылки на звонки VK». Там же, в меню, — другой профиль, новый пароль или
адрес сервера, удаление профиля.
Если что-то пошло не так, окно, открытое двойным щелчком, само не закроется: ошибку
можно прочитать, Enter закрывает окно. Запуск без человека — планировщик заданий,
служба, вывод в файл — Enter не ждёт: qwdtt-cli завершается сразу.
Меню — это те же команды, что ниже; qwdtt-cli menu открывает его явно (для ярлыка), а
qwdtt-cli menu -connect <профиль> сразу подключается, без меню, но с теми же вопросами:
права администратора, новые ссылки на звонки. В скриптах и конвейерах qwdtt-cli без
аргументов, как и раньше, печатает список команд.
Установка
Готовая сборка — архив qwdtt-cli_<версия>_windows_amd64.zip: распакуйте его целиком («Извлечь
всё»). В нём каталог с тем же именем: qwdtt-cli.exe, wintun.dll с её лицензией
wintun-LICENSE.txt, пример настроек qwdtt-cli.example.toml, лицензия, лицензии сторонних
компонентов THIRD_PARTY_NOTICES.txt и этот файл. Установка не нужна. Режиму по
умолчанию tun, который пускает через туннель весь трафик системы, нужны права
администратора — из меню qwdtt-cli попросит их сам — и wintun.dll: она уже лежит в архиве
и должна оставаться рядом с qwdtt-cli.exe.
Для Linux готовая сборка — архив qwdtt-cli_<версия>_linux_amd64.tar.gz, а для 64-битных
ARM-машин (Raspberry Pi 4 и 5 с 64-битной системой, ARM-серверы) —
qwdtt-cli_<версия>_linux_arm64.tar.gz. В архиве каталог с тем же именем: qwdtt-cli,
пример настроек, лицензия, THIRD_PARTY_NOTICES.txt и этот файл.
tar xzf qwdtt-cli_<версия>_linux_amd64.tar.gz
qwdtt-cli — один исполняемый файл, рядом с ним ничего не нужно; его можно переложить,
например, в /usr/local/bin. Как собрать его самому — в разделе «Сборка и отладка
под Linux». Права root (через sudo) нужны только режиму tun.
Сборка под Windows
Нужен Go 1.26 или новее, cgo не требуется. Из корня репозитория:
go build -o build\out\qwdtt-cli.exe ./cmd/qwdtt-cli
Этого достаточно для режимов socks и external. Режиму tun (свой сетевой
адаптер, нужны права администратора) нужна ещё wintun.dll — библиотека драйвера
Wintun от авторов WireGuard. В репозитории её нет: это чужой бинарь под своей
лицензией. Скачать и проверить её можно командой из scripts/, она кладёт DLL в
build\out рядом с qwdtt-cli.exe:
go run ./scripts/wintun
Команда берёт фиксированную версию Wintun (сейчас 0.14.1) с wintun.net, сверяет
SHA256 архива с зашитым в код, проверяет подпись DLL (WireGuard LLC) и копирует
wintun.dll вместе с её лицензией. Хеш не совпал или подпись не та — команда
останавливается и ничего не копирует. Другая архитектура — -arch arm64, другой
каталог — -dest <путь>, без сети — -archive <путь к wintun-0.14.1.zip>.
Можно и вручную: скачайте wintun-0.14.1.zip с https://www.wintun.net, сверьте хеш
certutil -hashfile wintun-0.14.1.zip SHA256
07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51
и положите wintun\bin\amd64\wintun.dll рядом с qwdtt-cli.exe. DLL ищется только
в каталоге qwdtt-cli.exe и в System32 — текущий каталог консоли и PATH не подходят.
Без неё qwdtt-cli connect -datapath tun откажет сразу, до подключения:
«рядом с qwdtt-cli нет файла wintun.dll».
Сборка и отладка под Linux
Сборка та же, Go 1.26 или новее, cgo не нужен:
go build -o build/out/qwdtt-cli ./cmd/qwdtt-cli
На Linux работают режимы socks и tun; external здесь не поддерживается.
Режиму socks ничего, кроме самого qwdtt-cli, не нужно: ни прав root, ни системных
пакетов. Режиму tun нужны sudo и ядро 5.12 или новее (подробности — в разделе
«tun на Linux»). Утилиты ip и nft ему не нужны: адаптер, маршруты и правила
qwdtt-cli ставит сам через netlink. Из системных программ он зовёт только resolvconf —
если /etc/resolv.conf ведёт он.
Для отладки пригодятся пакеты (имена — для Debian и Ubuntu):
sudo apt install wireguard wireguard-tools iproute2 nftables tcpdump resolvconf
wireguard, wireguard-tools — модуль ядра и wg, wg-quick: сверить конфиг
от сервера и поднять туннель вручную. Сам qwdtt-cli wireguard-go встраивает
библиотекой, отдельный wireguard-go не нужен.
iproute2, nftables — ip route, ip rule, ss, nft: маршруты и правила
при поднятом туннеле.
tcpdump — убедиться, что трафик и DNS идут через туннель, а не мимо.
resolvconf — без него wg-quick up падает на конфиге со строкой DNS =.
Если сетью управляет NetworkManager, после установки resolvconf файл
/etc/resolv.conf становится ссылкой на /run/resolvconf/resolv.conf и
до перезапуска NetworkManager остаётся без серверов — DNS на машине не
работает. Чинится sudo systemctl restart NetworkManager.
Релиз
Релиз для трёх платформ собирает go run ./scripts/release (из корня
репозитория; кроме Go, нужен только git): zip для Windows и tar.gz для Linux и
macOS. wintun.dll в zip для Windows он кладёт так же, как scripts/wintun (без
сети — с -wintun-archive <путь>), а THIRD_PARTY_NOTICES.txt в каждый архив
собирает go run ./scripts/notices — лицензии всех модулей, слинкованных в qwdtt-cli,
и самого Go. Время файлов в tar.gz фиксированное, так что одинаковые файлы дают
одинаковый архив. Модуль без файла лицензии или с нераспознанной лицензией
останавливает сборку: новую зависимость надо разобрать вручную. Бинари для Linux
и macOS собираются и запускаются. На Linux вживую проверены режимы socks и tun;
на macOS работает только socks, и вживую он там ещё не проверялся.
Ту же команду запускает GitHub Actions (.github/workflows/release.yml) на
Windows: на тег v* после тестов собирается релиз, проверяется, что в каждом
архиве есть всё нужное для запуска и что qwdtt-cli.exe из zip запускается, и архивы вместе с
SHA256SUMS.txt выкладываются черновиком в Releases — опубликовать его надо
вручную. Ручной запуск workflow только собирает: архивы остаются артефактом
прогона.
Быстрый старт в командной строке
-
Заведите профиль. Пароль и хеши спрашиваются скрытым вводом; в файл настроек
попадают только ссылки на хранилище секретов (на Windows — DPAPI, привязка к вашей
учётной записи; на Linux — связка ключей сеанса):
qwdtt-cli profile set home -peer example.org:56000
Или из ссылки qwdtt://config?… или wdtt://…: команда спросит её скрытым вводом (в ссылке пароль,
поэтому аргументом её не передать) или прочитает из stdin:
qwdtt-cli profile import home
qwdtt-cli profile import home < ссылка.txt
Без имени профиль называется именем из ссылки латиницей. Профиль с таким именем уже
есть — отказ, -replace заменяет в нём адрес, воркеры и секреты. -datapath socks
сразу записывает режим. Чего в ссылке нет (пароля, хешей), спрашивается.
-
Проверьте хеши и задержку до сервера. Обе команды не поднимают туннель:
qwdtt-cli hashes
qwdtt-cli ping
hashes печатает по строке на хеш со статусом ok, captcha, dead, limited,
network или error и возвращает код 1, если годных нет.
-
Поднимите туннель. По умолчанию через него идёт весь трафик системы (режим tun),
поэтому нужны права: на Windows — консоль от имени администратора, на Linux —
sudo:
qwdtt-cli connect
sudo qwdtt-cli connect
Через секунду-две в выводе появится == туннель работает. Проверить можно так:
curl https://ifconfig.me покажет адрес сервера, а не ваш.
Имя профиля можно опускать, если профиль один или назван в default_profile.
Флаг перекрывает то же поле профиля на один запуск: qwdtt-cli connect home -workers 27.
-v печатает весь лог ядра. На терминале внизу держится статусная строка
с состоянием, аптаймом и счётчиками; при перенаправлении в файл её нет.
-
Без прав администратора работает режим только для программ с прокси:
qwdtt-cli connect -datapath socks
В выводе появится [SOCKS] слушает 127.0.0.1:1080. Направьте на этот адрес браузер
или приложение, которое умеет ходить через прокси SOCKS5, и проверьте:
curl -x socks5h://127.0.0.1:1080 https://example.org/
Можно и записать datapath = "socks" в профиль. На macOS режим socks — единственный
и потому умолчание. Подробности — в разделе «Режимы доставки трафика».
Если VK попросит капчу, которую ядро не осилило само, на Windows откроется окно
со страницей капчи: решите её, и окно закроется само, а qwdtt-cli продолжит. Срок
написан в заголовке окна. Если окна не видно, оно может оказаться за консолью —
поищите его на панели задач. Окну нужен WebView2 Runtime: он есть в Windows 11 и в актуальных
Windows 10.
На Linux qwdtt-cli открывает страницу капчи в отдельном окне браузера на Chromium:
Chrome, Chromium, Яндекс Браузера, Edge или Brave — какой из них установлен. Решите капчу,
и окно закроется само. Это отдельный экземпляр браузера с пустым профилем: ваших вкладок,
закладок и паролей он не видит. Под sudo окно открывается от имени пользователя, который
вызвал sudo, а не root.
Если окна не будет — на Windows нет Runtime, на Linux нет браузера на Chromium или он не
запустился, qwdtt-cli запущен по SSH, — капча решается в обычном браузере, а qwdtt-cli
печатает в stderr инструкцию:
- Страница капчи открывается в браузере сама. На Linux — через
xdg-open, а под sudo —
в браузере того пользователя, который вызвал sudo, а не root. Если браузер открыть
не вышло (например, по SSH), откройте напечатанную ссылку вручную где угодно.
- В браузере нажмите F12, откройте вкладку Console и вставьте строку, которую напечатал
qwdtt-cli. Если браузер не даёт вставить, наберите в консоли allow pasting и нажмите
Enter — это защита браузера от вставки чужого кода.
- Решите капчу. В консоли браузера появится строка
qwdtt-cli-captcha token <длинная строка>.
- Скопируйте её и вставьте в терминал
qwdtt-cli.
Токен приходится переносить руками: VK отдаёт его только в ответе страницы, в адресной
строке его нет. На всё даётся три минуты.
Файл настроек
profiles.toml лежит в каталоге настроек пользователя: на Windows это
%APPDATA%\qwdtt-cli\, рядом — secrets.json с зашифрованными секретами.
На Linux и macOS — $XDG_CONFIG_HOME/qwdtt-cli/ (обычно ~/.config). Секреты на
Linux идут в связку ключей сеанса (Secret Service: gnome-keyring, KeePassXC, KWallet) и
лежат там зашифрованными; в secrets.json — только их имена. Если связка
заблокирована, она покажет своё окно разблокировки; если его закрыть, команда больше
не спрашивает и сообщит, что секреты не прочитаны. Где связки нет — вход по SSH,
сервер, консоль без графики, macOS, — секреты лежат в secrets.json открытым текстом
под защитой прав 0600 на файл. Какое хранилище выбрано, пишет qwdtt-cli profile set
(«Секреты записаны: …»), а ссылка в profile show начинается с secretservice: или
file:. Секреты, записанные в файл раньше, читаются как прежде и переезжают в связку,
когда их перезаписывают (profile set -password, -hashes, пункты меню). Под sudo
qwdtt-cli берёт каталог того, кто вызвал sudo (~/.config/qwdtt-cli/ его домашнего
каталога, а не root), и созданные файлы оставляет ему во владение; со связкой ключей
говорит тоже от его имени.
Другой путь — флаг -config. Файл правится командами qwdtt-cli profile set и
qwdtt-cli profile import, меню или руками,
пример со всеми полями и пояснениями — qwdtt-cli.example.toml.
| Поле |
Что задаёт |
По умолчанию |
peer |
адрес сервера host:port |
обязательно |
password_ref, vk_hashes_ref |
ссылки на секреты, пишет qwdtt-cli profile set |
обязательно |
workers |
число воркеров, кратно девяти, потолок 108 |
9 |
obfs |
RTP-маскировка: audio или video |
audio |
turn_transport |
udp или tcp; TCP помогает там, где душат UDP |
udp |
dtls |
DTLS поверх TURN; false требует сервера с -listen-direct |
true |
dns |
резолвер для доменов VK: yandex, cloudflare, google, doh-*, custom:IP, doh:URL |
yandex |
datapath |
как отдавать трафик: socks, tun или external |
tun (на macOS — socks) |
kill_switch |
в tun и external блокировать трафик системы, пока туннель не поднят (раздел «Kill-switch») |
true |
[profile.<имя>.socks] listen |
адрес локального SOCKS5 |
127.0.0.1:1080 |
Секреты просматриваются только замаскированными (qwdtt-cli profile show), удаляются
вместе с профилем (qwdtt-cli profile rm) и перезаписываются по qwdtt-cli profile set <имя> -password или -hashes. Аргументом командной строки их передать нельзя намеренно.
Режимы доставки трафика
Режим задаёт поле datapath профиля или флаг -datapath. Прежнее имя режима tun —
wintun — тоже принимается: старые профили и команды работают как раньше.
| Режим |
Что идёт через туннель |
Права |
Что нужно |
Системы |
socks |
программы, настроенные на прокси SOCKS5 |
не нужны |
ничего |
Windows, Linux, macOS |
tun |
весь трафик системы |
администратор, на Linux — root (sudo) |
Windows — wintun.dll рядом с qwdtt-cli.exe, Linux — ядро 5.12+ |
Windows, Linux |
external |
весь трафик системы |
администратор |
установленный WireGuard для Windows |
Windows |
socks
Режим без прав администратора (на macOS — единственный и умолчание): WireGuard целиком
внутри процесса и локальный SOCKS5 над ним.
Прав администратора не нужно, устанавливать ничего не нужно. Ограничения: только TCP,
только IPv4, только приложения, которые умеют ходить через прокси; DNS-запросы
приложения уйдут мимо туннеля, если оно не проксирует их само (в curl для этого
socks5h, в браузерах — настройка «DNS через прокси»).
tun — весь трафик системы
Режим по умолчанию на Windows и Linux. qwdtt-cli создаёт свой сетевой адаптер qwdtt-cli — на Windows
на драйвере Wintun от авторов WireGuard, на Linux через /dev/net/tun, — а сам
WireGuard работает внутри процесса qwdtt-cli: ставить ничего не нужно. Нужны права:
на Windows — консоль от имени администратора, на Linux — sudo; адаптер, маршруты
и фильтры без них не создать. Без прав qwdtt-cli откажет сразу, до подключения, и
предложит -datapath socks. На Windows без wintun.dll рядом с qwdtt-cli.exe он
откажет с сообщением «рядом с qwdtt-cli нет файла wintun.dll» (как её получить при сборке
из исходников — в разделе «Сборка под Windows»). Что на Linux устроено иначе — в
разделе «tun на Linux».
Пока туннель поднят:
- адаптер
qwdtt-cli получает адрес и DNS-серверы, которые выдал сервер; если DNS сервер
не прислал — 1.1.1.1;
- весь трафик забирают маршруты
0.0.0.0/1 и 128.0.0.0/1 через qwdtt-cli (для IPv6 —
::/1 и 8000::/1). Маршрут по умолчанию остаётся на месте: половины выигрывают
у него длиной префикса;
- собственные соединения
qwdtt-cli — с VK, с DNS для доменов VK и с TURN-relay — привязаны
к физическому адаптеру и идут мимо туннеля, иначе туннель зависел бы от самого
себя. Какой адаптер выбран, qwdtt-cli пишет строкой netguard: …; с -v видно каждое
такое соединение строкой [NETGUARD] … → интерфейс N;
- DNS-запросы системы идут только к DNS-серверам туннеля (раздел «Защита DNS»).
Пока туннель не поднят — до первого подъёма и между попытками, — трафик системы
заблокирован, кроме локальной сети (раздел «Kill-switch»).
Маршруты всегда забирают всё адресное пространство, что бы сервер ни выдал
в AllowedIPs. Если сервер разрешил не всё, трафик к остальным адресам уходит
в туннель и там отбрасывается, а не идёт тихо мимо него; об этом предупреждает
строка [TUN] Внимание: сервер разрешил в туннеле не весь IPv4 (AllowedIPs: …).
Адаптер живёт, пока работает qwdtt-cli connect: переподключения его не пересоздают, и
Windows не заводит «Сеть 2», «Сеть 3». Второй qwdtt-cli connect -datapath tun на той
же машине откажет сразу: «адаптер уже занят: на этой машине работает другой qwdtt-cli
с datapath tun».
tun на Linux
sudo qwdtt-cli connect -datapath tun
Профили и секреты под sudo берутся из каталога того, кто вызвал sudo
(раздел «Файл настроек»), так что заводить их заново для root не нужно.
Ядро. Нужно ядро 5.12 или новее: защита DNS держится на таблице nftables с
флагом owner, который появился в 5.12. Ядро само удаляет такую таблицу вместе
с процессом qwdtt-cli, даже если его убили. Модуль tun нужен тоже, но он есть почти
везде.
Обратный фильтр (rp_filter). Собственные соединения qwdtt-cli привязаны к физическому
интерфейсу, а маршруты /1 ведут в qwdtt-cli. Строгий обратный фильтр (rp_filter = 1)
считает ответы VK и TURN на физический интерфейс подделкой и отбрасывает их, так что
туннель не поднялся бы. Поэтому при строгом фильтре qwdtt-cli откажет до подключения
и подскажет команду:
sudo sysctl -w net.ipv4.conf.<интерфейс>.rp_filter=2
Нестрогий режим (2) проверяет только, что обратный маршрут вообще есть. Сам qwdtt-cli
sysctl не меняет: такая правка пережила бы его падение. Чтобы она сохранилась
после перезагрузки, запишите её файлом в /etc/sysctl.d/. Действует большее
из значений all и самого интерфейса.
firewalld. У firewalld по умолчанию строгая проверка обратного пути для IPv6
(IPv6_rpfilter). Она отбрасывала бы ответы IPv6 соединениям qwdtt-cli, поэтому при
работающем firewalld qwdtt-cli ходит к VK и TURN только по IPv4 и пишет об этом
строкой netguard: сокеты ядра — только IPv4: …. Трафика системы в туннеле это
не касается.
DNS туннеля. Как задать системе DNS туннеля, qwdtt-cli решает по тому, кто ведёт
/etc/resolv.conf, и печатает выбор строкой DNS системы: …:
Кто ведёт resolv.conf |
Что делает qwdtt-cli |
После Ctrl+C |
| systemd-resolved |
DNS и домен ~. на линке qwdtt-cli по D-Bus |
уходят вместе с адаптером |
Debian resolvconf |
запись tun.qwdtt-cli |
запись удаляется |
| openresolv |
запись tun.qwdtt-cli в монопольном режиме |
запись удаляется |
| никто (обычный файл) |
перезаписывает файл, прежний — в /etc/resolv.conf.qwdtt-cli-backup |
файл возвращается из копии |
Если resolv.conf — ссылка на незнакомый генератор, qwdtt-cli откажет до подключения:
перезаписать такой файл значило бы сломать его владельцу. Debian resolvconf
монопольного режима не умеет, поэтому в resolv.conf вслед за DNS туннеля
остаются и прежние серверы. Утечки через них нет: запросы к ним отклоняет
защита DNS (если qwdtt-cli не запущен с -allow-leak и она не отказала). Если обычный файл написала другая программа (заголовок
# Generated by …), qwdtt-cli предупредит: когда она перепишет файл, например при смене
сети, DNS туннеля пропадёт до следующего переподключения.
Корпоративный VPN. Если рядом поднят другой VPN с маршрутами к конкретным
сетям, его маршруты конкретнее половин /1 и остаются за ним. А вот DNS системы
при поднятом qwdtt-cli — только туннельный: внутренние имена такого VPN не
разрешаются, пока работает qwdtt-cli, и снова разрешаются после его остановки.
Контейнеры. Защита DNS действует и на пересылаемый трафик: контейнеры docker
и виртуальные машины за NAT хоста тоже не дойдут до чужого DNS мимо туннеля.
external
Конфиг от сервера передаётся штатному WireGuard для Windows:
wireguard.exe /installtunnelservice ставит службу туннеля, при остановке она
снимается. Нужны установленный WireGuard и
консоль от имени администратора. Пока туннель поднят, служба видна в
services.msc как «WireGuard Tunnel: qwdtt-cli», а её конфиг с приватным ключом лежит в
%APPDATA%\qwdtt-cli\qwdtt-cli.conf: служба читает его при запуске. При остановке qwdtt-cli
снимает службу и удаляет файл.
Собственные соединения qwdtt-cli идут мимо туннеля, как и в tun. Маршрут по умолчанию
из конфига сервера (AllowedIPs = 0.0.0.0/0, ::/0) qwdtt-cli записывает в qwdtt-cli.conf
двумя половинами (0.0.0.0/1, 128.0.0.0/1): охват тот же, но с /0 штатный
WireGuard включил бы свой kill-switch и отрезал бы соединения qwdtt-cli. Вместо него
работает kill-switch самого qwdtt-cli (раздел «Kill-switch»), а DNS защищает сам qwdtt-cli, как
в tun.
Если сервер выдал маршрут только для IPv4, qwdtt-cli дописывает и половины IPv6 —
раздел «IPv6».
Если нет причин держаться за штатный WireGuard, берите tun: он не ставит
службу и не пишет на диск файл с приватным ключом.
IPv6
Если сервер выдал адрес только IPv4, IPv6 машины не идёт мимо туннеля с вашим
настоящим адресом, а блокируется: маршруты ::/1 и 8000::/1 ведут
в туннель, и там такие пакеты отбрасываются. Так в обоих режимах полного туннеля;
в external qwdtt-cli дописывает эти половины в qwdtt-cli.conf и пишет об этом строкой
[WG-EXT] сервер не выдал маршрута IPv6: ….
На Linux есть особый случай. Ядро не держит IPv6 на интерфейсе с MTU меньше 1280,
поэтому если сервер выдал такой MTU, маршрутов IPv6 на qwdtt-cli нет. Тогда IPv6 системы
закрывает таблица nftables защиты DNS (строка [TUN] IPv6 системы, кроме loopback и сокетов qwdtt-cli, закрыт защитой DNS). Если защита не включилась и qwdtt-cli запущен с
-allow-leak, закрыть его нечем: qwdtt-cli предупредит, и IPv6 пойдёт мимо туннеля.
Если IPv6 у вашего провайдера нет, ничего не меняется. Если есть, у блокировки
есть цена. Браузеры и большинство современных программ пробуют IPv6 и IPv4
параллельно и за доли секунды переходят на IPv4 — разницы не видно. Программа,
которая перебирает адреса по очереди и начинает с IPv6, будет ждать таймаута
соединения, иногда десятки секунд, и только потом попробует IPv4. Если это
мешает, отключите IPv6 у физического адаптера на время работы туннеля.
Защита DNS
Windows рассылает DNS-запросы и резолверам других адаптеров, не только туннеля, —
без защиты имена посещаемых сайтов уходили бы провайдеру. Поэтому в tun и
external, пока туннель поднят, qwdtt-cli ставит фильтры брандмауэра Windows (WFP):
обращения на порт 53, UDP и TCP, разрешены только к DNS-серверам туннеля, к loopback
и самому qwdtt-cli — ему нужен DNS для доменов VK мимо туннеля. В выводе это строка
«защита DNS: пока туннель поднят, DNS системы — только к резолверам туннеля».
- Программа со своим резолвером, которая обращается на порт 53 к другому серверу,
пока туннель поднят, получит отказ. Это и есть защита.
- DNS поверх HTTPS у браузеров идёт на порт 443, фильтр его не трогает, но идёт он
по маршрутам через туннель — мимо туннеля не уходит.
dns = "doh:URL" с именем хоста в адресе: имя самого DoH-сервера qwdtt-cli разрешает
системным резолвером. С kill-switch это не работает: пока туннель не поднят,
системный DNS закрыт, и qwdtt-cli не найдёт свой DoH-сервер. Пишите в адресе IP
(doh:https://1.1.1.1/dns-query) или берите пресеты doh-*: они начинаются с
адресов, и их это не касается.
Фильтры живут в динамической сессии WFP: система снимает их вместе с процессом,
даже если qwdtt-cli убит. Если поставить их не удалось (например, остановлена служба
базовой фильтрации, BFE), qwdtt-cli откажет до подключения.
На Linux то же делает таблица nftables inet qwdtt-cli: порт 53 открыт только к DNS-серверам
туннеля и loopback, для исходящего и для пересылаемого трафика (контейнеры, ВМ).
Собственные запросы qwdtt-cli к DNS для доменов VK таблица узнаёт по метке сокета
(SO_MARK), а не по пользователю. Под sudo правило «root может всё» пропустило
бы любую программу root. UDP мимо туннеля отклоняется сразу (Operation not permitted), TCP ждёт таймаута. Таблица создана с флагом owner: ядро удаляет
её вместе с процессом, даже убитым.
Флаг -allow-leak разрешает подключиться без защиты — только на этот запуск, в
профиль он не записывается. Прежнее имя флага, -allow-dns-leak, тоже принимается.
Kill-switch
В tun и external, пока туннель не поднят, трафик системы заблокирован — до
первого подъёма и всё время, пока туннель переподключается. Иначе он уходил бы мимо
туннеля с вашим настоящим адресом, а DNS — к резолверам провайдера. Kill-switch
включён по умолчанию.
Пока туннель не поднят, разрешены:
- сам
qwdtt-cli — ему нужно добраться до VK и TURN;
- loopback;
- DHCP (IPv4 и IPv6) и обнаружение соседей IPv6 — без них сеть машины разваливается;
- локальная сеть:
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16,
fe80::/10, fc00::/7, мультикаст и широковещание. Роутер, принтер и NAS остаются
доступны.
Порт 53 закрыт и в локальной сети: резолвер роутера отправил бы запросы провайдеру.
Остальное отклоняется: UDP — сразу (на Linux — Operation not permitted), TCP ждёт
таймаута. На Linux закрыт и пересылаемый трафик — контейнеры docker и виртуальные
машины за NAT хоста. Корпоративный VPN отдельно не пропускается: его соединение с сервером оборвётся
и восстановится, когда туннель поднимется.
Когда туннель поднят, kill-switch ничего не блокирует — работает только защита DNS.
Программы, которые сами привязываются к физическому адаптеру, и маршруты конкретнее
половин /1 (например, к серверу корпоративного VPN) работают как без qwdtt-cli.
В выводе это видно так:
kill-switch: пока туннель не поднят, трафик системы заблокирован
…
туннель переподключается — трафик системы заблокирован (kill-switch)
…
туннель снова поднят — трафик системы идёт через него
Капча. При переподключении VK может попросить капчу. Окно капчи — WebView2 на
Windows, браузер на Chromium на Linux — ходит в сеть через локальный прокси qwdtt-cli: только
к доменам VK и только на порт 443. Kill-switch при этом не снимается. В ручном режиме
(Windows без WebView2, Linux без браузера на Chromium, вход по SSH) страница капчи
открывается в вашем браузере, а пропустить мимо блокировки один браузер нельзя. Поэтому
на время ручной капчи — от ссылки до ответа — kill-switch снимается, и трафик системы идёт
мимо туннеля:
kill-switch снят на время капчи — трафик системы идёт мимо туннеля
…
kill-switch возвращён: пока туннель не поднят, трафик системы заблокирован
Если прокси для окна не поднялся, qwdtt-cli пишет «окно капчи пойдёт в сеть само» и тоже
снимает kill-switch на время капчи.
Если qwdtt-cli упал или убит, правила kill-switch уходят вместе с процессом, как фильтры
защиты DNS: машина не остаётся без сети, но и не защищена — трафик идёт напрямую.
Постоянной блокировки, которая пережила бы qwdtt-cli, нет намеренно.
Как выключить. На один запуск — флаг -no-kill-switch, насовсем — kill_switch = false в профиле или qwdtt-cli profile set <имя> -kill-switch=false. Без kill-switch, пока
туннель переподключается, трафик и DNS системы идут мимо туннеля: qwdtt-cli снимает
маршруты и защиту DNS, иначе страница капчи не загрузилась бы. Это видно строками
маршруты сняты на время переподключения — трафик и DNS системы идут мимо туннеля
…
маршруты возвращены — трафик системы снова идёт через туннель
Обычно это секунды — одна попытка и задержка перед следующей, от 1 до 64 с. Дольше —
когда пропала сеть или VK несколько минут не выдаёт новых каналов TURN (с -v видно
Allocation Quota Reached).
Если kill-switch не включился (например, на Windows остановлена служба базовой
фильтрации, BFE), qwdtt-cli откажет до подключения. Подключиться без него — -no-kill-switch
или -allow-leak (на один запуск). Если правила откажут
посреди сеанса, qwdtt-cli пишет «Внимание: kill-switch не встал: …», и до подъёма туннеля
трафик идёт мимо него.
Если qwdtt-cli упал или был убит
Первый Ctrl+C останавливает туннель и убирает за собой всё. Второй Ctrl+C,
taskkill /F, kill -9 или падение убрать не дают, и тогда:
tun — адаптер qwdtt-cli, маршруты через него, фильтры DNS и kill-switch исчезают
вместе с процессом: адаптер снимает драйвер Wintun, фильтры — система. Убирать вручную
нечего, новый qwdtt-cli connect можно запускать сразу. Остаётся только запись реестра
с DNS бывшего адаптера (HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{GUID}):
адаптера нет, поэтому ни на что она не влияет, а следующий запуск её перезапишет.
tun на Linux — адаптер qwdtt-cli с маршрутами и таблица inet qwdtt-cli (защита DNS и
kill-switch) исчезают вместе с процессом. Остаётся DNS туннеля в системе: запись
tun.qwdtt-cli у resolvconf или перезаписанный /etc/resolv.conf с копией .qwdtt-cli-backup
(у systemd-resolved настройки уходят вместе с адаптером). DNS при этом работает — запросы идут к тем же
серверам, но уже напрямую, мимо туннеля. Следующий qwdtt-cli connect -datapath tun
убирает остаток сам и пишет об этом: «DNS системы: запись tun.qwdtt-cli прошлого запуска
qwdtt-cli снята» или «прежний resolv.conf возвращён из /etc/resolv.conf.qwdtt-cli-backup».
Вручную — sudo resolvconf -d tun.qwdtt-cli или sudo mv /etc/resolv.conf.qwdtt-cli-backup /etc/resolv.conf.
external — служба и файл конфига могли остаться, и тогда весь трафик
по-прежнему идёт в туннель, которого уже нет. Снимите службу командой
wireguard.exe /uninstalltunnelservice qwdtt-cli и удалите
%APPDATA%\qwdtt-cli\qwdtt-cli.conf. Фильтры DNS и kill-switch система сняла сама.
Что осталось в системе, показывает снимок go run ./scripts/checktunnel (раздел
«Отладка»).
Восстановление
При обрыве клиент переподключается сам с нарастающей задержкой: 1, 2, 4 … 64 с.
В режимах tun и external qwdtt-cli ещё и следит за сетью. Смена сети — другой Wi-Fi,
кабель вместо Wi-Fi — перезапускает подключение сразу, без задержки, строкой
«сеть сменилась: …». Если сеть пропала, qwdtt-cli пишет «сеть пропала — туннель
переподключится, когда она вернётся» и перезапускает подключение, как только она
вернётся.
Хеш, по которому VK отвечает «звонок закрыт», исключается из перебора; когда годных
не остаётся, клиент останавливается с ошибкой — заведите новые через
qwdtt-cli profile set <имя> -hashes.
Отладка
-v — весь лог ядра и строка [NETGUARD] на каждое соединение qwdtt-cli мимо
туннеля. Строки [TUN] и [WG-EXT] печатаются и без него.
- Пропадают пакеты — сначала посмотрите, не в
qwdtt-cli ли дело. Когда очереди внутри
клиента переполнены и он выбрасывает пакеты, строка счётчиков с -v кончается «сброшено
пакетов туда N, обратно M», а при остановке печатается итог. Нет этих слов — пакеты
теряются не в qwdtt-cli, а по пути через VK или на сервере.
QWDTT_WG_DEBUG=1 — подробный лог самого WireGuard: рукопожатия, ошибки приёма.
В PowerShell: $env:QWDTT_WG_DEBUG = 1; qwdtt-cli connect -v. На Linux под sudo
переменную надо передать явно: sudo env QWDTT_WG_DEBUG=1 qwdtt-cli connect -datapath tun -v.
go run ./scripts/checktunnel — снимок системы, запускается из исходников. Windows
и Linux. Показывает процессы qwdtt-cli, адаптеры, маршруты /0 и /1, внешний адрес
без прокси, кто отвечает на DNS; на Windows ещё фильтры WFP (без прав
администратора их нет), записи реестра, службу и qwdtt-cli.conf режима external, на
Linux — правила маршрутизации, таблицы nftables (только под sudo), resolv.conf
и записи resolvconf, rp_filter. Ничего не меняет; снимки до запуска, во время и
после остановки удобно сравнивать.
Сравнение с PWDTT
PWDTT — другой настольный клиент того же семейства:
графическое приложение на Wails для Windows, Linux и macOS. Ниже — различия по PWDTT v1.6.0.
|
qwdtt-cli |
PWDTT |
| Интерфейс |
консольный: меню вопросами и команды для скриптов |
графический; на Windows — трей и автозапуск |
| Платформы |
Windows, Linux |
Windows, Linux, macOS |
| Ядро |
ядро qWDTT, переносится из апстрима скриптом; свои исправления — правилами переноса |
форк исходного WDTT, переработан вручную |
| Режимы |
весь трафик системы (tun), SOCKS5 без прав администратора (socks), конфиг для своего WireGuard (external, Windows) |
весь трафик через WireGuard |
| Kill-switch |
есть: туннель упал — трафик системы закрыт до подъёма |
нет: при обрыве трафик идёт напрямую |
| Защита DNS |
DNS системы — только через туннель |
нет: на Linux и macOS серверы из /etc/resolv.conf получают маршрут мимо туннеля, на Windows DNS туннеля не задаётся |
| Что нужно на Linux |
ничего: один статический файл, sudo — только для tun |
wireguard-tools, модуль ядра WireGuard, libwebkit2gtk-4.1; правило sudoers без пароля для ip и wg |
| Пароль и хеши |
зашифрованы: DPAPI на Windows, связка ключей на Linux |
открытым текстом в JSON-файле сервера |
| Хеши звонков |
без ограничения, лишние — запас; закрытые звонки исключаются, кончились — клиент просит новые ссылки; проверка qwdtt-cli hashes |
до четырёх на сервер, без проверки |
| Капча |
решатель ядра; окно капчи: WebView2 на Windows, браузер на Chromium на Linux; ручной режим в браузере |
режимы ядра: автоматический и окно в интерфейсе |
Ссылки qwdtt://, wdtt:// |
импорт в меню и командой |
импорт, вставка Ctrl+V в окно |
| Обновления |
не проверяет, в сеть сам не ходит |
проверка через API GitHub при запуске |
| Закрытый звонок (ошибка 954) |
хеш исключается; кончились живые — остановка с подсказкой |
отдельного статуса нет, хеш не исключается |
Коротко: PWDTT удобнее, если нужны графический интерфейс, трей или macOS. qwdtt-cli — если
важно, чтобы при обрыве туннеля и в DNS ничего не уходило мимо, чтобы не ставить лишних
пакетов и не давать программе прав сверх нужного, и чтобы клиент работал на сервере или по
SSH.
Предупреждения
Релизные бинари не подписаны. Windows SmartScreen и антивирусы могут возражать
против программы, которая держит сетевой туннель, — это ожидаемо до появления
подписи. Исходники открыты, сборка воспроизводима скриптом из репозитория.
Лицензия
GNU General Public License v3.0 — см. LICENSE.
Проект включает исходный код qWDTT
и распространяется на тех же условиях.