***
Предпосылки
На сервере (Debian 12, от root, один раз):
# /etc/ssh/sshd_config
PermitTunnel point-to-point
# опционально, но полезно
AllowTcpForwarding yes
Перезапуск:
systemctl restart ssh
***
Скрипт: клиент + сервер
Сохрани, например, как ssh-vpn.sh на КЛИЕНТЕ (Manjaro), сделай chmod +x ssh-vpn.sh и запускай от root (sudo ./ssh-vpn.sh up / down). [git.sr](https://git.sr.ht/~greenfoo/vpn_over_ssh)
#!/usr/bin/env bash
# Простой TUN‑VPN поверх SSH: client <-> VPS
# режим: ./ssh-vpn.sh up | ./ssh-vpn.sh down
set -e
### НАСТРОЙКИ ###
SERVER_HOST="vps.example.com" # IP/дomen VPS
SERVER_USER="root" # юзер на сервере (нужен root/cap_net_admin)
SSH_PORT=22
TUN_ID=0 # tunX на обеих сторонах
CLI_TUN_IP="10.10.10.2" # IP клиента в VPN
SRV_TUN_IP="10.10.10.1" # IP сервера в VPN
VPN_NET="10.10.10.0/24" # сеть VPN (для NAT)
SRV_WAN_IF="eth0" # внешний интерфейс сервера (замени!)
SSH_OPTS="-p ${SSH_PORT} -o ServerAliveInterval=60 -o ServerAliveCountMax=3"
### ФУНКЦИИ ###
up_client_cfg() {
# addr/route на клиенте
ip addr add "${CLI_TUN_IP}/32" peer "${SRV_TUN_IP}" dev "tun${TUN_ID}" || true
ip link set "tun${TUN_ID}" up
# сохранить старый default (для down)
ip route show default > /run/ssh-vpn.old_default 2>/dev/null || true
# новый default через VPN
ip route replace default via "${SRV_TUN_IP}" dev "tun${TUN_ID}"
}
down_client_cfg() {
# вернуть старый default (если сохраняли)
if [ -s /run/ssh-vpn.old_default ]; then
# тупой restore: удалить текущий default и вернуть старый
ip route del default || true
while read -r line; do
ip route add $line || true
done < /run/ssh-vpn.old_default
rm -f /run/ssh-vpn.old_default
fi
ip link set "tun${TUN_ID}" down || true
ip addr del "${CLI_TUN_IP}/32" peer "${SRV_TUN_IP}" dev "tun${TUN_ID}" 2>/dev/null || true
}
up_server_cfg() {
ssh ${SSH_OPTS} "${SERVER_USER}@${SERVER_HOST}" bash -s <<EOF
set -e
ip addr add "${SRV_TUN_IP}/32" peer "${CLI_TUN_IP}" dev "tun${TUN_ID}" || true
ip link set "tun${TUN_ID}" up
# включаем форвардинг
sysctl -w net.ipv4.ip_forward=1 >/dev/null
# NAT для VPN‑сети через внешний интерфейс
iptables -t nat -C POSTROUTING -s "${VPN_NET}" -o "${SRV_WAN_IF}" -j MASQUERADE 2>/dev/null \
|| iptables -t nat -A POSTROUTING -s "${VPN_NET}" -o "${SRV_WAN_IF}" -j MASQUERADE
EOF
}
down_server_cfg() {
ssh ${SSH_OPTS} "${SERVER_USER}@${SERVER_HOST}" bash -s <<EOF
set -e
ip link set "tun${TUN_ID}" down || true
ip addr del "${SRV_TUN_IP}/32" peer "${CLI_TUN_IP}" dev "tun${TUN_ID}" 2>/dev/null || true
iptables -t nat -D POSTROUTING -s "${VPN_NET}" -o "${SRV_WAN_IF}" -j MASQUERADE 2>/dev/null || true
EOF
}
start_ssh_tunnel() {
# поднимаем SSH‑туннель с TUN с обеих сторон
# -f отправляет ssh в фон, -w TUN_ID:TUN_ID создаёт tunX на обеих концах
ssh ${SSH_OPTS} -f -w "${TUN_ID}:${TUN_ID}" "${SERVER_USER}@${SERVER_HOST}" \
"sleep 999999" # просто держим сессию живой
}
stop_ssh_tunnel() {
# глушим все ssh с -w к этому хосту (грубо, но просто)
pkill -f "ssh .* -w ${TUN_ID}:${TUN_ID} .*${SERVER_HOST}" 2>/dev/null || true
}
### MAIN ###
case "$1" in
up)
echo "[*] Старт SSH‑VPN..."
start_ssh_tunnel
sleep 1
up_server_cfg
up_client_cfg
echo "[+] VPN поднят. Проверка: ping ${SRV_TUN_IP}"
;;
down)
echo "[*] Остановка SSH‑VPN..."
down_client_cfg
down_server_cfg
stop_ssh_tunnel
echo "[+] VPN остановлен."
;;
*)
echo "Usage: $0 {up|down}"
exit 1
;;
esac
***
Пояснения по ключевым местам
PermitTunnel point-to-pointвsshd_configразрешает создавать TUN‑интерфейсы черезssh -w. [backreference](https://backreference.org/2009/11/13/openssh-based-vpns/index.html)ssh -w "${TUN_ID}:${TUN_ID}"создаётtun${TUN_ID}на клиенте и на сервере, по ним пойдут IP‑пакеты. [gist.github](https://gist.github.com/tjunussov/284cc843c88a670e6bb9cb325370b7c9)ip addr add CLI_TUN_IP/32 peer SRV_TUN_IPделает p2p‑линк (точка‑точка) между двумя TUN‑концами. [std](https://std.rocks/vpn_ssh.html)iptables -t nat -A POSTROUTING -s VPN_NET -o SRV_WAN_IF -j MASQUERADEдаёт клиенту выход в интернет с адреса сервера (как в классическом VPN). [perplexity](https://www.perplexity.ai/search/1a2d4421-64e9-4381-90a4-5aa2c63e6bd0)ip route replace default via SRV_TUN_IP dev tunXделает VPN дефолтным маршрутом на клиенте. [debian-fr](https://www.debian-fr.org/t/jai-cree-un-vpn-avec-ssh-et-interface-tun-mais-que-peut-on-faire-avec/91153)
############################
Через SSH можно наколбасить несколько разных «VPN‑подобных» схем — от полного TUN/TAP до «бедняцкого VPN» без root. [ssh](https://www.ssh.com/academy/ssh/tunneling)
1. L3 TUN‑VPN (то, что уже обсудили)
ssh -w+tun(IP point‑to‑point, L3). [github](https://github.com/openssh/openssh-portable/blob/master/README.tun)- Даёт
tunXна клиенте и сервере, маршруты, NAT на сервере, default route на клиенте — классический IP‑VPN. [backreference](https://backreference.org/2009/11/13/openssh-based-vpns/index.html) - Можно автоматизировать через
Tunnel point-to-point/TunnelDeviceв~/.ssh/config. [backreference](https://backreference.org/tag/tun/index.html)
2. L2 TAP/bridge через SSH
- Вместо TUN можно использовать TAP/bridge, если ОС позволяет (tap‑dev, Ethernet‑кадры). [github](https://github.com/openssh/openssh-portable/blob/master/README.tun)
- Схема:
tapXна обеих сторонах, на одной стороне TAP бриджится с физическим Ethernet, получается почти «одна L2‑сеть» через SSH. [backreference](https://backreference.org/2009/11/13/openssh-based-vpns/index.html) - Удобно, если нужно прокинуть DHCP, multicast, любые не‑IP протоколы, но оверхед больше и сложнее настройка.
3. sshuttle / transparent proxy «poor man’s VPN»
- Инструмент
sshuttleделает прозрачный VPN‑like туннель поверх обычного SSH, безtunX. [linuxconfig](https://linuxconfig.org/sshuttle-a-vpn-like-tool-for-secure-traffic-routing) - Пример:
sshuttle -r user@server 0/0 --dns
Всё TCP (и DNS) гонится через SSH; root нужен только локально, на сервере достаточно обычного SSH‑доступа. [github](https://github.com/sshuttle/sshuttle)
- Плюсы: минимум конфигурации, обход многих DPI/файрволов; минусы: только TCP/частично UDP, завязка на iptables/iptables‑подобные хаки. [linuxconfig](https://linuxconfig.org/sshuttle-a-vpn-like-tool-for-secure-traffic-routing)
4. Полный трафик через динамический SOCKS (ssh -D + tun2socks)
ssh -Dподнимает SOCKS5, дальшеtun2socks/redsocksделают TUN‑интерфейс и гонят его трафик через SOCKS. [github](https://github.com/sshuttle/sshuttle)- По сути:
ssh -D 1080 user@servertun2socks --tundev tun0 --net 10.0.0.0/24 --socks-server 127.0.0.1:1080- default route через
tun0. - Это обходной путь, когда
PermitTunnelна сервере нельзя трогать, но SSH+TCP открыт.
5. Простой порт‑форвардинг как частичный VPN
- Локальный, удалённый и динамический форвардинг:
ssh -L— проброс нужных портов (RDP, HTTP, БД и т.п.) в приватную сеть. [linuxize](https://linuxize.com/post/how-to-setup-ssh-tunneling/)ssh -R— дать удалённой стороне доступ назад в твою сеть по выбранному порту. [ssh](https://www.ssh.com/academy/ssh/tunneling)ssh -D— SOCKS‑прокси, который можно использовать как VPN только для приложений, умеющих SOCKS. [linuxize](https://linuxize.com/post/how-to-setup-ssh-tunneling/)- Это не полный VPN, но покрывает 80% задач типа «достучаться до внутренней услуги» или «прячем только браузер».
6. OpenVPN/WireGuard поверх SSH‑туннеля
- Если DPI гнобит OpenVPN/WG, можно завернуть их в SSH:
ssh -L 1194:real-vpn-server:1194 user@gatewayи на клиенте OpenVPN/WG подключается к127.0.0.1:1194. [backreference](https://backreference.org/tag/tunnel/index.html)- Так SSH работает как «обфускация/транспорт» для нормального VPN, а управление маршрутами — на самом OpenVPN/WG.
7. Многоскачковый VPN через SSH ProxyCommand
ProxyCommand/ProxyJumpпозволяют строить цепочки: клиент → bastion → dmz → vpn‑gw, и уже там поднимается TUN или sshuttle. [backreference](https://backreference.org/tag/tunnel/index.html)- Пример: в
~/.ssh/configописываетсяHost gwсProxyCommand ssh bastion nc gw 22, и TUN/sshuttle используют этот хост как конечный. [github](https://github.com/openssh/openssh-portable/blob/master/README.tun)
[file-name 000352_2026-03-01_13-44-05.txt]