p2p туннель средствами ssh

Тунель - способ установления безопасного соединения между двумя конечными точками в сети (Point - to - Point или p2p).

Суть туннелирования:

    • зашифровать исходный трафик (в том числе информацию о получателе и отправителе);
    • передать его на сервер, используя незащищенную сеть;
    • произвести расшифровку;
Point-to-Point тунель
    • отправить данные адресату.

С точки зрения операционной системы это выглядит следующим образом:

    1. Клиент устанавливает ssh подключение к серверу;
    2. Сервер авторизует Клиента;
    3. Клиент и Сервер создают виртуальные устройства (TUN) в операционной системе и назначают им ip адреса локальной и удаленной стороны.

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

Сценарии использования

Главное преимущество ssh перед другими средствами организации туннелей - его распространенность. В каждом linux дистрибутиве он включен в стандартную поставку. Среди основных сценариев можно выделить следующие:

    • Объединение дата-центров;
    • Организация подключения с удаленной локальной сетью;
    • Организация подключения с удаленным сервером.

Все эти сценарии, с точки зрения настройки, очень схожи. В данном примере будет рассмотрен процесс организации подключения с удаленным сервером.

Конфигурация систем

Параметры конфигурации компьютеров, между которыми будет произведено подключение:

Клиент:

IP адрес: 192.168.1.50  Маска сети: 255.255.255.0  Таблица маршрутизации: Destination   Gateway        Genmask        Flags Metric Ref Use Iface    192.168.1.0   0.0.0.0        255.255.255.0  U     1      0   0   eth0 169.254.0.0   0.0.0.0        255.255.0.0    U     1000   0   0   eth0 0.0.0.0       192.168.1.100  0.0.0.0        UG    0      0   0   eth0

Сервер:

IP адрес: 81.28.170.12  Маска сети: 255.255.192.0  Таблица маршрутизации: Destination   Gateway        Genmask        Flags Metric Ref Use Iface    81.28.170.0   0.0.0.0        255.255.255.0  U     1      0   0   eth0 169.254.0.0   0.0.0.0        255.255.0.0    U     1000   0   0   eth0 0.0.0.0       81.28.170.100  0.0.0.20        UG    0      0   0   eth0

169.254.0.0 — zeroconf маршрут.

Настройка сервера

Открывать root доступ, даже при условии запрета авторизации по паролю, очень опасно. В случае компрометации ключа (или пароля), злоумышленник получит полный доступ к вашему серверу. Поэтому необходимо создать пользователя с ограниченными правами доступа и сгенерировать для него ключ удаленной авторизации. Таким образом, даже в случае компрометации ключа, контроль над сервером не будет утрачен и урон будет значительно меньшим.

# Добавляем пользователя vpn root@server:/# useradd -mU vpn# Создаем папку .ssh, в которой ssh будет искать публичную часть ключа root@server:/# mkdir /home/vpn/.ssh# Генерируем ключ root@server:/# ssh-keygen -t rsa -b 2048 Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): /home/vpn/.ssh/vpn-17012 Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/vpn/.ssh/vpn-17012. Your public key has been saved in /home/vpn/.ssh/vpn-17012.pub. The key fingerprint is: d3:dc:72:21:c9:7e:58:5b:46:38:e7:a7:3a:06:73:0d root@server The key's randomart image is: +--[ RSA 2048]----+ |             ..  | |         . .o..  | |          + o+o  | |         + =E=. .| |        S * =o o | |         .o+. o  | |           + .   | |            +    | |           . .   | +-----------------+ # Добавляем публичную часть ключа в список разрешенных к авторизации root@server:/# cat /home/vpn/.ssh/vpn-17012.pub >> /home/vpn/.ssh/authorized_keys# Копируем приватную часть ключа в /tmp/ root@server:/# cp /home/vpn/.ssh/vpn-17012 /tmp/ root@server:/#

*Для удобства при генерации ключа используется имя пользователя и часть ip адреса или доменного имени сервера.

**Файл <user home>/.ssh/authorized_keys - стандартное место хранения публичной части ключа, используемого при авторизации.

***Последняя команда (cp /home/vpn/.ssh/vpn-17012 /tmp/) копирует приватную часть ключа в папку /tmp, чтобы позднее его можно было скопировать на клиента.

Теперь, когда пользователь создан, необходимо заранее создать TUN устройство, которое будет доступно для чтения и записи пользователю vpn (создание любого устройства /dev/* требует наличия прав администратора). Для этого необходимо создать systemd netdev и network файлы.

Создайте файл /etc/systemd/system/network/30-vpn-17012.netdev со следующим содержанием:

[NetDev]Name=tun0Kind=tun[Tun]Group=vpn

и файл /etc/systemd/network/30-vpn-17012.network:

[Match]Name=tun0[Address]Address=172.17.0.1/30Peer=172.17.0.2/30[Network]Address=172.17.0.1/30[Route]Gateway=172.17.0.1Destination=192.168.1.0/24

С помощью этих двух файлов сервис systemd-networkd сконфигурирует:

    • TUNTAP устройство /dev/tun0 в режиме TUN;
    • Разрешит доступ к нему пользователям, состоящим в группе vpn;
    • Назначит ip адрес интерфейсу и добавит маршрут для подсети клиента (секция Route).

Чтобы изменения вступили в силу, перезапустите сервис systemd-networkd:

root@server:/# systemctl restart systemd-networkd# Убеждаемся в правильной конфигурации TUN устройства root@server:/# ifconfig tun0tun0: flags=4241<UP,POINTOPOINT,NOARP,MULTICAST>  mtu 1500         inet 172.17.0.1  netmask 255.255.255.252  destination 172.17.0.2          unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)         RX packets 0  bytes 0 (0.0 B)         RX errors 0  dropped 0  overruns 0  frame 0         TX packets 0  bytes 0 (0.0 B)         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0# Проверяем таблицу маршрутизации root@server:/# route -nKernel IP routing table Destination   Gateway        Genmask         Flags Metric Ref Use Iface    81.28.170.0   0.0.0.0        255.255.255.0   U     1      0   0   eth0169.254.0.0   0.0.0.0        255.255.0.0     U     1000   0   0   eth00.0.0.0       81.28.170.100  0.0.0.0         UG    0      0   0   eth0192.168.1.0   0.0.0.0        255.255.255.0   U     0      0   0   tun0172.17.0.0    0.0.0.0        255.255.255.252 U     0      0   0   tun0  root@server:/#

*Последняя команда (route -n) показывает параметры маршрутизации пакетов. Один из них - подсеть 192.168.1.0/24, указывающая на интерфейс tun0. С помощью неё трафик будет возвращаться на клиента.

Следующим шагом необходимо перенастроить демон ssh. По умолчанию, тунелирование запрещено в конфигурации сервера ssh. Чтобы его включить, необходимо отредактировать файл /etc/ssh/sshd_config:

# Запрещает авторизацию для rootPermitRootLogin no# Список пользователей, которым разрешена авторизация. Указывается через пробел AllowUsers vpn alex  # По умолчанию PermitTunnel установлен в `no` PermitTunnel yes 

*Пользователю alex также разрешено удаленное подключение к серверу. При настройке клиента копирование ключа будет произведено от имени этого пользователя.

Чтобы изменения вступили в силу, перезапустите сервис sshd:

root@server:/# systemctl restart sshd root@server:/#

Последнее изменение, которое необходимо выполнить на сервере - разрешить пересылку пакетов между интерфейсами. Для этого необходимо изменить параметр ядра операционной системы net.ipv4.ip_forward, изменив файл /etc/sysctl.conf:

# Значение 0 отключает возможность пересылки пакетов между интерфейсамиnet.ipv4.ip_forward = 1

И перечитайть настройки ядра:

root@server:/# sysctl -f|grep "net.ipv4.ip_forward" net.ipv4.ip_forward = 1 root@server:/#

Настройка клиента

Как и при настройке сервера, необходимо создать пользователя с ограниченными правами доступа, но при этом генерация ключа не потребуется, так как подключение будет осуществлятся по ключу, сгенерированному на сервере.

# Добавляем пользователя vpn-17012 root@client:/# useradd -mU vpn-17012# Создаем папку .ssh, в которой ssh клиент будет хранить приватный ключ сервера root@client:/# mkdir /home/vpn-17012/.ssh# Копируем приватный ключ с сервера root@client:/# scp alex@81.28.170.12://tmp/vpn-17012 /home/vpn-17012/.ssh/ alex@81.28.170.12's password:  vpn-17012                                                  100%   51     0.1KB/s   0.1KB/s   00:00 # Меняем права доступа ключа root@client:/# chown vpn-17012:vpn-17012 /home/vpn/vpn-17012/.ssh/vpn-170-12 root@client:/# chmod 600 /home/vpn-17012/.ssh/vpn-17012 root@client:/# 

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

**Команды chown и chmod нужны для изменения прав доступа к ключу.

Теперь, когда пользователь создан, необходимо заранее создать TUN устройство, которое будет доступно для чтения и записи пользователю vpn-17012.

Создайте файл /etc/systemd/system/network/30-vpn-17012.netdev со следующим содержанием:

[NetDev]Name=tun0Kind=tun[Tun]Group=vpn-17012

и файл /etc/systemd/network/30-vpn-17012.network:

[Match]Name=tun0[Address]Address=172.17.0.2/30Peer=172.17.0.1/30[Network]Address=172.17.0.1/30

С помощью этих двух файлов сервис systemd-networkd сконфигурирует:

    • TUNTAP устройство /dev/tun0 в режиме TUN;
    • Разрешит доступ к нему пользователям, состоящим в группе vpn-17012;
    • Назначит ip адрес интерфейсу и добавит маршрут до сервера.

Чтобы изменения вступили в силу, перезапустите сервис systemd-networkd:

root@client:/# systemctl restart systemd-networkd# Убеждаемся в правильной конфигурации TUN устройства root@client:/# ifconfig tun0tun0: flags=4241<UP,POINTOPOINT,NOARP,MULTICAST>  mtu 1500         inet 172.17.0.2  netmask 255.255.255.252  destination 172.17.0.1         unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)         RX packets 0  bytes 0 (0.0 B)         RX errors 0  dropped 0  overruns 0  frame 0         TX packets 0  bytes 0 (0.0 B)         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0# Проверяем таблицу маршрутизации root@client:/# route -nKernel IP routing table Destination   Gateway        Genmask         Flags Metric Ref Use Iface192.168.1.0   0.0.0.0        255.255.255.0   U     1      0   0   eth0169.254.0.0   0.0.0.0        255.255.0.0     U     1000   0   0   eth00.0.0.0       192.168.1.100  0.0.0.0         UG    0      0   0   eth0172.17.0.1    0.0.0.0        255.255.255.255 UH    0      0   0   tun0  root@client:/#

*Последняя команда показывает параметры маршрутизации пакетов. Один из них - 172.17.0.1, указывающий на интерфейс tun0. С помощью него трафик будет отправляться на сервер.

Как и в случае с сервером, необходимо перенастроить демон ssh. Отредактировуйте файл /etc/ssh/sshd_config:

# Запрещает авторизацию для rootPermitRootLogin no# По умолчанию PermitTunnel установлен в `no` PermitTunnel yes 

* Обратите внимание, на клиенте пользователю vpn-17012 авторизация запрещена.

Чтобы изменения вступили в силу, перезапустите сервис sshd:

root@client:/# systemctl restart sshd

Последнее изменение, которое необходимо выполнить на клиенте - разрешить пересылку пакетов между интерфейсами. Для этого необходимо изменить параметр ядра операционной системы net.ipv4.ip_forward, отредактируя файл /etc/sysctl.conf:

# Значение 0 отключает возможность пересылки пакетов между интерфейсамиnet.ipv4.ip_forward = 1

И применить настройки ядра:

root@client:/# sysctl -f|grep "net.ipv4.ip_forward" net.ipv4.ip_forward = 1 root@client:/#

Подключение клиента к серверу

Подключение клиента к серверу, в режиме туннелирования осуществляется коммандой:

root@client:/# su vpn-17012 vpn-17012@client:/# ssh -NCT -w 0:0 vpn@81.28.170.12 -p 22 -i /home/vpn-17012/.ssh/vpn-17012

*Процесс подключения не перейдет в режим демона. Чтобы его остановить нажмите CTRL + C.

**Параметр N - запрещает выполнение удаленной команды, С - включает компрессию, и Т - отключает использование псевдо терминала.

***Параметр -w 0:0 - включает режим туннелирования (локальный:удаленный - номер локального и удаленного tun устройства).

Для проверки соединения откройте другой терминал и наберите в нем комманду:

root@client:/# ping -c 4 172.17.0.1 PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data. 64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.015 ms 64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.022 ms 64 bytes from 172.17.0.1: icmp_seq=3 ttl=64 time=0.030 ms 64 bytes from 172.17.0.1: icmp_seq=4 ttl=64 time=0.031 ms  --- 172.17.0.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 2998ms rtt min/avg/max/mdev = 0.015/0.024/0.031/0.008 ms root@client:/#

Во избежание проблем с подключением при обрыве связи, можно настроить автоматическое переподключение к серверу. Для этого необходимо создать systemd service.

Создайте файл /etc/systemd/system/vpn-17012.service:

[Unit]Description=ssh vpn@81.28.170.12After=network-online.targetRequires=network-online.target[Service]Restart=alwaysRestartSec=15User=vpn-17012ExecStart=/usr/bin/ssh -NCT -w 0:0 vpn@81.28.170.12 -p 22 -i /home/vpn-17012/.ssh/vpn-17012[Install]WantedBy=multi-user.target

Запустите его и добавьте в автозагрузку:

root@client:/# systemctl enable vpn-17012Created symlink from /etc/systemd/system/multi-user.target.wants/vpn-17012.service to /etc/systemd/system/vpn-17012.service. root@client:/# systemctl start vpn-17012 root@client:/#

После этого, в случае обрыва связи, systemd автоматически будет перезапускать ssh подключение.