p2p туннель средствами ssh
Тунель - способ установления безопасного соединения между двумя конечными точками в сети (Point - to - Point или p2p).
Суть туннелирования:
- зашифровать исходный трафик (в том числе информацию о получателе и отправителе);
- передать его на сервер, используя незащищенную сеть;
- произвести расшифровку;
- отправить данные адресату.
С точки зрения операционной системы это выглядит следующим образом:
- Клиент устанавливает ssh подключение к серверу;
- Сервер авторизует Клиента;
- Клиент и Сервер создают виртуальные устройства (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 подключение.