Skip to content

Latest commit

 

History

History
1263 lines (1019 loc) · 87.2 KB

File metadata and controls

1263 lines (1019 loc) · 87.2 KB

Qeli — установка и начало работы (пошагово)

Документация описывает 0.7.15 — последний выпущенный релиз. Что именно установлено у вас, покажет qeli --version.

Полное руководство «с нуля»: от поднятия сервера до заведения пользователей с маршрутами и подключения первого клиента — и через CLI, и через веб-панель.

Рассчитано на чистый Linux-сервер (Debian/Ubuntu) с root-доступом. Все команды сервера — от root (или через sudo).

Справочники, на которые опирается этот гайд: CONFIG.md — все ключи конфига · PANEL.md — веб-панель · примеры конфигов: server.conf · users.conf · client.conf.

Содержание

  1. Что понадобится
  2. Установка сервера
  3. Первичная настройка сервера (CLI)
  4. Запуск и проверка
  5. Full-tunnel: NAT (настраивается автоматически)
  6. Заведение пользователей (CLI)
  7. Маршруты: split/full-tunnel, pushed-маршруты, ACL, статический IP
  8. Подключение клиента
  9. То же самое через веб-панель
  10. Справочник CLI и диагностика
  11. Wire-режимы — какой выбрать
  12. Частые проблемы
  13. Полное удаление qeli

1. Что понадобится

  • Сервер Linux x86-64 (Debian 11+ / Ubuntu 20.04+), root, публичный IP. .deb — портируемая сборка (make deb-portable, gate check-abi); зависимости пакета: libc6 >= 2.28, libgcc-s1, iptables, iproute2, libcap2-bin. Ставится «из коробки» на Debian 11/12 и Ubuntu 20.04/22.04/24.04. Debian 10 (Buster) не подходит: там пакет называется libgcc1, а libgcc-s1 появился только в Debian 11, поэтому apt откажет по зависимости. Для Buster и систем с glibc < 2.28 остаются вариант B (сборка из исходников на самой машине) или вариант C (Docker — рантайм внутри образа).
  • Открытый порт под VPN (по умолчанию TCP 443) и, если включаете панель, её порт (по умолчанию 8080). В облачном файрволе/Security Group откройте их.
  • Ядро с поддержкой TUN (/dev/net/tun — есть почти везде; на некоторых VPS включается в панели провайдера).
  • Пакеты iproute2, iptables, libcap2-bin (тянутся зависимостью .deb).
  • Клиент: телефон (Android), десктоп (Windows/macOS) или Linux-CLI.

Один бинарь qeli совмещает обе роли: qeli server и qeli client.


2. Установка сервера

Самый быстрый путь (всё за одну команду). В корне репозитория есть готовый установщик install-qeli-server.sh: ставит qeli и его зависимости, спрашивает профильreality-tls (по умолчанию; настоящий TLS 1.3 на TCP:443, держит активный пробинг), fake-tls (дешевле по CPU, хватает против пассивного DPI) или udp-quic (UDP-путь с датаграммами под QUIC — берите там, где TCP:443 режут, сбрасывают или он иначе деградирует) — и порт (по умолчанию :443), поднимает его с full-tunnel NAT и заводит 5 пользователей с готовыми qeli://-строками в /etc/qeli/client-links/. Запуск от root: ./install-qeli-server.sh <публичный-IP-или-домен> (или sudo …, если sudo установлен — он не обязателен и не ставится). Скачивайте скрипт отдельно и запускайте вторым шагом — curl … | bash не используем: скрипт работает от root и его стоит прочитать до запуска, а curl -fsSL на HTTP-ошибке молчит, и bash с пустым stdin выходит с кодом 0 (сорвавшаяся загрузка выглядит как успешная установка). Для неинтерактивной установки (автоматизация) задайте выбор заранее: QELI_PROFILE=udp-quic QELI_PORT=443 ./install-qeli-server.sh <IP>. Дальше остаётся только вставить строку подключения в приложение. Ручная установка по шагам — ниже.

Что он делает, по порядку: ① ставит зависимости (curl, jq, iptables, iproute2, openssl) → ② заносит qeli на машину и настраивает ровно то же, что .deb (системный пользователь qeli, /etc/qeli + каталоги состояния, *.conf.example, systemd-юнит, polkit-правило) → ③ пишет /etc/qeli/server.conf с выбранным профилем на выбранном порту + full-tunnel NAT (для reality-tls — свежий short_id) → ④ генерирует identity-ключ профиля → ⑤ заводит 5 пользователей и сохраняет их qeli://-ссылки → ⑥ применяет тюнинг ОС под mobile/LTE (BBR + PMTU, плюс внешний MSS-clamp на TCP-профилях) → ⑦ включает веб-панель по HTTPS со сгенерированным паролем → ⑧ systemctl enable --now qeli.

От какого пользователя работает службаQELI_RUN_AS=qeli (по умолчанию, без привилегий) или QELI_RUN_AS=root. Установщик применяет выбор через qeli set-service-user (§10.4) прямо перед первым стартом, поэтому служба сразу поднимается от нужного пользователя:

sudo QELI_RUN_AS=root ./install-qeli-server.sh <IP>    # без разделения привилегий — см. §10.4

Без явной причины оставляйте значение по умолчанию; предупреждение из §10.4 в силе.

Две ветки установки (шаг ②) — обе дают идентичную систему:

  • По умолчанию — скачать .deb из GitHub Releases, проверить его SHA256 и apt install. Обычный путь, ничего дополнительно передавать не нужно.
  • Из готового бинаря — QELI_BIN=<путь>: вместо скачивания ставит этот бинарь и сам воспроизводит раскладку .deb (пользователь, каталоги, *.conf.example, qeli.service, polkit-правило 49-qeli.rules). Для сборки из исходников или air-gapped. Добавьте QELI_SRC=<чекаут репо>, чтобы копировать юнит и примеры прямо из исходников (полностью офлайн); без него они тянутся с GitHub. Пример:
    sudo QELI_BIN=qeli/target/release/qeli QELI_SRC=. ./install-qeli-server.sh <IP>

Что ещё он меняет на хосте (это не побочные мелочи — знайте о них заранее):

  • Тюнинг сети всей системы: пишет /etc/sysctl.d/99-qeli-perf.conf и переключает congestion control на BBR — это влияет на весь TCP хоста, не только на qeli. Там же поднимаются буферы сокетов по умолчанию (net.core.rmem_default/wmem_default до 4 МБ) — без этого UDP-профили теряют пакеты, потому что у UDP нет автотюнинга и он остаётся на 208 КБ. Это тоже общесистемные значения.
  • Загружает модуль tcp_bbr при каждой загрузке через /etc/modules-load.d/qeli-bbr.conf.
  • Ставит MSS-правило (только TCP-профили — udp-quic его пропускает) в mangle/OUTPUT и пытается сохранить firewall. Если netfilter-persistent нет — делает снимок в /etc/iptables/rules.v4, причём всего текущего ruleset хоста, а не только своего правила. Сохранение — best-effort, а не гарантия. Все шаги идут с || true, то есть молча продолжают при неудаче. И сам по себе файл /etc/iptables/rules.v4 ничего не восстанавливает: его читает при загрузке пакет iptables-persistent (netfilter-persistent), и без него после ребута MSS-правила не будет. Проверьте после первой перезагрузки: iptables -t mangle -S OUTPUT | grep TCPMSS — если пусто, поставьте iptables-persistent или повесьте правило своим unit'ом. Симптом отсутствия клэмпа — загрузки, встающие «намертво» у мобильных клиентов.
  • Включает веб-панель по HTTPS на 127.0.0.1:8080 (только loopback), сгенерировав пароль и показав его один раз в конце вывода. Это единственный момент, когда пароль виден — сохраните его сразу. Доступ — через SSH-форвард: ssh -L 8080:127.0.0.1:8080 root@<сервер>, затем https://127.0.0.1:8080. Публикация наружу — осознанное действие и требует ОБОИХ QELI_PANEL_PUBLIC=1 и QELI_PANEL_ALLOWED_IPS=<ip[,ip…]>; публичный bind без списка источников инсталлятор ОТКЛОНЯЕТ. Если панель не нужна вовсе — выключите её после установки ([web] enabled = false).
  • Кладёт /etc/qeli/client-links/CONNECTION-STRINGS.txt — там пароли пяти пользователей открытым текстом (каталог 0700, файлы 0600).
  • Если публичный адрес не задан аргументом — определяет его, обратившись к внешним сервисам (api.ipify.org, ifconfig.me, icanhazip.com).

Всё это снимается — см. §13 «Полное удаление».

Вариант A — .deb-пакет (рекомендуется)

A.1. Скачать пакет в /tmp

Качайте .deb именно в /tmp (или другой каталог, читаемый всеми), а не в /root и не в домашний каталог:

cd /tmp
curl -fLO https://github.com/litvinovtd/qeli/releases/download/v0.7.15/qeli_0.7.15_amd64.deb
# или scp с рабочей машины:  scp qeli_0.7.15_amd64.deb root@server:/tmp/

Почему /tmp. apt скачивает и распаковывает от имени служебного пользователя _apt, а /root и домашние каталоги ему недоступны. Из /root установка проходит, но с предупреждением:

N: Download is performed unsandboxed as root as file '/root/qeli_0.7.15_amd64.deb'
   couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

Это именно предупреждение (apt откатывается на работу от root), но из /tmp его просто не будет.

A.2. Установить

sudo apt install /tmp/qeli_0.7.15_amd64.deb     # ставит и подтягивает зависимости

Указывайте полный путь (или ./имя.deb) — без слэша apt будет искать пакет с таким именем в репозиториях. Альтернатива, если apt по какой-то причине недоступен:

sudo dpkg -i /tmp/qeli_0.7.15_amd64.deb
sudo apt-get -f install -y          # доустановить зависимости (iproute2, iptables, libcap2-bin)

Что делает пакет:

  • кладёт бинарь в /usr/bin/qeli (0755 root:root, без file-capabilities — с 0.7.12 setcap намеренно снимается: права даёт systemd-юнит через AmbientCapabilities CAP_NET_ADMIN/CAP_NET_RAW/CAP_NET_BIND_SERVICE, а с NoNewPrivileges=true ядро file-caps всё равно игнорирует);
  • создаёт системного пользователя qeli и каталоги /etc/qeli, /var/log/qeli, /var/lib/qeli, затем делает им chown -R qeli:qeli;
  • создаёт пустой /etc/qeli/users.conf (пример с известным хешем НЕ подкладывается);
  • ставит примеры /etc/qeli/{server,server-multiprofile,users,client,client-reality}.conf.example (рабочие конфиги вы создаёте сами — шаг 3);
  • ставит systemd-юнит qeli.service (ExecStart=/usr/bin/qeli server --config /etc/qeli/server.conf) и polkit-правило /etc/polkit-1/rules.d/49-qeli.rules;
  • спрашивает, от какого ОС-пользователя работать службе (вопрос debconf qeli/run-as: qeli — по умолчанию, без привилегий — или root) и применяет ответ через qeli set-service-user. Неинтерактивно (автоматизация / preseed):
    echo "qeli qeli/run-as select root" | sudo debconf-set-selections
    sudo apt install /tmp/qeli_0.7.15_amd64.deb
    Изменить можно в любой момент позже — sudo qeli set-service-user root|qeli (§10.4), там же расписаны размены варианта root.

A.3. Права на /etc/qeli — обязательный шаг после настройки

Это самая частая причина «установил, а ничего не работает». Служба работает под User=qeli (см. qeli.service) и пишет внутрь /etc/qeli — там генерируются identity-ключи профилей (/etc/qeli/identity/<profile>.key), туда сохраняет пользователей add-client и веб-панель, там же usage.json. Под это в юните специально разрешён ReadWritePaths=/etc/qeli.

postinst выставляет владельца в момент установки, но всё, что вы создадите после — под root, — останется root-овым:

sudo cp /etc/qeli/server-multiprofile.conf.example /etc/qeli/server.conf   # → root:root
sudo qeli show-identity --config /etc/qeli/server.conf                      # создаёт identity/ от root

Что изменилось в 0.7.13. Раньше под ловушку попадала и перезапись существующего файла: атомарная запись делает rename, а он подставляет новый inode, принадлежащий тому, кто пишет, — поэтому один sudo qeli add-client переводил уже правильный users.conf из qeli:qeli в root:root, и следом ломалась панель (файл блокировки создаётся с владельцем охраняемого файла). Теперь запись сохраняет владельца заменяемого файла, так что этот сценарий закрыт. Создание новых файлов и каталогов от root ловушкой быть не перестало — всё, что ниже, по-прежнему нужно.

После этого служба под qeli не сможет писать в эти файлы. Поэтому после создания конфига и любых CLI-команд под root приведите права в порядок:

sudo chown -R qeli:qeli /etc/qeli
sudo chmod 755 /etc/qeli
sudo chmod 640 /etc/qeli/server.conf /etc/qeli/users.conf   # в них хеши паролей и ключи
[ -d /etc/qeli/identity ] && sudo chmod 700 /etc/qeli/identity && sudo chmod 600 /etc/qeli/identity/*.key
sudo systemctl restart qeli

Как не наступать на это вовсе — запускайте CLI сразу от имени qeli:

sudo -u qeli qeli add-client alice --config /etc/qeli/server.conf

Тогда всё создаётся с правильным владельцем и chown не нужен.

Каталоги /var/lib/qeli, /var/log/qeli и /run/qeli (control-сокет) systemd создаёт и раздаёт сам через StateDirectory/LogsDirectory/RuntimeDirectory — их трогать не нужно.

Признаки, что права всё-таки не те (проверять journalctl -u qeli -n 50 --no-pager):

  • Permission denied / EROFS при генерации identity — профиль не поднимается на свежей установке;
  • add-client отработал, но пользователь «пропал» после рестарта — запись в users-файл не сохранилась;
  • панель сохраняет настройки без ошибки, но после рестарта они прежние;
  • служба уходит в рестарт-петлю (systemctl status qeliNRestarts растёт).

A.4. Проверить установку

qeli --version
systemctl status qeli --no-pager
ls -la /etc/qeli                      # владелец всего — qeli:qeli
journalctl -u qeli -n 30 --no-pager   # ошибок прав быть не должно

Вариант B — сборка из исходников

Нужен Rust (stable). В корне репозитория:

cd qeli
cargo build --release --features jemalloc   # бинарь → qeli/target/release/qeli
# --features jemalloc обязателен для СЕРВЕРНОГО бинаря: без него RSS воркера
# упирается в ~180 МБ под churn'ом хендшейков (glibc держит освобождённые арены)
# вместо ~40–60 МБ с jemalloc. Клиенту это не нужно.

# (опц.) собрать свой .deb из свежего бинаря (Makefile уже включает jemalloc):
make -C debian deb             # → qeli/debian/qeli_<версия>_amd64.deb

Без пакета можно запускать бинарь напрямую (см. шаг 4), но тогда systemd-юнит, пользователя и каталоги создаёте вручную — или поручите это установщику: он из свежесобранного бинаря воспроизведёт точную раскладку .deb (пользователь qeli, /etc/qeli + каталоги состояния, *.conf.example, qeli.service, polkit-правило) без всякого скачивания. Из корня репо:

sudo QELI_BIN=qeli/target/release/qeli QELI_SRC=. ./install-qeli-server.sh <публичный-IP>

QELI_BIN выбирает ветку установки из бинаря; QELI_SRC=. копирует юнит и примеры прямо из этого чекаута (полностью офлайн). См. §2 «Две ветки установки». Заодно ставит и polkit-правило, поэтому кнопка панели Apply & Restart работает без отдельного шага ниже.

⚠️ Установка не из .deb + веб-панель: кнопка панели Apply & Restart выполняет systemctl restart сервиса. Non-root сервис User=qeli может это делать только с polkit-правилом. .deb (Вариант A) ставит его сам; при ручной/бинарной установке добавьте его один раз, под root:

sudo qeli install-polkit          # → /etc/polkit-1/rules.d/49-qeli.rules (см. §10.4)

Без этого Apply & Restart сообщит, что правила нет (молча больше не падает). В контейнере systemctl недоступен вовсе — панель применяет изменения профилей через перезапуск воркера в процессе, а изменения сокета панели (web.bind/port/tls) требуют пересоздания контейнера (docker restart).

Вариант C — Docker

Мульти-арч образ (linux/amd64, linux/arm64, linux/arm/v7) несёт обе роли (qeli server и qeli client) со всеми рантайм-зависимостями внутри (iproute2, iptables, CA-сертификаты) — работает на любом Linux-хосте и в контейнерных рантаймах роутеров (MikroTik RouterOS v7, OpenWrt). Контейнеру нужны /dev/net/tun и три capability — NET_ADMIN (TUN, маршруты, iptables), NET_RAW и NET_BIND_SERVICE (привязка к портам < 1024); готовый docker-compose.yml (сервер + опц. gateway-клиент) в комплекте. Сборка/запуск, пример compose и нюансы:

🐳 release/docker/README.md

С Docker остальные шаги установки/systemd из этого гайда можно пропустить; управление профилями и пользователями ниже (CLI или веб-панель) внутри контейнера работает так же.

Права в контейнере устроены иначе — и §A.3 к нему не относится. В образе нет директивы USER и сброса привилегий в entrypoint, поэтому процесс внутри контейнера работает от root. Отсюда три следствия:

  • Разделения привилегий, ради которого на хосте существует пользователь qeli, здесь нет: компрометация демона — это root внутри контейнера (не на хосте, но с выданными NET_ADMIN/NET_RAW граница тоньше, чем кажется). Не выставляйте панель наружу без пароля и web.allowed_ips.
  • Ловушки с владельцем /etc/qeli не возникает — всё внутри и так пишется от root. Но файлы в примонтированном томе появятся на хосте с uid 0; если тот же каталог потом отдать хостовой службе под User=qeli, права придётся привести в порядок вручную.
  • Хуки post_up/post_down в контейнере действительно исполняются от root (в отличие от .deb-установки, где это qeli).

Перезапуск службы из панели в контейнере не работает и не пытается: systemd внутри нет. Профили/пользователи/DNS/NAT применяются рестартом worker'а автоматически, а изменения сокета панели (web.bind/web.port/web.tls*/web.enabled) требуют пересоздания контейнера снаружи — см. §6.11 в TROUBLESHOOTING.md.


3. Первичная настройка сервера (CLI)

3.1. Создать рабочий конфиг из примера

sudo cp /etc/qeli/server.conf.example /etc/qeli/server.conf
sudo nano /etc/qeli/server.conf

Формат — flat-INI. Файл-пример исчерпывающий: каждый ключ перечислен со значением по умолчанию и пояснением; любой удалённый ключ берёт дефолт. Для старта достаточно проверить несколько полей в секции [profile:tcp].

3.2. Минимально нужные поля профиля

[profile:tcp]
enabled = true

# на чём слушаем (порт должен быть открыт в файрволе)
bind.address = 0.0.0.0
bind.port    = 443
# tcp | udp
bind.transport = tcp

# виртуальная сеть туннеля
# адрес сервера внутри туннеля (шлюз)
tun.address  = 10.9.0.1
# пушится клиентам; для прод-TCP см. §12 и CONFIG.md
tun.mtu      = 1400

# подсеть VPN и пул; её префикс также настраивает сервер и клиентов
pool.cidr    = 10.9.0.0/24

# режим маскировки на проводе (см. §11)
obf.mode = fake-tls

Остальное (DNS-прокси, padding, heartbeat, лимиты) уже задано разумными дефолтами в примере. Полное описание каждого ключа — CONFIG.md.

Несколько профилей. Можно держать рядом второй интерфейс, например UDP на :1443 — добавьте секцию [profile:udp] (свой tun.name/tun.address/pool.cidr/ bind.port/bind.transport = udp). У каждого профиля — свой identity-ключ и свой пул. Готовый шаблон со всеми 10 режимами сразу (reality-tls на :443, остальные на 8443–8451) — /etc/qeli/server-multiprofile.conf.example (его ставит .deb; в исходниках — config/server-multiprofile.conf): скопируйте его в server.conf, оставьте нужные профили, замените CHANGEME-ключи.

3.3. Пользователи: где они живут

По умолчанию пользователи живут в отдельном файлеauth.users_file (по умолчанию /etc/qeli/users.conf). Примеры конфигов идут без инлайн-юзеров; заводите их командой qeli add-client (шаг 6) — она допишет их в этот файл. Больше ничего делать не нужно.

Можно вместо этого держать пользователей инлайн в server.conf секциями [user:*], но тогда auth.users_file игнорируется целиком (инлайн имеет приоритет) — так что не задавайте оба, иначе сервер выдаёт предупреждение, а файл молча отбрасывается. Рекомендуемый вариант по умолчанию — отдельный файл; [user:*] в server.conf не держите.


4. Запуск и проверка

Сначала проверьте конфиг — это ловит опечатки в ключах (о которых предупреждают §3.1 и §12: неверный ключ молча остаётся с дефолтом) и ключи, убранные в 0.7.12:

sudo qeli check-config --config /etc/qeli/server.conf     # сервер (rc≠0 = не запускать)
qeli check-config --config ~/qeli-client.conf --client     # клиентский конфиг

Затем запуск:

sudo systemctl enable --now qeli         # запустить + автозапуск при бутe
systemctl status qeli                    # должно быть active (running)
journalctl -u qeli -f                     # живой лог (Ctrl-C — выйти)

В логе при старте должны появиться Profile 'tcp': TUN vpn0 is up, listening on 0.0.0.0:443, и строка с публичным ключом профиля.

Получить identity-ключ сервера (для пиннинга на клиенте)

sudo qeli show-identity --config /etc/qeli/server.conf
PROFILE   BIND                SERVER PUBLIC KEY (pin on client)
tcp       tcp://0.0.0.0:443   33f399e6d9b8a31a41e5ffa8b1e1ce457f10d8bbf07c145377fcb7917d532450

Этот hex-ключ клиент пинит (key = …). Команда создаёт ключи профилей, если их ещё нет (/etc/qeli/identity/<profile>.key).

Почему пиннинг обязателен. По умолчанию включён H-1 (auth.bind_static_to_session = true): сессионные ключи привязаны к статической личности сервера, поэтому клиент обязан пинить реальный ключ (иначе сервер его отвергнет). Ссылка qeli://, выданная командой add-client --link (шаг 6), уже содержит этот ключ — пользователю ничего вручную вписывать не нужно.

После изменения конфига примените его: sudo systemctl restart qeli.


5. Full-tunnel: NAT (настраивается автоматически)

Нужно, только если хотите гнать весь интернет-трафик клиента через сервер (full-tunnel / «выходная нода»). Для split-tunnel (доступ лишь к подсети туннеля и ресурсам за сервером) — пропустите.

Достаточно включить один тумблер в профиле — сервер сам через iptables включит IP-форвардинг и поставит MASQUERADE + FORWARD + MSS-clamp, а при остановке снимет правила:

# в [profile:tcp]
routing.nat.enabled  = true
# WAN-интерфейс наружу. Оставьте пустым/по умолчанию — определится автоматически
# (ip route get 1.1.1.1); либо задайте явно, напр. ens3.
routing.nat.interface =
sudo systemctl restart qeli      # сервер применит NAT при старте профиля
journalctl -u qeli | grep NAT    # "NAT masquerade active via iptables (10.9.0.0/24 -> ens3)"
sudo iptables-save | grep qeli-nat   # увидеть установленные правила

Что именно ставит сервер (правила помечены comment'ом qeli-nat:<профиль>, чтобы снять ровно их при выключении/остановке): net.ipv4.ip_forward=1; -t nat POSTROUTING -s <pool.cidr> -o <wan> -j MASQUERADE; две FORWARD … ACCEPT (tun↔wan); две -t mangle FORWARD … TCPMSS --set-mss (tun.mtu−40) (защита от PMTU-чёрной дыры).

⚠️ Требуется iptables (пакет iptables). У .deb он в зависимостях, так что при установке пакетом уже стоит. Если iptables не установлен, NAT применить нельзя: в логе сервера будет ERROR … routing.nat.enabled is set but NAT was NOT applied, а в веб-панели (Dashboard) — жёлтый баннер с подсказкой. Поставить: sudo apt install iptables. Используется только классический iptables (не nft/ufw).

Прод-тюнинг (BBR, буферы, MTU-probing — заметно ускоряет TCP на мобильных) описан в CONFIG.md → «Тюнинг ОС сервера». Для full-tunnel настоятельно примените. Чтобы правила NAT пережили перезагрузку без сервиса qeli, можно дополнительно сохранить их (apt install iptables-persistent), но обычно qeli ставит их сам при старте.


6. Заведение пользователей (CLI)

6.1. Простой пользователь

sudo qeli add-client alice --password 's3cret'
sudo systemctl restart qeli            # перечитать пользователей

Команда Argon2id-хеширует пароль и дописывает секцию [user:alice] в users-файл. Без --password сгенерирует случайный и напечатает его один раз.

6.2. С опциями

sudo qeli add-client bob \
  --password 'pass123' \
  --static-ip 10.9.0.50 \          # фиксированный IP в туннеле
  --max-sessions 3 \               # сколько устройств одновременно (0 = без лимита)
  --profiles tcp                   # доступ только к профилю tcp (изоляция интерфейсов)
Опция Назначение
--password <P> пароль (иначе случайный, печатается один раз)
--static-ip <IP> постоянный адрес в туннеле (иначе из пула)
--max-sessions <N> лимит одновременных устройств (0 = наследовать группу/без лимита)
--profiles a,b разрешённые профили (пусто = все)
--link --host <H[:port]> сразу напечатать qeli://-ссылку + QR (см. ниже)
--link-profile <P> для какого профиля строить ссылку (по умолчанию первый)

6.3. Сразу выдать qeli://-ссылку / QR

sudo qeli add-client carol --password 'pw' --link --host vpn.example.com:443 --link-profile tcp

Печатает готовую qeli://…-ссылку (с уже вшитым ключом сервера, режимом, SNI) и QR-код в терминале — пользователь сканирует его в мобильном клиенте и подключается в один тап. Ничего вручную вписывать не нужно.

6.4. Тонкая настройка вручную (опционально)

Любые поля можно дописать прямо в секцию [user:*] (см. комментарии в users.conf):

[user:bob]
# ставит add-client
password_hash = $argon2id$v=19$m=...$...
enabled = true
static_ip = 10.9.0.50
max_sessions = 3
profiles = tcp
# ACL: куда этому юзеру можно (пусто = куда угодно)
allowed_networks = 10.9.0.0/24, 192.168.1.0/24
# лимит скорости (0 = без лимита)
bandwidth.limit_mbps = 50
bandwidth.burst_mbps = 100
# персональный pushed-маршрут (повторяемо)
route = 10.20.0.0/16 gateway=10.9.0.1 metric=100
# унаследовать из [group:premium]
group = premium

Группы — шаблоны для повторяющихся настроек:

[group:premium]
bandwidth_limit_mbps = 100
max_sessions = 5
allowed_networks = 0.0.0.0/0

После правок users-файла — sudo systemctl restart qeli (или примените живой командой, §10, без перезапуска).


7. Маршруты

7.1. Split-tunnel (по умолчанию)

Клиент по умолчанию заворачивает в туннель только подсеть туннеля (pool.cidr). Остальной трафик идёт мимо VPN. Ничего настраивать на сервере не нужно.

7.2. Full-tunnel (весь трафик через сервер)

Включается на клиенте (gateway = true в client.conf / тумблер в приложении), а на сервере требует NAT+форвардинг из §5. Тогда весь интернет клиента выходит с IP сервера.

7.3. Pushed-маршруты на уровне профиля (всем клиентам профиля)

Чтобы открыть клиентам доступ к сети за сервером (напр. офисной 192.168.50.0/24), сервер «пушит» маршрут — клиент сам добавит его в таблицу при подключении:

# в [profile:tcp] — повторяемо
route = 192.168.50.0/24 gateway=10.9.0.1 metric=100

gateway — адрес сервера в туннеле (tun.address). metric — приоритет (опц.). Форвардинг RFC1918-сетей за сервером (routing.forward_private) включён по умолчанию; поставьте false, чтобы запретить.

7.4. Персональные маршруты (конкретному пользователю)

Тот же синтаксис, но в секции [user:*] — пушится только этому пользователю:

[user:bob]
route = 10.20.0.0/16 gateway=10.9.0.1 metric=100

7.5. ACL назначения (allowed_networks)

Ограничивает, куда пользователю можно ходить через туннель (whitelist dst-CIDR). Пусто/нет ключа = без ограничений:

[user:bob]
allowed_networks = 10.9.0.0/24, 192.168.1.0/24

7.6. Клиент-клиент и статические адреса

# в [profile:tcp]
# разрешить клиентам видеть друг друга в туннеле
routing.client_to_client = true
# закрепить IP за юзером (альтернатива user.static_ip)
pool.reservation.alice = 10.9.0.100

7.7. DNS-через-туннель

Важно различать два разных механизма — это частый источник путаницы:

  1. Встроенный DNS-прокси (dns.enabled / dns.listen / dns.upstream) — сервер поднимает резолвер на tun.address:53 (кэш, блоклист) и форвардит запросы на upstream.
  2. Какой DNS выдаётся клиентам (dns.push_servers) — адрес(а), которые клиент пропишет себе. Это отдельный ключ.

Что сервер реально пушит клиенту (server/handler.rs):

dns.push_servers dns.enabled Клиент получает Итог
задан (напр. 1.1.1.1) первый адрес из списка клиент ходит на него напрямую, мимо прокси (кэш/блоклист не действуют)
пусто true dns.listen (адрес прокси) клиент → прокси на сервере → upstream. Так по умолчанию.
пусто false ничего клиент оставляет свои резолверы
# в [profile:tcp] — вариант «клиенты через мой прокси» (рекомендуется)
dns.enabled  = true
dns.upstream = 1.1.1.1, 8.8.8.8
# dns.blocklist = ads.example.com, track.example.com   # отдавать 0.0.0.0 (блок рекламы)
dns.push_servers = ""        # пусто → клиентам выдаётся адрес прокси (tun.address)

# ...или «раздать клиентам готовый резолвер напрямую» (LAN / AdGuard / NextDNS):
# dns.push_servers = 192.168.50.10        # прокси при этом можно и не включать

Если в панели видите в поле «Передавать DNS клиентам» непустое значение, но клиент всё равно получает tun.address — проверьте, что правка сохранена и применена (перезапуск сервиса): пуш-DNS берётся из конфига на диске, а не из несохранённой формы.


8. Подключение клиента

8.1. Мобильный (Android) и десктоп (Windows/macOS)

  1. На сервере выдайте ссылку: qeli add-client <user> --link --host <публичный-host:порт> (§6.3) — получите qeli://… + QR.
  2. В приложении: Add profile → Scan QR (или Paste qeli:// link) → профиль появится со всеми параметрами и запиненным ключом сервера.
  3. Нажмите кольцо подключения. Готово.

Full-tunnel и «маршрутизировать локальные сети» переключаются тумблерами в приложении.

Форма метки времени в окне лога — Настройки → Время в логе (те же пять вариантов, что и у [logging] time_format на сервере: дата и время / RFC 3339 в UTC / только время / Unix / без метки). Если собираетесь сверять лог приложения с серверным, поставьте RFC 3339 с обеих сторон. Применяется сразу, к уже написанным строкам — нет.

iOS. Клиент для iPhone/iPad лежит в qeli-ios/ и по возможностям повторяет Android: те же профили, qeli://-ссылки и QR, те же режимы обмена, русский/английский интерфейс, виджет и переключатель в Пункте управления. Он собирается из исходников на macOS (Xcode 16+, см. README) — готовой сборки в релизах нет, и на живом устройстве он ещё не проверялся. Отличия, продиктованные платформой: маршрутизация «по приложениям» доступна только через MDM, а вместо автоподключения при загрузке используется VPN On Demand — подробности в qeli-ios/PARITY.md.

⚠️ macOS — первый запуск. Приложение подписано ad-hoc (не нотаризовано Apple), поэтому Gatekeeper его блокирует и оно не откроется двойным кликом. Один раз снимите карантин в Терминале:

xattr -cr /Applications/Qeli.app

(см. qeli-mac/README.md).

8.2. Linux CLI-клиент

sudo cp /etc/qeli/client.conf.example /etc/qeli/client.conf
sudo nano /etc/qeli/client.conf

Минимум (см. client.conf — описан каждый ключ):

[qeli]
server = vpn.example.com:443
proto  = tcp
user   = alice
pass   = s3cret
# из `qeli show-identity` (ОБЯЗАТЕЛЕН при H-1)
key    = 33f399e6…d532450
# должен совпадать с obf.mode профиля
mode   = fake-tls
sni    = www.cloudflare.com

# локальная маршрутизация (в qeli://-ссылке НЕ передаётся — только в файле):
# true = full-tunnel (весь трафик через VPN)
gateway     = false
# также заворачивать приватные сети + server-pushed
route_local = false
# блокировать утечки, пока туннель не поднят (full-tunnel)
kill_switch = false
# tunnel = per-link DNS через systemd-resolved; off = DNS управляет платформа
dns         = tunnel
sudo qeli client --config /etc/qeli/client.conf

При H-1 (дефолт) key обязателен и должен быть реальным (не нулевым). Если на сервере bind_static_to_session = false, можно работать по TOFU (нулевой key).


9. То же самое через веб-панель

Полный гайд — PANEL.md. Краткий старт:

9.1. Включить панель

# задать админ-пароль (генерирует/хеширует, прописывает в [web], включает панель)
sudo qeli set-web-password                    # случайный пароль, печатается один раз
# или свой:  sudo qeli set-web-password --password 'PANELPASS'

Добейте секцию [web] и перезапустите. Начните с loopback — это значение по умолчанию, и для него не нужно ничего открывать в файрволе:

[web]
enabled = true
bind = 127.0.0.1
port = 8080
# встроенный HTTPS (self-signed авто; браузер предупредит 1 раз)
tls  = true
# хост по умолчанию для share-ссылок
# public_host = vpn.example.com

Доступ со своей машины — через SSH-форвард:

ssh -L 8080:127.0.0.1:8080 root@<сервер>   # затем откройте https://127.0.0.1:8080

Если панель действительно нужна на внешнем адресе — публикуйте её со списком источников, а не без него. Кроме пароля, allowed_ips — единственное, что отделяет открытый интернет от интерфейса, который управляет пользователями, переписывает конфиг, ротирует identity-ключи и восстанавливает бэкапы:

[web]
enabled = true
bind = 0.0.0.0
port = 8080
tls  = true
allowed_ips = 203.0.113.4          # ЗДЕСЬ ОБЯЗАТЕЛЕН — ваш адрес (адреса)
# public_host = vpn.example.com
# дефолтный хост для share-ссылок
# public_host = vpn.example.com
sudo systemctl restart qeli

Fail-closed: с пустым password_hash панель не стартует ни на каком bind, включая loopback (с 0.7.12 — раньше loopback был исключением и отдавал открытую панель). VPN :443 при этом работает — это отдельный процесс. Хеш задаётся через qeli set-web-password; осознанный отказ — web.insecure_no_auth = true. Откройте порт 8080 в файрволе.

9.2. Пользоваться

Откройте https://<bind>:8080, войдите как admin.

  • Quick startотдельный пункт левого меню (не вкладка Dashboard). Таблица всех 10 режимов маскировки: reality-tls, reality, fake-tls, obfs-ws, obfs-none, plain, udp-fake-tls, udp-quic, udp-obfs, obfs-awg. Кнопка Launch в строке собирает готовый профиль (TUN/NAT/DNS/пул/обфускация), сохраняет его и перезапускает сервер.
  • Config — все поля профиля одной страницей (Bind/TUN/Pool/Routing/DNS/Obfuscation/ Performance), вкл. pushed-маршруты и NAT; вкладка Global — identity-ключи (показ + Rotate), Web UI, H-1. Кнопки: Save — записать конфиг на диск; Apply & Restart — сохранить и сделать полный systemctl restart (применяет всё, включая сокет панели); Reload — перечитать конфиг с диска, отбросив несохранённые правки.
  • Users — создать пользователя (пароль открытым текстом — хешируется сервером), задать bandwidth/static-IP/группу/max-sessions/разрешённые профили/allowed-networks/ персональные маршруты. Группы — шаблоны.
  • Share / QR у пользователя — выдаёт qeli://-ссылку + QR без ввода пароля (сервер хранит обратимо-зашифрованную копию; пароль не меняется).

9.3. Подключение К другим серверам (вкладка Client)

Панель умеет не только раздавать VPN, но и сама подключаться к другим qeli-серверам (этот бокс становится клиентом — релеем, или просто управляемым клиентом). Вкладка Client:

  • Добавить профиль — тремя способами:

    • Import qeli:// link — вставить qeli://-строку, которую вам дал админ сервера;
    • Add manually — форма (server/user/pass/key/mode/sni/rsid/obfs_key, QUIC для UDP, split/full-tunnel);
    • Paste INI config / переключатель Raw INI — полный клиентский INI (любой ключ: dev/mtu/dns/kill_switch/bind_static/[logging]…).
  • Каждый профиль управляется НЕЗАВИСИМО. Создание профиля его не подключает — он лежит в статусе Disconnected. У каждого своя кнопка Connect / Disconnect; жмёте только на нужные. Статус (подключён + хвост лога) обновляется сам.

  • Несколько подключений одновременно — поднимайте сколько нужно: каждому профилю автоматически выдаётся свой TUN-интерфейс (vpn0/vpn1/…, виден в списке), так что туннели не конфликтуют. К одному серверу — заведите несколько профилей (один тоннель на профиль). Любой режим, не только reality-tls.

  • ⚠️ Full-tunnel и несколько туннелей. Маршрут по умолчанию в системе один, поэтому несколько одновременных full-tunnel конфликтуют — для мульти-релея используйте split-tunnel (и разные пул-подсети на серверах), либо держите full-tunnel по одному. Полный заворот на сервере-боксе может отрезать саму панель/SSH — включайте осознанно.

  • Хранилище: профили лежат в /etc/qeli/clients/<name>.conf (тот же flat-INI). Это значит, то же самое можно сделать и файлами: положить конфиги туда и запускать qeli client --config /etc/qeli/clients/<name>.conf (для нескольких — разный dev в каждом файле). Готовый пример клиента — client-reality.conf и client.conf (все режимы и ключи).

  • Автозапуск при загрузке. У каждого профиля есть флаг autostart: помеченные профили qeli (supervisor + панель) поднимает сам при старте сервиса — после reboot/systemctl restart qeli нужные тоннели встают без ручного Connect. Задаётся двумя способами, равнозначно:

    • в панели — галочка «Auto-connect this profile when the server/panel starts» в форме профиля (в списке такой профиль помечен значком ↻ autostart);
    • в файле — строкой autostart = true в секции [qeli] файла /etc/qeli/clients/<name>.conf (правьте руками — эффект тот же, что и галочка).

    Флаг независим для каждого профиля — автозапускаются только помеченные, остальные остаются Disconnected до явного Connect. Снять автозапуск — снять галочку (или убрать строку из файла).


10. Справочник CLI и диагностика

qeli — один бинарь с подкомандами; есть ещё тонкий клиентский бинарь qeli-client. Команды делятся по тому, как они общаются с сервером: правят конфиг на диске (нужен рестарт) или идут через control-сокет (применяются на лету). qeli --help и qeli <команда> --help печатают то же самое.

10.1. Режимы запуска (-c/--config)

qeli server        [-c /etc/qeli/server.conf]   # сервер (супервайзер + data-plane worker)
qeli client        [-c /etc/qeli/client.conf]   # клиент
qeli check-config  [-c <путь>] [--client]        # проверить конфиг и выйти (см. §4); --client = как [qeli]
qeli-client        [-c /opt/etc/qeli/client.conf] # тонкий клиент для роутеров/headless (Entware), только --config

Скрытая qeli _worker — внутренний data-plane потомок, порождается server. Руками не запускать.

10.2. Пользователи и идентичность

Правят файл конфига/ключей на диске (-c/--config, дефолт /etc/qeli/server.conf), а не сокет — где меняется конфиг или ключ, нужен рестарт сервиса:

# добавить пользователя (Argon2-хеш пароля) в users-файл:
sudo qeli add-client alice \
     -p 'секрет' \            # --password; без него сгенерит и покажет ОДИН раз
     --profiles tcp,reality \ # ограничить профилями (пусто = все)
     --static-ip 10.9.0.100 \ # закрепить туннельный IP (опц.)
     --max-sessions 2 \       # 0 = дефолт группы
     --link --host vpn.example.com:443 --link-profile reality   # напечатать qeli://-ссылку (+QR)

# ПОВТОРНО выдать ссылку УЖЕ существующему пользователю (пароль вводить не нужно):
sudo qeli share-link alice \
     --host vpn.example.com:443 \  # без него берётся web.public_host
     --profile reality \           # по умолчанию — первый профиль
     --label 'Мой VPN'             # по умолчанию <профиль>-<порт>

sudo qeli set-web-password --username admin [-p 'пароль'] [--no-enable]  # логин панели (Argon2id); §9.1
sudo qeli show-identity                     # pubkey каждого профиля (клиент пинит key=); создаёт ключи, если их нет
sudo qeli rotate-identity reality           # перегенерировать ключ профиля → клиентам обновить key=, рестарт

10.2.1. share-link — переслать конфиг существующему пользователю

Отвечает на вопрос «клиент потерял настройки / сменил телефон — как выдать ему конфиг заново». add-client для этого не годится: он создаёт пользователя и на существующем имени падает с ошибкой.

qeli share-link <username> [--host <адрес[:порт]>] [--profile <имя>]
                           [--label <текст>] [--reset] [-c <конфиг>]
Флаг По умолчанию Что делает
<username> обязателен: существующий пользователь из users-файла
--host web.public_host из конфига публичный адрес сервера для ссылки; host:port переопределяет порт профиля
--profile первый профиль в конфиге для какого профиля собрать ссылку (у каждого свой порт, режим, ключ)
--label <профиль>-<порт> подпись профиля в приложении клиента
--reset выкл сгенерировать НОВЫЙ пароль, если старый не восстанавливается (разрушающее, см. ниже)
-c, --config /etc/qeli/server.conf путь к конфигу сервера

Как это работает. Пароль вводить не нужно и невозможно восстановить из хеша — он необратим. Поэтому при заведении пользователя рядом с Argon2-хешем сохраняется ещё и обратимо зашифрованная копия пароля; share-link расшифровывает её и подставляет в ссылку. Остальное берётся из конфига профиля автоматически: порт, транспорт, wire-режим, SNI, obfs-ключ, reality short_id, параметры awg и закреплённый публичный ключ сервера (show-identity). Это тот же механизм и тот же код, что за кнопкой share/QR в панели, — ссылки из CLI и из панели совпадают.

# типовой случай: адрес уже задан в web.public_host
sudo qeli share-link alice

# явный адрес и конкретный профиль
sudo qeli share-link alice --host vpn.example.com:443 --profile reality --label 'Мой VPN'

Вывод — строка qeli://…: её можно отправить клиенту, показать как QR или вставить в приложение.

Когда копии пароля нет (пользователь заведён до появления этой возможности либо сменился ключ шифрования) — команда откажется и укажет на --reset:

sudo qeli share-link alice --reset      # печатает НОВЫЙ пароль один раз
sudo systemctl reload qeli              # обязательно: иначе сервер проверяет старый пароль

⚠️ --reset разрушающий: конфиг, которым пользователь пользуется сейчас, перестаёт работать — ему нужно передать новую ссылку. И, в отличие от панели, у CLI нет канала к работающему воркеру, поэтому перечитать пользователей нужно вручную (reload); команда сама об этом напоминает в выводе.

10.3. Живое управление (control-сокет, БЕЗ рестарта)

Идут через --socket (дефолт /var/run/qeli/control.sock) — применяются немедленно:

sudo qeli list-clients               # кто сейчас подключён + выданные IP
sudo qeli kick alice                 # оборвать сессии пользователя
sudo qeli disable-user bob           # заблокировать (кик + запрет реконнекта)
sudo qeli enable-user bob            # снова разрешить
sudo qeli set-bandwidth alice 50     # лимит Мбит/с (0 = без лимита)
sudo qeli show-routes alice          # маршруты пользователя
sudo qeli list-blocked               # IP, залоченные брутфорс-защитой (неверный пароль)
sudo qeli unblock 1.2.3.4            # снять блок с адреса (--all — со всех)

10.4. Прочее

qeli version           # версия
qeli version --check   # спросить у GitHub Releases, есть ли новее (opt-in, только уведомляет, ничего не качает)

# Разрешить non-root сервисному пользователю перезапускать свой юнит из кнопки панели
# «Apply & Restart». Нужно ТОЛЬКО при установке НЕ из .deb (.deb ставит правило сам) —
# панель сама сообщит, когда правила нет. Пишет /etc/polkit-1/rules.d/49-qeli.rules; root.
sudo qeli install-polkit                                        # по умолчанию: user=qeli, unit=qeli.service
sudo qeli install-polkit --unit qeli-server.service --user vpn  # нестандартный юнит/пользователь
sudo qeli install-polkit --dry-run                             # напечатать правило, ничего не писать

# Выбрать ОС-пользователя, от которого работает СЛУЖБА: `qeli` (по умолчанию, без привилегий) или `root`.
sudo qeli set-service-user root      # переключить на root (см. предупреждение ниже)
sudo qeli set-service-user qeli      # вернуть непривилегированный вариант по умолчанию
sudo qeli set-service-user root --dry-run          # показать, что изменится
sudo qeli set-service-user root --unit qeli-server.service   # нестандартный юнит
sudo systemctl restart qeli          # нужен, чтобы изменение вступило в силу

Что именно делает set-service-user. Он не правит поставляемый юнит (/lib/systemd/system/qeli.service): dpkg перезапишет его при каждом обновлении, и правка молча потеряется. Вместо этого он управляет systemd drop-in override:

аргумент что делает
root пишет /etc/systemd/system/qeli.service.d/run-as.conf с [Service] User=root / Group=root — он приоритетнее поставляемого User=qeli. Лежит в /etc, поэтому переживает обновления пакета.
qeli удаляет этот drop-in (в поставляемом юните уже User=qeli) и выполняет chown -R qeli:qeli /etc/qeli: файлы, созданные пока служба работала от root, принадлежат root, и непривилегированная служба не смогла бы их писать.

Оба варианта затем выполняют systemctl daemon-reload; для применения перезапустите службу. Команда идемпотентна (повторный запуск безопасен), требует root и отвергает любые значения, кроме qeli/root. Закалка юнита — ProtectSystem=full, NoNewPrivileges=true, ограниченный CapabilityBoundingSetдействует в обоих случаях; root меняет только то, от кого работает процесс.

⚠️ Когда запускать от root — и почему обычно не стоит. Пользователь qeli по умолчанию нужен для разделения привилегий: если демон скомпрометируют, атакующий получит учётку, которой не принадлежит ничего, кроме /etc/qeli, — а не машину. Запуск от root это убирает: компрометация VPN-демона становится полным root на хосте. Демон доступен из интернета, так что различие не теоретическое.

Законные причины выбрать root:

  • ядро или контейнер, не уважающие AmbientCapabilities, — непривилегированная служба вообще не может создать TUN или занять :443 (симптом: профиль не поднимается с Operation not permitted, хотя юнит выдаёт нужные capabilities);
  • ограниченное окружение, где нельзя поставить polkit-правило, а кнопка панели Apply & Restart нужна (root управляет своим юнитом напрямую);
  • вы постоянно наступаете на ловушку с владельцем /etc/qeli (§A.3) и осознанно принимаете размен.

Если всё же работаете от root — компенсируйте в другом месте: не выставляйте панель в интернет (web.allowed_ips либо bind на loopback + SSH-туннель) и вернитесь на sudo qeli set-service-user qeli, как только причина отпадёт.

10.5. Диагностика

journalctl -u qeli -f                          # лог сервера
sudo qeli list-clients                          # активные сессии + выданные IP
ping 10.9.0.2                                   # пинг клиента из туннеля (с сервера)
ss -tulnp | grep qeli                           # слушает ли :443 / :8080

На клиенте проверьте, что появился интерфейс vpn0 и маршруты (ip a, ip route).

Глубокая диагностика обфускации. Если DPI режет туннель и надо понять, что реально уходит в провод, включите таймлайн форм пакетов: QELI_TRACE=<файл> qeli client … (opt-in, пишет только размеры/тайминги, не содержимое; дамп по SIGUSR1). Подробности и разбор — в TROUBLESHOOTING.md.


11. Wire-режимы — какой выбрать

Задаётся obf.mode на сервере и mode на клиенте (должны совпадать):

Режим Когда
fake-tls по умолчанию. Мимикрия под TLS 1.3, против пассивного/сигнатурного DPI. Хороший баланс.
reality-tls максимальная маскировка: туннель внутри настоящего TLS 1.3 с одолженным сертом реального сайта (паритет Xray-REALITY). Держит и активное зондирование. Требует key + reality_sid + sni; чуть медленнее.
obfs ChaCha20-обфускация всего потока; WS-fronting опционален (front = websocket / none). Нужен общий obfs_key. Работает и по TCP, и по UDP.
plain без маскировки — голый шифрованный туннель (макс. скорость). Для доверенных сетей.
QUIC-masking для UDP-профилей (obf.quic.enabled = true), маскирует под QUIC.

Подробное сравнение, REALITY-настройка (short_ids, handrolled), multipath-бондинг — в CONFIG.md. Бенчмарки всех режимов — BENCHMARK.md.


12. Частые проблемы

  • Сервер отказывается стартовать: «pool.cidr … contains this host's DEFAULT GATEWAY» / «overlaps the existing route …». Это предстартовая проверка, и она спасает вас от потери доступа к машине. Подсеть туннеля пересекается с сетью, которую хост уже использует. Худший случай — когда tun.address совпадает с адресом шлюза: при подъёме TUN шлюз становится локальным адресом, весь исходящий трафик умирает в туннеле, и сервер пропадает из сети целиком, вместе с SSH и пингом; вернуться можно только через консоль хостера. Лечение — увести туннель в свободный диапазон (tun.address = 10.9.0.1, pool.cidr = 10.9.0.0/24). Свои сети смотрите через ip route и ip -4 addr, а проверить конфиг до запуска можно командой qeli check-config --config /etc/qeli/server.conf — она выполняет ту же проверку против текущего хоста.
  • Поставил из .deb — «ничего не работает»: профиль не поднимается, пользователи и настройки панели не сохраняются, служба в рестарт-петле. Почти всегда это права: служба работает под User=qeli и пишет в /etc/qeli (identity-ключи, users-файл, сохранения панели), а конфиг и файлы, созданные вами под root после установки, остались root-овыми. Лечится sudo chown -R qeli:qeli /etc/qeli + рестарт — подробно с симптомами и модами в §2, «A.3. Права на /etc/qeli».
  • Клиент проходит «identity verified», но сразу отваливается / AUTH FAIL … not found. Пользователь не там, где сервер его ищет: в server.conf есть инлайн [user:*]users_file игнорируется (см. §3.3). Держите пользователей в одном месте.
  • Подключается, но интернета нет (full-tunnel). Проверьте, что в профиле routing.nat.enabled = true и что на сервере установлен iptables (apt install iptables) — без него сервер не сможет поставить MASQUERADE (в логе NAT requested but NOT applied, в панели — жёлтый баннер). Проверка: iptables-save | grep qeli-nat должно показывать правила; journalctl -u qeli | grep NAT — строку «NAT masquerade active». Если WAN-интерфейс определился неверно — задайте routing.nat.interface явно.
  • Загрузка зависает / рвётся под нагрузкой (TCP). Не сделан MSS-clamp под MTU туннеля (PMTU-чёрная дыра) — правило TCPMSS из §5; для прода ещё BBR (CONFIG.md).
  • Сервер отвергает клиента без понятной причины. Включён H-1 (дефолт), а клиент не пинит ключ. Впишите реальный key (из qeli show-identity) — проще всего выдать профиль ссылкой add-client --link (§6.3).
  • Не пускает после нескольких неверных паролей. Сработал анти-брутфорс по source-IP. Политик две, и они независимы: [auth] brute_force — вход VPN-пользователей, снимается qeli unblock <ip> (или --all); [web] brute_force — вход в панель, снимается только на её странице Blocked IPs (CLI туда не достаёт: control-сокет живёт в воркере, а панель — в супервизоре). Дефолты у обеих: 5 попыток / окно 300 с / блокировка 900 с. Либо дождитесь конца блокировки, либо systemctl restart qeli — счётчики хранятся в памяти и сбрасываются.
  • Веб-панель не стартует. Fail-closed: пуст password_hash — панель не поднимается ни на каком bind, включая loopback — задайте qeli set-web-password (§9.1). VPN :443 при этом не страдает (это отдельный процесс).
  • 403 на любое сохранение в панели за доменом/прокси. Добавьте домен в web.allowed_origins (CSRF same-origin); свой IP — в web.allowed_ips, иначе заблокируете сами себя.

13. Полное удаление qeli

По ролям — удаляйте только то, что ставили. <ПОРТ> ниже = порт вашего профиля (напр. 443).

13.1. Сервер (Linux)

# 1. Остановить и отключить сервис
sudo systemctl disable --now qeli

# 2a. Ставили из .deb → снять пакет (удалит сервис, /usr/bin/qeli, polkit-правило).
#     purge удалит и conffiles (примеры конфигов):
sudo apt purge qeli

# 2b. Ставили вручную/бинарём → снять руками:
sudo rm -f /usr/bin/qeli /usr/local/bin/qeli
sudo rm -f /etc/systemd/system/qeli.service /lib/systemd/system/qeli.service && sudo systemctl daemon-reload

# 3. Конфиги, ключи идентичности, пользователи, выданные ссылки.
#    ⚠️  identity-ключ пропадёт → клиентам с пиннингом (reality-tls / H-1) придётся
#    ПЕРЕВЫДАТЬ конфиги. Хотите сохранить: sudo cp -a /etc/qeli /root/qeli-backup
sudo rm -rf /etc/qeli

# 4. Состояние, логи, runtime
sudo rm -rf /var/lib/qeli /var/log/qeli /run/qeli

# 5. Системный пользователь сервиса
sudo deluser --system qeli 2>/dev/null; sudo delgroup qeli 2>/dev/null; true

Дополнительно — если ставили через install-qeli-server.sh (он трогает ОС):

# sysctl-тюнинг (BBR / буферы / PMTU)
sudo rm -f /etc/sysctl.d/99-qeli-perf.conf && sudo sysctl --system >/dev/null

# BBR-модуль: установщик прописывает его в автозагрузку — иначе tcp_bbr грузится вечно
sudo rm -f /etc/modules-load.d/qeli-bbr.conf

# iptables: СВОИ NAT/MASQUERADE-правила qeli снимает сам при чистой остановке (шаг 1).
# Установщик дополнительно ставит MSS-clamp — на ИСХОДЯЩИЙ порт (--sport): SYN-ACK летит
# ОТ порта сервера, поэтому правило матчит именно --sport. Сначала посмотреть остатки:
sudo iptables-save | grep -iE 'qeli-nat|MASQUERADE|TCPMSS'
sudo iptables -t mangle -D OUTPUT -p tcp --sport <ПОРТ> --tcp-flags SYN,RST SYN \
     -j TCPMSS --set-mss 1340 2>/dev/null; true

# И только ПОСЛЕ удаления пере-сохранить — иначе save законсервирует то, что вы
# только что пытались снять. Проверьте, что grep выше больше ничего не находит.
sudo netfilter-persistent save 2>/dev/null; true

Проверьте --sport, а не --dport. Установщик ставит правило с --sport; команда с --dport не совпадёт ни с чем, тихо провалится (из-за 2>/dev/null; true), и следующий netfilter-persistent save закрепит правило навсегда.

Если у вас нет netfilter-persistent, установщик сохранил снимок в /etc/iptables/rules.v4 — причём весь текущий ruleset хоста, не только правило qeli. Проверьте этот файл перед удалением: sudo iptables-save > /etc/iptables/rules.v4.

Если правила НЕ сохранялись в netfilter-persistent / /etc/iptables/rules.v4 — они исчезнут сами после перезагрузки.

13.2. Клиент — Linux (Rust CLI)

Чистая остановка (Ctrl+C) сама восстанавливает /etc/resolv.conf, снимает kill-switch / NAT и удаляет tun. Руками — только если клиент упал:

sudo pkill -f 'qeli client'                    # прибить, если висит
# DNS: оригинал лежит в /var/lib/qeli/dns-backup.json — проще всего запустить и ЧИСТО
#      остановить клиент (он восстановит resolv.conf сам), либо вернуть из бэкапа вручную.

# Kill-switch (если был kill_switch = true). Правила живут в ОТДЕЛЬНОЙ цепочке
# QELI_KS_<интерфейс> — имя привязано к `dev = …`, чтобы несколько экземпляров клиента
# не затирали правила друг друга. Снимается точечно: сначала убрать переход из OUTPUT
# (иначе цепочку не удалить), потом очистить и удалить саму цепочку. В режиме шлюза
# добавляется ещё и переход из FORWARD. То же самое для IPv6 — engage() программирует
# обе таблицы, и без ip6tables-части v6-трафик останется заблокированным.
#
# Точное имя цепочки клиент печатает в лог при включении kill-switch; ниже пример для
# `dev = vpn0`.
CH=QELI_KS_vpn0
sudo iptables  -D OUTPUT  -j $CH 2>/dev/null; true
sudo iptables  -D FORWARD -j $CH 2>/dev/null; true
sudo iptables  -F $CH            2>/dev/null; true
sudo iptables  -X $CH            2>/dev/null; true
sudo ip6tables -D OUTPUT  -j $CH 2>/dev/null; true
sudo ip6tables -D FORWARD -j $CH 2>/dev/null; true
sudo ip6tables -F $CH            2>/dev/null; true
sudo ip6tables -X $CH            2>/dev/null; true

# Exit-узел / шлюз (если был exit_node = true или gateway_nat = true). Эти правила тоже
# снимаются только на ЧИСТОЙ остановке, а краш их оставляет — и тогда хост продолжает
# маскарадить и форвардить уже после того, как туннель умер. Каждое правило помечено
# комментарием: qeli-exit-node (exit_node) или qeli-gw-nat (gateway_nat) — по нему и ищем.
sudo iptables -t mangle -S | grep -e qeli-exit-node -e qeli-gw-nat
sudo iptables -t nat    -S | grep -e qeli-exit-node -e qeli-gw-nat
sudo iptables           -S | grep -e qeli-exit-node -e qeli-gw-nat
# Удалять построчно: в найденной строке заменить -A на -D и выполнить как есть, например:
#   sudo iptables -t nat -D POSTROUTING -o eth0 -m mark --mark 0x51/0x51 -j MASQUERADE \
#        -m comment --comment qeli-exit-node
# ip_forward и rp_filter клиент менял на лету — вернуть, если они были выключены:
#   sudo sysctl -w net.ipv4.ip_forward=0
#   sudo sysctl -w net.ipv4.conf.eth0.rp_filter=1        # eth0 = ваш WAN

sudo ip link del vpn0 2>/dev/null; true        # tun — имя из `dev = …`
# Удалить бинарь, конфиг, состояние:
sudo rm -f /usr/local/bin/qeli
rm -f ~/qeli-client.conf                        # ваш путь к клиентскому конфигу
sudo rm -rf /var/lib/qeli                       # device-id + dns-backup

Никогда не снимайте kill-switch через iptables -F. Без имени цепочки эта команда очищает всю таблицу filter — вместе с правилами SSH, ufw/fail2ban, Docker и всем, что настроил администратор. qeli держит свои правила в собственной цепочке QELI_KS_<интерфейс> именно для того, чтобы её можно было снять точечно. При включении клиент печатает в лог снятие перехода из OUTPUT; в режиме шлюза дополнительно уберите переход из FORWARD и ip6tables-копии — как в примере выше.

На совмещённом хосте (сервер + клиент рядом) /var/lib/qeli общий — не удаляйте его, пока не снесли сервер.

13.3. Десктоп — Windows / macOS (GUI)

  • Windows: закрыть приложение → удалить QeliWin (папку portable-сборки или через «Приложения и возможности»). Wintun-адаптер эфемерный — создаётся и удаляется на каждый сеанс, после «Отключить» в системе не остаётся; маршруты/DNS восстанавливаются там же. Данные (профили / настройки / device-id) — удалить папки: %AppData%\QeliWin, %LocalAppData%\qeli, %ProgramData%\QeliWin.
  • macOS: закрыть → удалить QeliMac.app. utun управляется ядром — исчезает при отключении. Данные — удалить ~/.local/share/qeli; если включали автозапуск — снять LaunchAgent из ~/Library/LaunchAgents (файл с qeli в имени).

13.4. Android

Настройки → Приложения → qeli → Удалить. Сносит всё: профили (в шифрованном хранилище), device-id, виджет, QS-плитку, автозапуск на буте. Для полной чистоты — отозвать VPN-согласие и выключить Always-on VPN (если включали): Настройки → Сеть/Подключения → VPN → qeli.

13.5. Роутеры

OpenWrt:

/etc/init.d/qeli stop; /etc/init.d/qeli disable
opkg remove luci-app-qeli qeli
rm -f /etc/config/qeli /etc/init.d/qeli /usr/bin/qeli-client
# удалить firewall-зону qeli, которую создавал uci-default при установке:
sec=$(uci show firewall | awk -F. "/\.name='qeli'/{print \$2; exit}")
[ -n "$sec" ] && uci delete firewall.$sec && uci commit firewall && /etc/init.d/firewall restart

Keenetic: остановить и удалить init-скрипт, бинарь и конфиг — обратно шагам установки (см. docs/*/KEENETIC-DEPLOY.md).

13.6. Docker

docker compose -f release/docker/docker-compose.yml down      # остановить и снести контейнер
# (-v тут бесполезен: в compose нет именованных volume, только bind-mount ./data —
#  данные удаляет команда rm -rf ./data ниже)
docker rmi qeli:latest                                        # образ
rm -rf ./data                                                 # смонтированный /etc/qeli (конфиги + ключи)

Нашли неточность или есть вопрос по настройке — заводите issue/discussion в репозитории. Полная карта документации — в README.