Белого IP нет, роутер провайдерский, а домашний компьютер нужен прямо сейчас: забытый файл, зависшая сборка, открытая вкладка. Отдавать доступ стороннему сервису не хочется. Решение известное: пусть домашний компьютер сам подключается к VPS и держит туннель, через который мы попадём обратно.
В статье соберём такой туннель так, чтобы он переживал обрывы и перезагрузки (autossh + systemd), пустим через него полноценный рабочий стол (VNC) и сведём подключение к одной команде ssh home. Отдельно разберём грабли, из‑за которых туннель «вроде работает», а на деле нет.
Вводная: что и зачем
Итак, у нас есть:
Домашний компьютер (Debian 13) за NAT провайдера, без белого IP. Хотим получить к нему доступ из любой точки мира — в том числе к графическому рабочему столу.
VPS (Debian 13) с публичным IP. Он будет «точкой встречи»: домашний компьютер сам к нему подключится, а мы будем заходить на VPS и через него попадать дальше.
Схема:
[Вы] ──ssh :443──▶ [VPS] ◀──ssh :443 (исходящее)── [Дом] 127.0.0.1:44443 ══ туннель ══▶ :22 дома VNC: localhost:5900 у вас ══ внутри SSH ══▶ 127.0.0.1:5900 дома
Ключевая идея: домашний компьютер сам инициирует соединение с VPS. Поэтому:
не нужен белый IP и проброс портов у провайдера;
не нужно трогать настройки роутера;
фаервол провайдера не мешает — исходящие соединения обычно разрешены.
Конструкцию сделаем отказоустойчивой: если туннель оборвётся (сменился IP, упал провайдер, перезагрузился VPS), он поднимется сам. VNC при этом не будет торчать в интернет — он доступен только через SSH.
Что нам понадобится
На VPS (Debian 13):
публичный IP (в примерах — 203.0.113.10, адрес из документационного диапазона);
SSH‑сервер на порту 443 — этот порт почти везде открыт на выход, даже в гостиничных и корпоративных сетях;
пользователь для подключения. Для простоты начнём с root, а в разделе о безопасности заменим его на отдельных пользователей.
На домашнем компьютере (Debian 13):
utossh— для автоматического переподключения туннеля;x11vnc— для доступа к текущему рабочему столу;SSH‑клиент и SSH‑сервер (клиент в Debian есть по умолчанию, сервер нужно поставить);
графический сеанс X11, а не Wayland. В Debian 13 GNOME по умолчанию запускается на Wayland, а x11vnc с ним не работает — будет чёрный экран. Выберите «GNOME on Xorg» на экране входа или пропишите WaylandEnable=false в /etc/gdm3/daemon.conf. Если хотите остаться на Wayland — смотрите в сторону встроенного в GNOME удалённого рабочего стола (RDP), wayvnc для wlroots‑окружений или krfb для KDE; туннельная часть статьи от этого не меняется.
Устанавливаем пакеты:
# Домашний компьютер sudo apt update sudo apt install autossh x11vnc openssh-server # VPS sudo apt update sudo apt install openssh-server
Шаг 0. Готовим SSH‑сервер на VPS
Переносим SSH на порт 443 и сразу учим сервер быстро замечать мёртвые подключения. В /etc/ssh/sshd_config на VPS:
Port 443 ClientAliveInterval 30 ClientAliveCountMax 3
Зачем ClientAlive*: когда связь с домом рвётся, старый процесс sshd на VPS ещё долго не знает об этом и продолжает держать порт 44443. Новое подключение из дома не может занять порт, падает, перезапускается — и так несколько минут, пока старая сессия не умрёт по таймауту. С этими настройками VPS сам закроет мёртвую сессию примерно через полторы минуты.
Применяем, не закрывая текущую SSH‑сессию, и проверяем вход на новый порт из второго окна:
sudo systemctl restart ssh ssh -p 443 root@203.0.113.10
⚠ Если на VPS есть фаервол (ufw, nftables, панель хостера) — откройте в нём
443/tcpдо перезапуска. Если на VPS включена сокет‑активация SSH (ssh.socket), порт задаётся в ней, а не вsshd_config. И помните: 443 не «маскирует» SSH подHTTPS — DPIопределяет протокол по рукопожатию, а не по номеру порта. Порт выбран просто потому, что он почти везде открыт.
Шаг 1. SSH‑доступ с домашнего компьютера на VPS по ключу
Домашний компьютер должен подключаться к VPS без пароля, иначе при каждом переподключении туннель будет ждать ввода, и вся автоматика теряет смысл.
Генерируем ключ на домашнем компьютере (если его ещё нет):
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" Копируем публичный ключ на VPS и проверяем, что пускает без пароля: ssh-copy-id -p 443 root@203.0.113.10 ssh -p 443 root@203.0.113.10
Заодно этот вход добавит ключ VPS в ~/.ssh/known_hosts — без этого сервис в шаге 4 не сможет подключиться.
Шаг 2. Проверяем reverse‑туннель вручную
Прежде чем городить systemd, убедимся, что туннель вообще работает. На домашнем компьютере:
ssh -p 443 -R 44443:localhost:22 root@203.0.113.10
Оставляем окно открытым. На VPS в другом окне смотрим, слушается ли порт:
sudo ss -tlnp | grep 44443
Ожидаем что‑то вроде:
LISTEN 0 128 127.0.0.1:44443 0.0.0.0:* users:(("sshd",pid=...,fd=...))
Порт появился — туннель работает. Теперь с VPS можно зайти на домашний компьютер (vasvs — ваш пользователь дома):
ssh -p 44443 vasvs@localhost
⚠ Важный нюанс. По умолчанию reverse‑туннель слушает только 127.0.0.1 на VPS. Это правильно и безопасно: порт доступен только с самого VPS, а не из интернета. GatewayPorts yes не включаем.
Шаг 3. Держим туннель живым: autossh
Обычный SSH‑туннель падает при первой же сетевой икоте. autossh запускает ssh и перезапускает его, если тот завершился:
autossh -M 0 -N \ -o ServerAliveInterval=30 \ -o ServerAliveCountMax=3 \ -o ExitOnForwardFailure=yes \ -p 443 \ -R 44443:localhost:22 \ root@203.0.113.10
Разберём флаги:
-M 0— отключаем встроенный мониторинг autossh (он использует отдельные порты и часто упирается в фаерволы). Живость соединения проверяет сам ssh.-N— не выполнять команды на удалённой стороне, только туннель.ServerAliveInterval=30— каждые 30 секунд ssh отправляет keepalive.ServerAliveCountMax=3— три keepalive подряд без ответа, и соединение считается мёртвым: ssh завершается, autossh поднимает новое.ExitOnForwardFailure=yes— если ssh не смог занять порт 44 443 на VPS, соединение сразу закрывается. Без этого флага можно получить «тихий» туннель: ssh подключён, а порта на VPS нет. Эта мелочь экономит пару вечеров отладки.-p 443— порт SSH на VPS.-R 44443:localhost:22— собственно reverse‑туннель.
Честная оговорка: с ‑M 0 под systemd autossh почти ничего не добавляет — перезапуск умеет и сам systemd (Restart=always), а проверку живости делает ssh. Можно смело заменить /usr/bin/autossh -M 0 на /usr/bin/ssh в unit‑файле ниже, всё будет работать так же. autossh удобен, когда туннель запускается руками или из cron, без systemd.
Шаг 4. Оформляем туннель как systemd‑сервис
Создаём /etc/systemd/system/reverse-ssh.service:
[Unit] Description=Reverse SSH Tunnel to VPS After=network-online.target Wants=network-online.target [Service] User=vasvs Environment=AUTOSSH_GATETIME=0 ExecStart=/usr/bin/autossh -M 0 -N \ -o ServerAliveInterval=30 \ -o ServerAliveCountMax=3 \ -o ExitOnForwardFailure=yes \ -o BatchMode=yes \ -p 443 \ -R 44443:localhost:22 \ root@203.0.113.10 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
Пояснения:
User=vasvs— сервис работает от вашего пользователя, потому что ключ и known_hosts лежат в его ~/.ssh. От root ключ не найдётся.After= и Wants=network-online.target— стартуем, когда сеть действительно поднялась, а не только интерфейс.AUTOSSH_GATETIME=0— без этого autossh завершается, если самое первое подключение не удалось (например, VPS ещё недоступен при загрузке).BatchMode=yes — sshникогда не станет ждать пароль или подтверждение ключа хоста: либо подключился, либо ошибка в журнале.Restart=always и RestartSec=10— перезапуск в любом случае, с паузой 10 секунд.
Активируем и проверяем:
sudo systemctl daemon-reload sudo systemctl enable --now reverse-ssh.service sudo systemctl status reverse-ssh.service
Должно быть active (running). На VPS снова проверяем sudo ss ‑tlnp | grep 44 443 — если порт слушается, туннель работает и переживёт перезагрузку.
Шаг 5. VNC: полный рабочий стол
SSH‑доступ есть, теперь графика. Задаём пароль VNC на домашнем компьютере:
x11vnc -storepasswd
Пароль сохранится в ~/.vnc/passwd. Это пароль именно на VNC, не путайте с паролем пользователя. Учтите, что VNC использует только первые 8 символов — основная защита здесь всё равно SSH.
Проверяем вручную, находясь в графическом сеансе:
x11vnc -forever -shared -localhost -rfbauth ~/.vnc/passwd -display :0
Флаги:
-forever— не выходить после отключения клиента;-shared— разрешить нескольким клиентам подключаться одновременно;-localhost— принимать соединения только с localhost. Критично для безопасности: VNC не должен быть доступен снаружи, ходим к нему только через SSH;-rfbauth— файл с паролем;-display :0— какой X‑дисплей показывать. Номер может отличаться: проверьте echo $DISPLAY в терминале графического сеанса.
Во втором терминале убеждаемся, что VNC слушает только localhost:
ss -tlnp | grep 5900
Должно быть 127.0.0.1:5900. Это то, что нужно.
Шаг 6. Автозапуск x11vnc
Создаём /etc/systemd/system/x11vnc.service:
[Unit] Description=x11vnc server for reverse SSH access After=display-manager.service Wants=display-manager.service [Service] Type=simple User=vasvs ExecStart=/usr/bin/x11vnc -forever -shared -localhost \ -rfbauth /home/vasvs/.vnc/passwd -find Restart=always RestartSec=5 [Install] WantedBy=graphical.target
Вместо жёсткого -display :0 здесь -find: x11vnc сам найдёт X‑дисплей пользователя и нужный файл авторизации, а если сеанса ещё нет — подождёт. Это важно, потому что GDM после входа часто поднимает сеанс пользователя не на :0, а на :1.
Сервис показывает ваш рабочий стол, то есть начинает работать после входа в графический сеанс. Если компьютер после перезагрузки стоит на экране входа, до рабочего стола вы не доберётесь — но SSH будет доступен. Проще всего включить автовход в настройках GDM (и блокировку экрана — чтобы дома рабочий стол не стоял открытым).
sudo systemctl daemon-reload sudo systemctl enable --now x11vnc.service sudo systemctl status x11vnc.service
Теперь и туннель, и VNC поднимаются автоматически.
Шаг 7. Подключаемся из любой точки
Вариант А: одна команда через ProxyJump
ssh умеет сам «прыгать» через промежуточный сервер. На компьютере, с которого подключаетесь:
ssh -J root@203.0.113.10:443 -p 44443 -L 5900:localhost:5900 vasvs@localhost
ssh зайдёт на VPS и уже оттуда подключится к localhost:44443 — то есть в reverse‑туннель. localhost здесь относится к VPS, а не к вашей машине. Одна команда — два прыжка.
Чтобы не набирать это каждый раз, добавим в ~/.ssh/config:
Host vps HostName 203.0.113.10 Port 443 User root Host home HostName localhost Port 44443 User vasvs ProxyJump vps HostKeyAlias home-desktop LocalForward 5900 localhost:5900
HostKeyAlias нужен, чтобы ключ домашнего компьютера не записался в known_hosts под безликим [localhost]:44443 и не конфликтовал с другими туннелями.
Теперь подключение выглядит так:
ssh home # терминал домашнего компьютера + проброс VNC vncviewer localhost:5900 # во втором окне — рабочий стол
Если локально порт 5900 занят, возьмите другой: LocalForward 5901 localhost:5900 и vncviewer localhost:5901.
Вариант Б: два прыжка вручную (чтобы понять, как это работает)
На своём компьютере заходим на VPS и пробрасываем локальный 5900 на 5900 VPS:
ssh -p 443 -L 5900:localhost:5900 root@203.0.113.10
В этом же сеансе, уже на VPS, заходим домой и пробрасываем 5900 VPS на 5900 домашнего компьютера:
ssh -p 44443 -L 5900:localhost:5900 vasvs@localhost
Получилась цепочка: ваш localhost:5900 → VPS:5900 → дом:5900. Во втором терминале запускаем vncviewer localhost:5900, вводим пароль VNC — и видим рабочий стол. Вариант А делает то же самое, но короче и без открытого порта 5900 на VPS.
Шаг 8. Безопасность
Схема рабочая, но root на VPS мы использовали только для простоты. Приведём её в порядок. Делайте изменения по одному и держите открытой рабочую SSH‑сессию, пока не проверите новый вход.
1. Отдельный пользователь для туннеля. На VPS:
sudo adduser --disabled-password --gecos "" tunnel sudo install -d -m 700 -o tunnel -g tunnel /home/tunnel/.ssh
В /home/tunnel/.ssh/authorized_keys кладём публичный ключ домашнего компьютера (~/.ssh/id_ed25519.pub) с ограничениями:
restrict,port-forwarding,permitlisten="44443" ssh-ed25519 AAAA... home
Этот ключ сможет только открыть reverse-туннель на порт 44443: ни shell, ни команд, ни других портов. Не забудьте sudo chown tunnel:tunnel и chmod 600 на файл. В reverse-ssh.service меняем root@... на tunnel@....
2. Отдельный пользователь для себя. Туннельный пользователь не умеет ничего, кроме туннеля, поэтому для входа на VPS заведите обычного пользователя с ключом вашего ноутбука и замените им root в блоке Host vps в ~/.ssh/config.
3. Закрываем root и пароли. Когда вход под своим пользователем проверен, в /etc/ssh/sshd_config на VPS:
PermitRootLogin no PasswordAuthentication no
И sudo systemctl restart ssh.
4. fail2ban. Ставим sudo apt install fail2ban, но учтите две вещи: стандартный jail банит на порту 22, а в Debian нет /var/log/auth.log по умолчанию. Создаём /etc/fail2ban/jail.local:
[sshd] enabled = true port = 443 backend = systemd
и перезапускаем: sudo systemctl restart fail2ban.
5. VNC — только через SSH. Флаг -localhost у x11vnc гарантирует, что VNC недоступен напрямую. Не убирайте его.
6. Обновления. И на VPS, и дома: sudo apt update && sudo apt upgrade. На VPS удобно включить unattended-upgrades.
Диагностика: что может пойти не так
Порт 44 443 на VPS не слушается. Смотрим сервис на домашнем компьютере:
sudo systemctl status reverse-ssh sudo journalctl -u reverse-ssh -f
В журнале будет точная причина. Частые варианты:
ключ не скопирован на VPS или лежит не у того пользователя — с
BatchMode=yesбудетPermission denied;ключ VPS не в
known_hostsпользователяvasvs — Host key verification failed, зайдите на VPS руками один раз;порт
44443на VPS занят —remote port forwarding failed;фаервол на VPS не пропускает
443/tcp;в команде не тот порт SSH (
-p 443против-p 22).
Туннель после обрыва несколько минут не поднимается, в журнале remote port forwarding failed. Порт держит старая «мёртвая» сессия на VPS. Проверьте ClientAliveInterval и ClientAliveCountMax из шага 0.
VNC показывает чёрный экран. Почти всегда это Wayland — проверьте echo $XDG_SESSION_TYPE в графическом сеансе, там должно быть x11. Второй вариант — x11vnc подключился не к тому дисплею: посмотрите who и echo $DISPLAY и journalctl ‑u x11vnc.
VNC‑клиент не подключается к localhost:5900. Проверьте, что:
SSH‑сессия с
-L(илиssh home) открыта;порядок аргументов именно такой:
-L локальный_порт:хост:удалённый_порт;на домашнем компьютере
x11vncдействительно слушает127.0.0.1:5900 (ss -tlnp | grep 5900).
Туннель живёт, но отваливается через несколько минут простоя. Где‑то по пути есть idle-timeout. ServerAliveInterval=30 обычно решает проблему; если нет — уменьшите до 15 секунд.
Итог
Что мы получили:
домашний Debian 13 сам поднимает reverse SSH‑туннель на VPS и держит его живым благодаря autossh и systemd;
VPS быстро закрывает мёртвые сессии, так что туннель восстанавливается за секунды, а не за минуты;
x11vnc показывает рабочий стол, но слушает только localhost — снаружи он недоступен;
из любой точки мира
ssh homeоткрывает терминал домашнего компьютера и проброс к его рабочему столу;всё переживает перезагрузки, смену IP и кратковременные обрывы сети.
Схема не претендует на корпоративный уровень, но для личного использования подходит отлично. Все компоненты стандартные, из репозиториев Debian.
Если хочется совсем без ручной возни — посмотрите в сторону Tailscale или ZeroTier. Но если хочется понимать, что происходит под капотом, и не зависеть от сторонних сервисов, reverse SSH и systemd остаются классикой, которая работает годами.
P. S. Если дома не Debian 13, отличия минимальны: замените apt на свой пакетный менеджер, пути к systemd‑юнитам останутся прежними. x11vnc есть в большинстве репозиториев.

