Skip to content

Latest commit

 

History

History
470 lines (380 loc) · 30.5 KB

VPN.md

File metadata and controls

470 lines (380 loc) · 30.5 KB

Режим VPN (ssh_tunnel_vpn.exe, ssh_tunnel_vpn_linux)

Обычные ssh_tunnel.exe и ssh_tunnel_linux — это прокси: они работают только с теми программами, которые умеют ходить через прокси (браузеры, curl, npm и т.д.). Программы, которые про прокси не знают (часть игр, клиенты Docker, самописные утилиты), идут мимо туннеля.

Версии с режимом VPN работают как настоящий VPN: создают в системе виртуальную сетевую карту, и весь трафик компьютера идёт через неё — а дальше через тот же SSH до твоего сервера. Настраивать отдельные программы не нужно.

Со стороны провайдера разницы нет: и там и там он видит одно зашифрованное SSH-соединение с сервером.

Чем приходится платить

  • Права администратора (на Linux — root). Создавать сетевые адаптеры и менять маршруты система разрешает только им. На Windows без службы окно UAC появляется при каждом запуске; со службой (галочка «Запускать при старте системы», см. ниже) — один раз, при её установке. На Linux запускать надо через sudo. Из-за этого режим VPN — отдельные файлы: обычные версии остаются без повышенных прав.
  • Размер. Внутри exe сетевой стек (gvisor) и драйвер Wintun — файл больше обычного.
  • Одновременно запускается что-то одно — обычная версия или VPN. Настройки и серверы у них общие (на Linux под sudo берутся из домашней папки того, кто запустил).

Как это устроено

  любая программа
        │  обычные IP-пакеты
        ▼
  адаптер «ssh_tunnel» (Wintun)       маршруты 0.0.0.0/1 и 128.0.0.0/1
        │
        ▼
  сетевой стек gvisor                 пакеты → снова TCP-соединения
        │
        ▼
  ядро туннеля (то же, что у прокси)  правила, журнал, пул SSH
        │  SSH
        ▼
    твой сервер
  • Адаптер — драйвер Wintun от авторов WireGuard. Он вшит в exe и при первом включении кладётся в папку настроек (%APPDATA%\ssh_tunnel\wintun).
  • Маршруты. Весь интернет — двумя половинками (0.0.0.0/1 и 128.0.0.0/1), а не одним маршрутом по умолчанию: так наши маршруты всегда точнее маршрута настоящей сети. Своя локальная подсеть (роутер, принтер) точнее ещё и продолжает идти напрямую.
  • Петля. Соединение с сервером и прямые соединения «мимо туннеля» программа открывает сама — и они тоже попали бы в адаптер. Поэтому каждый её сокет привязывается к настоящей сетевой карте (IP_UNICAST_IF). Сменилась сеть (Wi-Fi → кабель) — привязка меняется и пул переподключается сам.
  • DNS. Адаптер объявляет свой DNS-сервер 198.18.0.53 — его обслуживает программа. На имя отдаётся подставной адрес из 198.18.128.0/17, а настоящее имя разрешает сервер в момент соединения — как в прокси-режиме и на Android. Имена из «всегда напрямую» и локальной сети разрешаются по-настоящему, через DNS настоящей сети.
  • Защита от утечки DNS. Windows рассылает DNS-запросы через все сетевые карты сразу. Чтобы провайдер не видел запросов и не подсовывал заглушки, ставятся фильтры брандмауэра Windows (WFP): DNS разрешён только через наш адаптер и самой программе. Фильтры живут в «динамической» сессии — если программа упадёт, Windows снимет их сама, и интернет не пропадёт.
  • Правила по программам работают так же, как в прокси-режиме: владелец соединения виден по порту.
  • UDP (звонки, игры, QUIC) — через ретранслятор на сервере, если он установлен и включён в настройках сервера. Иначе UDP отбрасывается, и браузеры сами переходят с QUIC на TCP.

Обход блокировок и сеть устройств — по отдельности

На главном экране две кнопки:

  • большая — обход блокировок: весь трафик идёт через сервер;
  • маленькая «Сеть устройств» (видна, когда у сервера включена сеть устройств) — адреса 198.19.x.y и имена .mesh, RDP и всё остальное между твоими устройствами.

Обе едут по одному SSH-соединению, но включаются и выключаются отдельно. Выключил обход — сайты идут напрямую, а сеть устройств работает: адаптер остаётся, но в нём только подсеть 198.18.0.0/15 (сеть устройств и наш DNS), маршрутов всего интернета, DNS через VPN и запрета DNS мимо адаптера больше нет. Переключение идёт на живом адаптере — открытые RDP-сессии не рвутся. Туннель гаснет целиком, только когда выключены обе кнопки.

Имена .mesh без обхода блокировок разрешаются правилом NRPT (таблица политик разрешения имён Windows: «зону .mesh спрашивай у 198.18.0.53»), как у Tailscale и NetBird. На Linux то же делает systemd-resolved доменом ~mesh; без resolved в этом режиме устройства доступны по адресам.

В прокси-версии выключенный обход снимает системный прокси, а туннель остаётся ради сети устройств: к этому компьютеру можно подключаться с других устройств, а сам он ходит к ним через SOCKS/HTTP-прокси программы.

Автозапуск на Windows — служба

Галочка «Запускать при старте системы» в VPN-версии ставит службу Windows — программу, которую система запускает сама при включении компьютера, ещё до входа в учётную запись. Так устроены NetBird и Tailscale, и даёт это то же самое: включил компьютер удалённо — он висит на экране ввода пароля, а VPN и сеть устройств уже работают, к нему можно подключиться по RDP.

  при включении компьютера                     при входе пользователя
  ┌──────────────────────────────┐             ┌───────────────────────────┐
  │ служба ssh_tunnel_vpn        │  127.0.0.1  │ окно ssh_tunnel VPN (трей)│
  │ (SYSTEM): туннель, адаптер,  │◄────────────│ без прав администратора   │
  │ сеть устройств, веб-интерфейс│ service.json│                           │
  └──────────────────────────────┘             └───────────────────────────┘
  • Установка. Галочка → окно UAC один раз. Программа копирует себя в C:\Program Files\ssh_tunnel\ssh_tunnel_vpn.exe (служба работает от имени SYSTEM, и её файл не должен лежать там, где его может подменить обычная программа) и ставит службу ssh_tunnel_vpn: автоматический запуск, перезапуск при сбое через 5/10/30 секунд. «Подключаться сразу при запуске» включается само — ради этого служба и ставится.
  • Настройки — те же, что у окна (%APPDATA%\ssh_tunnel): служба получает папки пользователя параметрами -profile и -appdata. Драйвер Wintun служба кладёт в Program Files, а не в папку пользователя.
  • Сети при включении может ещё не быть — служба ждёт её сколько угодно и подключается, как только она появится. Окно без службы ждёт три минуты.
  • Окно — обычная программа без прав администратора, в автозагрузке пользователя (HKCU\...\Run, с ключом -tray — сразу значком в трее). Адрес и ключ веб-интерфейса службы оно берёт из service.json в папке настроек (туда может заглянуть только сам пользователь, администраторы и SYSTEM) и показывает его через свой маленький прокси: перезапуск службы открытое окно не ломает. «Выход» в трее закрывает только окно — VPN продолжает работать.
  • Журнал службы — %APPDATA%\ssh_tunnel\service.log.
  • Обновление. Запусти файл новой версии — он увидит, что служба работает на старой, и предложит обновить её (окно UAC). Если окно программы уже открыто, сначала выйди из него через трей.
  • Выключение. Сними галочку → окно UAC → служба удаляется, окно перезапускается в обычном режиме (ядро в процессе окна, UAC при каждом запуске). Файл в Program Files остаётся, его можно удалить руками.
  • Обычный ssh_tunnel.exe, запущенный при работающей службе, открывает окно VPN-версии: второй туннель поверх первого только мешал бы.
  • Автозапуск прежних версий (запись в реестре, задача Планировщика) при первом запуске новой переносится на службу сам. Ярлык в папке «Автозагрузка», положенный руками, надо удалить.

Руками: ssh_tunnel_vpn.exe -install-service / -uninstall-service (от имени администратора), состояние — sc query ssh_tunnel_vpn.

Linux

Файл ssh_tunnel_vpn_linux — то же, что ssh_tunnel_linux, но через сервер идёт весь трафик машины, а не только программы с настройкой прокси, и сама машина ходит к устройствам сети по именам .mesh (ssh, ping, RDP-клиенты — что угодно). Цена — права root: создавать сетевое устройство и менять маршруты ядро разрешает только ему. Поэтому:

  • запускать — через sudo (настройки при этом остаются в твоей домашней папке, ~/.config/ssh_tunnel, общие с обычной версией);
  • автозапуск — системной службой, командами ниже. Галочка «Запускать при старте системы» в панели рассчитана на обычную версию и для VPN не годится.

Учти: торренты, игры и другие VPN на этой машине (WireGuard, NetBird) ходят по UDP — через SSH он не проходит, без ретранслятора UDP на сервере они перестанут работать. Домашняя сеть (192.168.x.x) и Docker остаются как были.

Нужен только доступ к этой машине с других устройств (её порты, SSH, панели), а её собственный интернет пусть идёт напрямую? Тогда хватит обычной версии — LINUX_SETUP.md.

Как это выглядит

  1. Скачать и запустить программу — блок под свою систему ниже.
  2. Добавить сервер в панели — как в программе на Windows (см. «Добавить сервер» ниже). Адрес VPS в командах не нужен.
  3. Включить автозапуск — общий блок в конце.

Команды под свою систему

Блоки работают и под обычным пользователем (через sudo), и под root, где sudo нет. На Proxmox открывай его собственный блок — там есть важные отличия.

Ubuntu · Debian · Linux Mint · Raspberry Pi OS
S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S apt update && $S apt install -y curl

# скачать (на Raspberry Pi и других ARM возьмётся сборка _arm64) и поставить
F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
$S install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

# запустить с панелью: http://АДРЕС_ЭТОЙ_МАШИНЫ:47821 (Ctrl+C — выключить)
$S ssh_tunnel_vpn_linux -web -web-lan

DNS: в Ubuntu работает systemd-resolved — программа настроит его сама. В Debian без resolved на время работы подменяется /etc/resolv.conf и потом возвращается как было.

Если включён ufw и панель нужна с других устройств домашней сети:

S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S ufw allow from 192.168.0.0/16 to any port 47821 proto tcp
Proxmox VE

Proxmox — это Debian, но работают там под root, поэтому sudo не нужен, а настройки лежат в /root/.config/ssh_tunnel/.

apt update && apt install -y curl

F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

# запустить с панелью: http://АДРЕС_ХОСТА:47821 (Ctrl+C — выключить)
ssh_tunnel_vpn_linux -web -web-lan

Важно для Proxmox:

  • На самом хосте VPN заворачивает весь интернет хоста — в том числе скачивание обновлений и шаблонов. Виртуальные машины и контейнеры ходят через свой мост (vmbr0) и VPN хоста не затрагиваются. Если хосту нужна только сеть устройств (доступ к веб-панели Proxmox с других устройств по имя.mesh:8006), поставь обычную версию — LINUX_SETUP.md.

  • В LXC-контейнере по умолчанию нет устройства TUN, без него VPN не запустится. Разреши его на хосте (номер контейнера вместо 101) и перезапусти контейнер:

    printf '%s\n' 'lxc.cgroup2.devices.allow: c 10:200 rwm' \
      'lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file' >> /etc/pve/lxc/101.conf
    pct reboot 101
  • Firewall Proxmox (Datacenter → Firewall), если включён: порт 47821 разрешается там, в веб-интерфейсе Proxmox, — ufw в нём не участвует.

Fedora · RHEL · CentOS Stream · Rocky · AlmaLinux
S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S dnf install -y curl

F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
$S install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

# запустить с панелью: http://АДРЕС_ЭТОЙ_МАШИНЫ:47821 (Ctrl+C — выключить)
$S ssh_tunnel_vpn_linux -web -web-lan

Firewall здесь firewalld; если панель нужна с других устройств:

S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S firewall-cmd --permanent --add-port=47821/tcp && $S firewall-cmd --reload
Arch · Manjaro · EndeavourOS
S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S pacman -S --needed curl

F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
$S install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

# запустить с панелью: http://АДРЕС_ЭТОЙ_МАШИНЫ:47821 (Ctrl+C — выключить)
$S ssh_tunnel_vpn_linux -web -web-lan

Firewall по умолчанию не стоит; если поставил свой — порт 47821 открывай в нём.

openSUSE
S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S zypper install -y curl

F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
$S install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

# запустить с панелью: http://АДРЕС_ЭТОЙ_МАШИНЫ:47821 (Ctrl+C — выключить)
$S ssh_tunnel_vpn_linux -web -web-lan

Порт панели — через firewalld, как в Fedora:

S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox и т.п.) sudo не нужен
$S firewall-cmd --permanent --add-port=47821/tcp && $S firewall-cmd --reload
Alpine Linux

Здесь нет systemd (вместо него OpenRC), поэтому общий блок автозапуска ниже не подходит — служба заводится прямо здесь. Работают под root.

apk add curl
modprobe tun   # устройство TUN; на большинстве ядер уже есть

F=ssh_tunnel_vpn_linux; [ "$(uname -m)" = aarch64 ] && F=${F}_arm64
curl -fL -o /tmp/ssh_tunnel_vpn_linux https://github.com/VITAZGIO/ssh_tunel/releases/latest/download/$F
install -m 755 /tmp/ssh_tunnel_vpn_linux /usr/local/bin/ssh_tunnel_vpn_linux && rm -f /tmp/ssh_tunnel_vpn_linux

cat > /etc/init.d/ssh_tunnel_vpn <<'EOF'
#!/sbin/openrc-run
command="/usr/local/bin/ssh_tunnel_vpn_linux"
command_args="-web -web-lan"
command_background=true
pidfile="/run/ssh_tunnel_vpn.pid"
depend() { need net; }
EOF
chmod +x /etc/init.d/ssh_tunnel_vpn
rc-update add ssh_tunnel_vpn default
rc-service ssh_tunnel_vpn start

DNS без systemd-resolved: на время работы подменяется /etc/resolv.conf и потом возвращается как было.

Добавить сервер

Сервер здесь — твой VPS, тот же, что в программе на Windows, а не роутер. Удобнее всего перенести его вместе с ключом:

  1. В программе на компьютере: настройки своего сервера → «Экспорт» (с ключом) — получится файл.
  2. Открой панель этой машины (http://АДРЕС_ЭТОЙ_МАШИНЫ:47821) с любого устройства в домашней сети → «Импорт» → этот файл → «Подключить». Вместе с сервером приезжают SSH-ключ и ключ сети устройств: машина сразу появляется в сети как имя-машины.mesh.
  3. Файл экспорта удали — он равносилен паролю от сервера.

Можно и вписать руками в той же панели: адрес VPS, пользователь, путь к ключу — как в первый раз на Windows.

Автозапуск при включении машины

Для всех систем с systemd (всё, кроме Alpine). Выполни тем же пользователем, которым запускал программу через sudo: служба возьмёт настройки (и добавленный сервер) из его домашней папки. Окно с ручным запуском перед этим закрой (Ctrl+C). Блок годится и для обновления — просто вставь его снова после установки нового файла.

S=sudo; [ "$(id -u)" = 0 ] && S=   # под root (Proxmox) sudo не нужен — его там и нет
printf '%s\n' '[Unit]' 'Description=ssh_tunnel VPN' \
  'After=network-online.target systemd-resolved.service' 'Wants=network-online.target' '' \
  '[Service]' "Environment=XDG_CONFIG_HOME=$HOME/.config" \
  'ExecStart=/usr/local/bin/ssh_tunnel_vpn_linux -web -web-lan' \
  'Restart=always' 'RestartSec=5' 'TimeoutStopSec=15' '' \
  '[Install]' 'WantedBy=multi-user.target' | $S tee /etc/systemd/system/ssh_tunnel_vpn.service >/dev/null
$S systemctl daemon-reload
$S systemctl enable ssh_tunnel_vpn
$S systemctl restart ssh_tunnel_vpn

sleep 3
systemctl is-active ssh_tunnel_vpn
echo "Панель: http://$(hostname -I | awk '{print $1}'):47821"

В конце — active и адрес панели. Она открыта только для домашней сети (-web-lan), из интернета к ней не попасть. Чтобы VPN подключался сам, в панели должна стоять галочка «Подключаться сразу при запуске» (включена по умолчанию). Журнал службы — journalctl -u ssh_tunnel_vpn -f.

Обычную версию (ssh_tunnel.service) одновременно с VPN не запускай — хватит одной: sudo systemctl disable --now ssh_tunnel, а если она стояла как пользовательская — systemctl --user disable --now ssh_tunnel.

Удалить всё
sudo systemctl disable --now ssh_tunnel_vpn
sudo rm -f /etc/systemd/system/ssh_tunnel_vpn.service /usr/local/bin/ssh_tunnel_vpn_linux
sudo systemctl daemon-reload

Настройки (~/.config/ssh_tunnel) остаются — они общие с обычной версией. На Alpine: rc-service ssh_tunnel_vpn stop; rc-update del ssh_tunnel_vpn; rm -f /etc/init.d/ssh_tunnel_vpn /usr/local/bin/ssh_tunnel_vpn_linux.

Как устроено

Устроено так же, как на Windows, со своими средствами системы:

  • адаптер — устройство TUN sshtun0, адреса и маршруты задаются через netlink (интерфейс ядра для настройки сети);
  • свои сокеты привязываются к настоящей сети через SO_BINDTODEVICE;
  • DNS: если работает systemd-resolved — нашему интерфейсу ставится DNS 198.18.0.53 и домен ~. (все запросы идут только туда); исчезнет интерфейс — resolved забудет настройку сам. Без resolved подменяется /etc/resolv.conf, прежний сохраняется в папку настроек и возвращается при выключении или при следующем запуске, если программа упала;
  • служба systemd — packaging/linux/ssh_tunnel_vpn.service.

Маршруты и защита от петли проверяются тестом на настоящем ядре: он запускается в отдельном сетевом пространстве имён и сеть машины не трогает (go test ./vpnlayer/ под root).

Сборка

Нужен Go 1.26 (для сетевого стека), curl и unzip:

cd vpn
./build.sh      # скачает Wintun, сверит сумму, соберёт exe и файлы для Linux в ../releases

На GitHub то же делает workflow vpn на каждый пуш — готовые файлы лежат в артефактах запуска.

Что проверить руками (Windows)

Сетевой адаптер, маршруты, UAC и фильтры брандмауэра Windows в тестах не проверить — только на живой системе.

  1. Запуск: окно UAC, затем обычное окно программы с заголовком «ssh_tunnel VPN».
  2. «Подключить» → в «Сетевых подключениях» появился адаптер ssh_tunnel.
  3. https://2ip.ru (или любая проверка IP) показывает адрес сервера — в браузере без настроенного прокси.
  4. Программа, не знающая про прокси (например, curl без флагов в cmd, git), тоже ходит через сервер.
  5. Роутер (192.168.x.1) открывается — локальная сеть идёт напрямую.
  6. Выключение Wi-Fi и включение обратно (или переключение на кабель) — через несколько секунд всё снова работает, без переподключения руками.
  7. «Отключить» — адаптер исчезает, интернет работает как обычно.
  8. Утечки DNS: https://browserleaks.com/dns — должны быть только DNS-серверы со стороны твоего сервера, не провайдерские.
  9. Закрыть программу через диспетчер задач («Снять задачу») — интернет после этого должен работать сам, без перезагрузки.
  10. Галочка «Запускать при старте системы» → окно UAC → в services.msc служба «ssh_tunnel VPN» (автоматически, выполняется), окно перезапустилось без прав администратора. Перезагрузить компьютер и не входить в систему: с другого устройства сети ping имя.mesh и RDP на него работают.
  11. Вход в систему — значок в трее, без окна UAC; окно показывает состояние службы. «Выход» в трее — VPN продолжает работать.
  12. Большая кнопка при включённой сети устройств: сайты идут напрямую (2ip.ru — свой адрес), а ping имя.mesh и открытая RDP-сессия живут. Маленькая кнопка выключает сеть, большая снова включает обход.
  13. Снять галочку → окно UAC → служба удалена, программа перезапустилась в обычном режиме.