Help us shape the future of Go! Take the 2026 Go Developer Survey

qwdtt-cli

module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: GPL-3.0

README

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, запущенный без аргументов, ведёт вопросами.

  1. Скачайте архив для своей системы (раздел «Установка») и распакуйте его.
  2. Запустите qwdtt-cli:
    • Windows — дважды щёлкните по qwdtt-cli.exe в распакованной папке. Откроется окно консоли с меню. Если Windows предупредит о программе из интернета — «Подробнее» → «Выполнить в любом случае».
    • Linux — откройте терминал в распакованном каталоге и наберите ./qwdtt-cli.
  3. Профиля ещё нет — меню предложит его создать (Enter). Дальше:
    • если у вас есть ссылка qwdtt://config?… или wdtt://… (Android-приложение qWDTT → экспорт профиля, или бот сервера), вставьте её: адрес, пароль и ссылки на звонки qwdtt-cli возьмёт из неё. Ссылку при вставке не видно — так и задумано: в ней ваш пароль;
    • если ссылки нет, нажмите Enter и ответьте на вопросы: имя профиля (Enter — home), адрес сервера, пароль подключения (дважды) и ссылки на звонки VK. Адрес и пароль даёт тот, кто настроил сервер.
  4. Выберите, что пускать через туннель: весь трафик компьютера (Enter) или только программы, где указан прокси SOCKS5 127.0.0.1:1080. Первому режиму нужны права администратора — qwdtt-cli попросит их сам: на Windows появится окно «Разрешить этому приложению вносить изменения?», и подключение откроется в новом окне; на Linux sudo спросит пароль вашей учётной записи. Если ваша учётная запись Windows без прав администратора, qwdtt-cli скажет об этом и предложит второй режим.
  5. В меню нажмите 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 только собирает: архивы остаются артефактом прогона.

Быстрый старт в командной строке

  1. Заведите профиль. Пароль и хеши спрашиваются скрытым вводом; в файл настроек попадают только ссылки на хранилище секретов (на 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 сразу записывает режим. Чего в ссылке нет (пароля, хешей), спрашивается.

  2. Проверьте хеши и задержку до сервера. Обе команды не поднимают туннель:

    qwdtt-cli hashes
    qwdtt-cli ping
    

    hashes печатает по строке на хеш со статусом ok, captcha, dead, limited, network или error и возвращает код 1, если годных нет.

  3. Поднимите туннель. По умолчанию через него идёт весь трафик системы (режим tun), поэтому нужны права: на Windows — консоль от имени администратора, на Linux — sudo:

    qwdtt-cli connect
    sudo qwdtt-cli connect
    

    Через секунду-две в выводе появится == туннель работает. Проверить можно так: curl https://ifconfig.me покажет адрес сервера, а не ваш.

    Имя профиля можно опускать, если профиль один или назван в default_profile. Флаг перекрывает то же поле профиля на один запуск: qwdtt-cli connect home -workers 27. -v печатает весь лог ядра. На терминале внизу держится статусная строка с состоянием, аптаймом и счётчиками; при перенаправлении в файл её нет.

  4. Без прав администратора работает режим только для программ с прокси:

    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 инструкцию:

  1. Страница капчи открывается в браузере сама. На Linux — через xdg-open, а под sudo — в браузере того пользователя, который вызвал sudo, а не root. Если браузер открыть не вышло (например, по SSH), откройте напечатанную ссылку вручную где угодно.
  2. В браузере нажмите F12, откройте вкладку Console и вставьте строку, которую напечатал qwdtt-cli. Если браузер не даёт вставить, наберите в консоли allow pasting и нажмите Enter — это защита браузера от вставки чужого кода.
  3. Решите капчу. В консоли браузера появится строка qwdtt-cli-captcha token <длинная строка>.
  4. Скопируйте её и вставьте в терминал 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 и распространяется на тех же условиях.

Directories

Path Synopsis
cmd
qwdtt-cli command
Command qwdtt-cli — консольный клиент qWDTT для настольных систем.
Command qwdtt-cli — консольный клиент qWDTT для настольных систем.
internal
app
Package app — имя программы.
Package app — имя программы.
captcha
browser_linux.go — капча в браузере под управлением по CDP (Linux).
browser_linux.go — капча в браузере под управлением по CDP (Linux).
cli
connect.go — команда qwdtt-cli connect.
connect.go — команда qwdtt-cli connect.
config
Package config читает profiles.toml — файл с настройками подключения.
Package config читает profiles.toml — файл с настройками подключения.
datapath
Package datapath отвечает за то, каким способом трафик приложений попадает в туннель.
Package datapath отвечает за то, каким способом трафик приложений попадает в туннель.
linuxsys
Package linuxsys — системная часть Linux для Э4: выбор физического интерфейса и подписка на смену сети (plan-e4.md, блок N), дальше — адаптер, маршруты и DNS.
Package linuxsys — системная часть Linux для Э4: выбор физического интерфейса и подписка на смену сети (plan-e4.md, блок N), дальше — адаптер, маршруты и DNS.
netguard
Package netguard уводит собственные сокеты ядра мимо туннеля (architecture.md §05, дорожка 2).
Package netguard уводит собственные сокеты ядра мимо туннеля (architecture.md §05, дорожка 2).
secretservice
Package secretservice хранит секреты в связке ключей Linux — по протоколу Secret Service на шине D-Bus сеанса.
Package secretservice хранит секреты в связке ключей Linux — по протоколу Secret Service на шине D-Bus сеанса.
sudo
Package sudo узнаёт, от чьего имени qwdtt-cli запущен через sudo.
Package sudo узнаёт, от чьего имени qwdtt-cli запущен через sudo.
supervisor
lifecycle.go — цикл подключения (задача F3): то единственное место в супервизоре, где есть время, горутины и внешний мир.
lifecycle.go — цикл подключения (задача F3): то единственное место в супервизоре, где есть время, горутины и внешний мир.
winsys
Package winsys — системная часть Windows для Э2: выбор физического интерфейса, маршруты, DNS и подписка на смену сети (architecture.md §09).
Package winsys — системная часть Windows для Э2: выбор физического интерфейса, маршруты, DNS и подписка на смену сети (architecture.md §09).
scripts
checktunnel command
Общее для снимков Windows и Linux: разделы, маршруты /0 и /1, внешний адрес и резолвер.
Общее для снимков Windows и Linux: разделы, маршруты /0 и /1, внешний адрес и резолвер.
ctrlbreak command
Ctrl+Break по PID — только на Windows: на Linux то же делает kill -INT.
Ctrl+Break по PID — только на Windows: на Linux то же делает kill -INT.
distcheck command
Команда distcheck проверяет состав архивов релиза в dist/ — шаг «Состав архивов» в .github/workflows/release.yml.
Команда distcheck проверяет состав архивов релиза в dist/ — шаг «Состав архивов» в .github/workflows/release.yml.
internal/script
Package script — общее для служебных команд в scripts/: корень репозитория, вывод с цветом и порядок имён файлов.
Package script — общее для служебных команд в scripts/: корень репозитория, вывод с цветом и порядок имён файлов.
internal/wintun
Package wintun скачивает wintun.dll фиксированной версии, проверяет её и кладёт рядом с qwdtt-cli.exe.
Package wintun скачивает wintun.dll фиксированной версии, проверяет её и кладёт рядом с qwdtt-cli.exe.
notices command
Команда notices собирает THIRD_PARTY_NOTICES.txt — лицензии всего, что слинковано в qwdtt-cli.
Команда notices собирает THIRD_PARTY_NOTICES.txt — лицензии всего, что слинковано в qwdtt-cli.
outage command
Команда outage устраивает обрыв связи на время — для живых проверок переподключения qwdtt-cli (plan-e4.md, R1 и R2; на Windows — plan-e2.md, S1).
Команда outage устраивает обрыв связи на время — для живых проверок переподключения qwdtt-cli (plan-e4.md, R1 и R2; на Windows — plan-e2.md, S1).
release command
Команда release собирает релиз qwdtt-cli: бинари для каждой платформы, zip для Windows и tar.gz для Linux и macOS.
Команда release собирает релиз qwdtt-cli: бинари для каждой платформы, zip для Windows и tar.gz для Linux и macOS.
releasenotes command
Команда releasenotes пишет начало описания релиза — блок «Скачать» со ссылками на архивы в порядке Windows, Linux, macOS, затем исходники и SHA256SUMS.txt.
Команда releasenotes пишет начало описания релиза — блок «Скачать» со ссылками на архивы в порядке Windows, Linux, macOS, затем исходники и SHA256SUMS.txt.
sha256sums command
Команда sha256sums пишет dir/SHA256SUMS.txt — хеши всех файлов каталога релиза, шаг «SHA256SUMS.txt» в .github/workflows/release.yml.
Команда sha256sums пишет dir/SHA256SUMS.txt — хеши всех файлов каталога релиза, шаг «SHA256SUMS.txt» в .github/workflows/release.yml.
vendorcore command
Команда vendorcore переносит ядро qWDTT из апстрима в internal/core.
Команда vendorcore переносит ядро qWDTT из апстрима в internal/core.
wintun command
Команда wintun скачивает wintun.dll фиксированной версии, проверяет её и кладёт рядом с qwdtt-cli.exe: хеш архива, на Windows — подпись Authenticode (WireGuard LLC).
Команда wintun скачивает wintun.dll фиксированной версии, проверяет её и кладёт рядом с qwdtt-cli.exe: хеш архива, на Windows — подпись Authenticode (WireGuard LLC).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL