comvir
comvir
901 просмотров0 комментариев

Резервный ip-тоннель через ssh

Существует неиллюзорная вероятность, когда неожиданно или даже внезапно могут перестать работать защищенные подключения между центральным vpn-cервером и удалёнными точками. Даже при условии что и vpn-концентратор и vpn-абоненты находятся на территории России. Бодание между вашей тех. службой с одной стороны, тех. службой вашего оператора интернет с другой и госрегулятором может затянуться на несколько дней. И на всё это время связь с удалёнными точками будет отсутствовать.

OpenSSH вполне можно назвать “мультитулом сетевого администратора”, через него при необходимости можно довольно быстро: пробрасывать tcp-порты (ssh -L, ssh -R); организовать защищённое socks5 прокси подключение (ssh -D); безопасно передавать файлы (sftp). Администраторы частенько пользуются этими возможностями. Но помимо вышеперечисленного, в OpenSSH есть опция позволяющего организовать тоннель через системные tun/tap интерфейсы. Это-то нам и поможет оперативно восстановить связь с удалёнными точками, пока недоступно основное VPN-подключение.

И так, для создания резервного защищенного канала связи нам понадобится:

  • Репка - 1 или более штук;
  • Актуальная прошивка - 1 версия;
  • Актуальный пакет openssh-server;
  • Актуальный пакет openssh;
  • Актуальный пакет bird2 или аналогичный, при необходимости (в рамках этой статьи настройка протоколов динамической маршрутизации рассматриваться не будет);
  • Сетевой администратор :)

Начальную установку и настройку репки пропускаем. В статьях на сайте тема раскрыта чуть более, чем полностью. Переходим к теме повествования. Для начала создадим пользователя sshtun, ssh-ключи(без пароля) и т.п. как на клиентской части(репка), так и на серверной(другая репка):

# adduser sshtun
# sudo -u sshtun bash
$ ssh-keygen -t ecdsa -b 521

Публичный ключ с клиентской части нужно добавить в файл ~/.ssh/authorized_keys для пользователя sshtun и проверить что файл доступен на запись и чтение только владельцу. Проверяем с клиентской части, что ssh подключение работает (вместо 1X.2X.3X.4X - реальный IP адрес, по которому будет осуществляться ssh подключение):

# echo "1X.2X.3X.4X  server.vps" >> /etc/hosts
# sudo -u sshtun bash
$ ssh server.vps

Далее на серверной части создаём файл /etc/ssh/sshd_config.d/tunnel.conf:

Match User sshtun
  PermitTunnel yes
  PasswordAuthentication no

Не забываем перезапустить службу ssh. Следующий шаг для серверной части - добавить и активировать службу которая будет однократно запускать скрипт который будет создавать и настраивать tun интерфейс(-ы).

Файл скрипта /usr/local/bin/sshtun.sh:

#!/bin/bash

if [ "$1" = "repka-pi" ] && [ "repka-pi$(/usr/bin/ip tuntap | grep tun0)" = "repka-pi" ] && [ "$2" = "add" ];
  then
    /usr/bin/ip tuntap add mode tun user sshtun tun0
    /usr/bin/ip addr add 10.22.0.10/31 dev tun0
    /usr/bin/ip addr add fc22::10/127 dev tun0
    /usr/bin/ip link set tun0 mtu 1400
    /usr/bin/ip link set tun0 up
fi

if [ "$1" = "repka-pi" ] && [ "repka-pi$(/usr/bin/ip tuntap | grep tun0)" != "repka-pi" ] && [ "$2" = "del" ];
  then
    /usr/bin/ip tuntap del mode tun tun0
fi

Файл службы /etc/systemd/system/sshtun-add@.service:

[Unit]
Description=SSH Tunnel add device for %i
Wants=network-online.target ssh.service
Requires=ssh.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/sshtun.sh %i add

[Install]
WantedBy=multi-user.target

Файл службы /etc/systemd/system/sshtun-del@.service:

[Unit]
Description=SSH Tunnel del device for %i
Wants=network-online.target ssh.service
Requires=ssh.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/sshtun.sh %i del

[Install]
WantedBy=multi-user.target

Активируем и запускаем службу:

# systemctl daemon-reload
# systemctl enable sshtun-add@repka-pi
# systemctl start sshtun-add@repka-pi
# ip addr show dev tun0

На этом этапе настройка серверной части завершена, возвращаемся на клиентскую часть и донастраиваем её. Файлы служб для добавления/удаления системного tun-интерфейса такие-же как и на серверной части, а в остальном (скрипт и конфигурация по части ssh) есть отличия.

Файл клиентского скрипта /usr/local/bin/sshtun.sh:

#!/bin/bash

if [ "$1" = "server.vps" ] && [ "server.vps$(/usr/bin/ip tuntap | grep tun0)" = "server.vps" ] && [ "$2" = "add" ];
  then
    /usr/bin/ip tuntap add mode tun user sshtun tun0
    /usr/bin/ip addr add 10.22.0.11/31 dev tun0
    /usr/bin/ip addr add fc22::11/127 dev tun0
    /usr/bin/ip link set tun0 mtu 1400
    /usr/bin/ip link set tun0 up
fi

if [ "$1" = "server.vps" ] && [ "server.vps$(/usr/bin/ip tuntap | grep tun0)" != "server.vps" ] && [ "$2" = "del" ];
  then
    /usr/bin/ip tuntap del mode tun tun0
fi

Создаём файл /etc/ssh/ssh_config.d/server.vps.conf (если на сервере используется нестандартный порт ssh, то он задаётся в этом файле через опцию Port):

Host server.vps
  Port 12592
  TCPKeepAlive Yes
  ServerAliveInterval 120
  Match User sshtun
    Tunnel Yes
    TunnelDevice 0:0

Файл службы /etc/systemd/system/sshtun@.service:

[Unit]
Description=SSH Tunnel to %i
Wants=network-online.target ssh.service
After=sshtun-add@%i.service
Requires=ssh.service

[Service]
User=sshtun
Type=Exec
ExecStart=/usr/bin/ssh -N %i
Restart=always
RestartSec=15s

[Install]
WantedBy=multi-user.target

Осталось активировать и запустить службы на клиентской части:

# systemctl daemon-reload
# systemctl enable sshtun-add@server.vps
# systemctl start sshtun-add@server.vps
# systemctl enable sshtun@server.vps
# systemctl start sshtun@server.vps
# ip addr show dev tun0

Далее, если на сети используются протоколы динамической маршрутизации из пакета bird2 или аналогичного, то новые интерфейсы нужно добавить в конфигурационные файлы со значениями cost хуже, чем на основном vpn-соединении. Тогда при восстановлении основной схемы работы трафик автоматически переключится на нёё. А подключение через ssh останется в горячем резерве.

Ну и напоследок проверим что тоннель заработал:

# ps ax | grep server.vps
   1556 ?        Ss     0:00 /usr/bin/ssh -N server.vps

# ping -c 5 fc22::10
PING fc22::10(fc22::10) 56 data bytes
64 bytes from fc22::10: icmp_seq=1 ttl=64 time=36.5 ms
64 bytes from fc22::10: icmp_seq=2 ttl=64 time=35.1 ms
64 bytes from fc22::10: icmp_seq=3 ttl=64 time=33.6 ms
64 bytes from fc22::10: icmp_seq=4 ttl=64 time=35.5 ms
64 bytes from fc22::10: icmp_seq=5 ttl=64 time=33.5 ms

--- fc22::10 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 33.491/34.834/36.486/1.156 ms

# ping -c 5 fc22::11
PING fc22::11(fc22::11) 56 data bytes
64 bytes from fc22::11: icmp_seq=1 ttl=64 time=0.243 ms
64 bytes from fc22::11: icmp_seq=2 ttl=64 time=0.366 ms
64 bytes from fc22::11: icmp_seq=3 ttl=64 time=0.378 ms
64 bytes from fc22::11: icmp_seq=4 ttl=64 time=0.284 ms
64 bytes from fc22::11: icmp_seq=5 ttl=64 time=0.342 ms

--- fc22::11 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4097ms
rtt min/avg/max/mdev = 0.243/0.322/0.378/0.051 ms

# ping -c 5 10.22.0.10
PING 10.22.0.10 (10.22.0.10) 56(84) bytes of data.
64 bytes from 10.22.0.10: icmp_seq=1 ttl=64 time=33.3 ms
64 bytes from 10.22.0.10: icmp_seq=2 ttl=64 time=33.3 ms
64 bytes from 10.22.0.10: icmp_seq=3 ttl=64 time=35.6 ms
64 bytes from 10.22.0.10: icmp_seq=4 ttl=64 time=33.6 ms
64 bytes from 10.22.0.10: icmp_seq=5 ttl=64 time=35.6 ms

--- 10.22.0.10 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4007ms
rtt min/avg/max/mdev = 33.256/34.266/35.621/1.106 ms

# ping -c 5 10.22.0.11
PING 10.22.0.11 (10.22.0.11) 56(84) bytes of data.
64 bytes from 10.22.0.11: icmp_seq=1 ttl=64 time=0.187 ms
64 bytes from 10.22.0.11: icmp_seq=2 ttl=64 time=0.222 ms
64 bytes from 10.22.0.11: icmp_seq=3 ttl=64 time=0.143 ms
64 bytes from 10.22.0.11: icmp_seq=4 ttl=64 time=0.246 ms
64 bytes from 10.22.0.11: icmp_seq=5 ttl=64 time=0.325 ms

--- 10.22.0.11 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4092ms
rtt min/avg/max/mdev = 0.143/0.224/0.325/0.061 ms

Комментарии (0)

Для участия в обсуждении вы должны быть авторизованным пользователем

Навигация

ВойтиРегистрацияТемы