Существует неиллюзорная вероятность, когда неожиданно или даже внезапно могут перестать работать защищенные подключения между центральным 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