***

Предпосылки

На сервере (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

***

Пояснения по ключевым местам

############################

Через SSH можно наколбасить несколько разных «VPN‑подобных» схем — от полного TUN/TAP до «бедняцкого VPN» без root. [ssh](https://www.ssh.com/academy/ssh/tunneling)

1. L3 TUN‑VPN (то, что уже обсудили)

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 -r user@server 0/0 --dns

Всё TCP (и DNS) гонится через SSH; root нужен только локально, на сервере достаточно обычного SSH‑доступа. [github](https://github.com/sshuttle/sshuttle)

4. Полный трафик через динамический SOCKS (ssh -D + tun2socks)

  • ssh -D поднимает SOCKS5, дальше tun2socks/redsocks делают TUN‑интерфейс и гонят его трафик через SOCKS. [github](https://github.com/sshuttle/sshuttle)
  • По сути:
  • ssh -D 1080 user@server
  • tun2socks --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

[file-name 000352_2026-03-01_13-44-05.txt]