SSH – это не только shell на сервере. Через OpenSSH можно пробросить TCP-порты, поднять SOCKS-прокси и даже layer-3 туннель (TUN). Команды ниже одинаковы по смыслу на Linux, macOS и FreeBSD: клиент – ssh, сервер – sshd. Различия в основном в перезапуске службы и синтаксисе ip/ifconfig.
Что значит «инкапсуляция» здесь
Трафик приложения едет внутри уже зашифрованной SSH-сессии. Снаружи виден обмен с портом SSH (обычно 22), содержимое портов и SOCKS – нет. Это удобно для доступа к внутренним сервисам, обхода «только исходящий 22» и ad-hoc VPN без отдельного демона.
- шифрование канала OpenSSH;
- доступ к хостам, видимым только с jump/SSH-сервера;
- минимум инфраструктуры: достаточно рабочего
sshd.
Три типа проброса портов
Локальный (-L)
На вашей машине слушается порт; соединения уходят на SSH-сервер и с него – на целевой host:port (часто во внутренней сети).
ssh -L [локальный_порт]:[удалённый_хост]:[удалённый_порт] user@ssh.example.com # пример: internal.example.com:80 → localhost:8080 ssh -L 8080:internal.example.com:80 user@ssh.example.com
В браузере: http://127.0.0.1:8080. Цель резолвится и доступна со стороны SSH-сервера, не обязательно с вашего ноутбука.
Удалённый (-R)
На SSH-сервере открывается порт; трафик с сервера приходит на host:port у вас (или за вами).
ssh -R [порт_на_сервере]:[цель_хост]:[цель_порт] user@ssh.example.com # локальный MySQL → порт 3306 на сервере (только localhost сервера по умолчанию) ssh -R 3306:localhost:3306 user@ssh.example.com
Чтобы слушать не только 127.0.0.1 на сервере, в sshd_config нужно GatewayPorts (осторожно с экспозицией). Для «выставить локальный сервис наружу» чаще смотрят reverse tunnel + firewall, а не открытый 0.0.0.0 без нужды.
Динамический (-D, SOCKS)
Локальный SOCKS-прокси: приложения сами указывают, куда идти, а SSH ходит к целям от имени сервера.
ssh -D 1080 user@ssh.example.com
В браузере или системе: SOCKS5, host 127.0.0.1, порт 1080. Для CLI часто ALL_PROXY=socks5h://127.0.0.1:1080 или proxychains – зависит от инструмента.
Примеры сценариев
OpenSSH-флаги на Linux, macOS и FreeBSD одни и те же. Меняются только пути логов и менеджер служб.
- HTTPS-сервис за бастионом:
ssh -L 8443:remote.service.com:443 user@ssh.example.com, затемhttps://127.0.0.1:8443; - отдать локальный веб на сервер:
ssh -R 8080:localhost:8080 user@ssh.example.com; - временный SOCKS «весь браузер через VPS»:
ssh -D 1080 user@vps; - SMTP relay через bastion:
ssh -L 2525:mail.example.com:25 user@ssh.example.com.
Полезные опции: -N (без shell, только туннель), -f (в фон после auth), -C (сжатие, иногда помогает на тексте). Для фона надолго удобнее autossh или unit systemd, а не «забытый» -f.
Jump-host (-J)
Цепочка: ваш ПК → bastion → целевой хост без ручного double-ssh:
ssh -J user@jump-host user@destination-host
Несколько прыжков – через запятую. В ~/.ssh/config то же через ProxyJump.
X11 forwarding
Запуск GUI-приложения с удалённого хоста (нужен X-сервер на клиенте; на macOS – отдельный XQuartz и т.п.):
ssh -X user@ssh.example.com # или -Y (trusted), если -X режет нужные расширения
На сервере в sshd_config:
X11Forwarding yes
Для постоянной удалённой работы удобнее VNC/RDP/Waypipe, чем тяжёлый X11 через SSH.
Layer-3: TUN через SSH (-w)
Режим «почти VPN»: point-to-point через устройства tun. Нужны root на клиенте, поддержка TUN, на сервере – PermitTunnel yes. Это не полноценная замена WireGuard/OpenVPN (NAT, MTU, устойчивость, маршруты – вручную).
Сервер
# /etc/ssh/sshd_config PermitTunnel yes # Linux (systemd): sudo systemctl restart sshd # FreeBSD: sudo service sshd restart
Клиент: сессия с tun
sudo ssh -w 0:0 user@ssh.example.com
-w 0:0 – пара номеров tun на клиенте и сервере (tun0/tun0). Сессия должна оставаться открытой; адреса и маршруты задают отдельно (часто вторым терминалом или скриптом после подъёма интерфейса).
Адреса на tun
Сервер (Linux; на macOS синтаксис ip может отличаться, часто используют ifconfig):
sudo ip addr add 10.0.0.1/24 dev tun0 sudo ip link set tun0 up
Клиент:
sudo ip addr add 10.0.0.2/24 dev tun0 sudo ip link set tun0 up
FreeBSD (пример point-to-point):
# сервер sudo ifconfig tun0 10.0.0.1 10.0.0.2 netmask 255.255.255.0 up # клиент sudo ifconfig tun0 10.0.0.2 10.0.0.1 netmask 255.255.255.0 up
Маршруты
Гнать default через туннель (осторожно: можно потерять маршрут к самому SSH-серверу, если не оставить host-route):
# Linux: лучше сначала host-route до ssh.example.com через старый gateway sudo ip route add default via 10.0.0.1 dev tun0 # FreeBSD sudo route add default 10.0.0.1
На сервере для выхода клиентов в интернет нужны IP forwarding и NAT (nftables/iptables). Без этого «пинг 8.8.8.8» с клиента не заработает, даже если tun up.
UDP через SSH
Проброс портов SSH – TCP. UDP иногда «протаскивают» через socat/аналоги, оборачивая в поток внутри SSH. Схема хрупкая; для DNS/VPN-подобных задач надёжнее WireGuard или отдельный VPN.
Практика: устойчивость и безопасность
- ключи вместо пароля:
ssh-keygen -t ed25519(или RSA 4096, если политика требует); - ограничения в
sshd_config:AllowUsers, отключение root-пароля, по возможности fail2ban/гео; - keep-alive, чтобы NAT не рвал idle-туннель:
# в ~/.ssh/config для Host * ServerAliveInterval 60 ServerAliveCountMax 3
- не открывайте
-Rна 0.0.0.0 без firewall и понимания, кто достучится; - логи: Linux часто
/var/log/auth.logили journald; FreeBSD –/var/log/auth.log/ security.
Типичные сбои
- порт уже занят локально – смените левую часть
-L/-D; -Rне слушает снаружи –GatewayPortsи firewall на сервере;- TUN: «device busy» / нет
tun0– другой номер-w, права root,PermitTunnel; - маршруты:
ip route/netstat -rn, host-route до bastion до смены default.
Краткий чеклист
- нужен один порт/сервис –
-Lили-R; - нужен «весь браузер/куча хостов» –
-D; - нужен IP-туннель – WireGuard предпочтительнее; SSH
-w– запасной вариант; - ключи, keep-alive, минимальные открытые порты, понятные маршруты.
Итог: локальный, удалённый и динамический проброс закрывают большую часть задач «достучаться до сервиса через bastion». TUN и трюки с UDP – ниша; для постоянной сети лучше профильный VPN.
