Тунель - способ установления безопасного соединения между двумя конечными точками в сети (Point - to - Point или p2p).
Суть туннелирования:
С точки зрения операционной системы это выглядит следующим образом:
В качестве транспортного уровня используется ранее установленное 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=tun0
Kind=tun
[Tun]
Group=vpn
и файл /etc/systemd/network/30-vpn-17012.network:
[Match]
Name=tun0
[Address]
Address=172.17.0.1/30
Peer=172.17.0.2/30
[Network]
Address=172.17.0.1/30
[Route]
Gateway=172.17.0.1
Destination=192.168.1.0/24
С помощью этих двух файлов сервис systemd-networkd сконфигурирует:
Чтобы изменения вступили в силу, перезапустите сервис systemd-networkd:
root@server:/# systemctl restart systemd-networkd
# Убеждаемся в правильной конфигурации TUN устройства
root@server:/# ifconfig tun0
tun0: 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 -n
Kernel 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 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.0 UG 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
172.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:
# Запрещает авторизацию для root
PermitRootLogin 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=tun0
Kind=tun
[Tun]
Group=vpn-17012
и файл /etc/systemd/network/30-vpn-17012.network:
[Match]
Name=tun0
[Address]
Address=172.17.0.2/30
Peer=172.17.0.1/30
[Network]
Address=172.17.0.1/30
С помощью этих двух файлов сервис systemd-networkd сконфигурирует:
Чтобы изменения вступили в силу, перезапустите сервис systemd-networkd:
root@client:/# systemctl restart systemd-networkd
# Убеждаемся в правильной конфигурации TUN устройства
root@client:/# ifconfig tun0
tun0: 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 -n
Kernel IP routing table
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
172.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:
# Запрещает авторизацию для root
PermitRootLogin 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.12
After=network-online.target
Requires=network-online.target
[Service]
Restart=always
RestartSec=15
User=vpn-17012
ExecStart=/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-17012
Created 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 подключение.