Домашний компьютер за NAT может сам достучаться до VPS и оставить дверь открытой только для вас. Собираем туннель, который переживает обрывы, смену IP и перезагрузки, и выводим через него рабочий стол. Читать далее
Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели9.1K
Туториал
Белого 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Шаг 1. SSH‑доступ с домашнего компьютера на VPS по ключу⚠ Если на VPS есть фаервол (ufw, nftables, панель хостера) — откройте в нём
443/tcpдо перезапуска. Если на VPS включена сокет‑активация SSH (ssh.socket), порт задаётся в ней, а не вsshd_config. И помните: 443 не «маскирует» SSH подHTTPS — DPIопределяет протокол по рукопожатию, а не по номеру порта. Порт выбран просто потому, что он почти везде открыт.
Домашний компьютер должен подключаться к 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Шаг 3. Держим туннель живым: autossh⚠ Важный нюанс. По умолчанию reverse‑туннель слушает только 127.0.0.1 на VPS. Это правильно и безопасно: порт доступен только с самого VPS, а не из интернета. GatewayPorts yes не включаем.
Обычный 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.
Создаём /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. Это то, что нужно.
Создаём /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. Подключаемся из любой точкиВариант А: одна команда через ProxyJumpssh умеет сам «прыгать» через промежуточный сервер. На компьютере, с которого подключаетесь:
ssh -J root@203.0.113.10:443 -p 44443 -L 5900:localhost:5900 vasvs@localhostssh зайдёт на 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:5900HostKeyAlias нужен, чтобы ключ домашнего компьютера не записался в 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.
Схема рабочая, но 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 есть в большинстве репозиториев.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Как я переносил работающую Windows-ВМ с Hyper-V на Proxmox, не выключая исходную машину | 0 | 9.98 | 22-09-2026 |
| 2 | Как найти лишние процессы, открытые порты и подозрительные соединения на VDS | 0 | 8.18 | 24-09-2026 |
| 3 | Консоль починки сети по аудиокабелю: когда SSH уже бесполезен | 0 | 8.26 | 01-10-2026 |
| 4 | Как я перенаправил Claude Desktop и Claude Code на свой VPS с CLIProxyAPI | 0 | 5.88 | 05-10-2026 |
| 5 | Следуй за белым кроликом: пишем VPN на Rust и ищем выход из собственного туннеля | 0 | 7.12 | 01-10-2026 |
| 6 | Показываем одно окно Windows на планшете через обычный браузер | 0 | 8.8 | 30-09-2026 |
| 7 | Чем заменить top, ps и netstat в 2026 году, и когда их лучше не трогать | 0 | 9.77 | 17-09-2026 |
| 8 | Пивотинг в аду легаси: MIPS-сервер, BusyBox и ядро 2014 года | 0 | 23.68 | 29-09-2026 |
| 9 | [Перевод] Telegram Desktop под атакой прокси: деанонимизация, утечка секретов и RCE с правами SYSTEM | 0 | 8.98 | 24-09-2026 |
| 10 | CanvasDesk: от замены рабочего стола до визуального математического моделирования | 0 | 8.26 | 30-09-2026 |