VPN-канал с помощью OpenSSH. Часть третья

10.04.2020

Теги: LinuxSSHUbuntuVPNКлиентКонфигурацияНастройкаСерверСетевойИнтерфейс

Мы посмотрели, как можно завернуть весь трафик одного компьютера в защищенный туннель. Теперь посмотрим, как можно направить в туннель трафик всех компьютеров локальной сети. Итак, у нас есть сервер с белым ip-адресом 123.123.123.123, несколько компьютеров в сети 192.168.250.0/24 и маршрутизатор, который обеспечивает для этих компов выход в интернет.

Для простоты будем считать, что у нас есть физический доступ к маршрутизатору gateway и настройку сервера будем выполнять с него. Для этого настроим аутентификацию по ключу на сервере для пользователя evgeniy.

Вход на сервер по ключу

Создаем ключи на маршрутизаторе для пользователя evgeniy:

$ ssh-keygen

Копируем публичный ключ на сервер:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub evgeniy@123.123.123.123

Проверяем аутентификацию по ключу:

$ ssh evgeniy@123.123.123.123
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-91-generic x86_64)

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

1. Добавляем пользователя ssh-vpn

Создаем пользователя ssh-vpn:

# useradd -mU ssh-vpn
# mkdir /home/ssh-vpn/.ssh/ # директория для хранения ключей
# chown ssh-vpn:ssh-vpn /home/ssh-vpn/.ssh/
# chmod 700 /home/ssh-vpn/.ssh/

2. Настройки OpenSSH сервера

Изменяем настройки ssh-сервера:

# nano /etc/ssh/sshd_config
# Разрешаем создание сетевых туннелей
PermitTunnel point-to-point
# Запрещаем аутентификацию для root
PermitRootLogin no
# Разрешаем аутентификацию по ключу
PubkeyAuthentication yes
# Запрещаем аутентификацию по паролю
PasswordAuthentication no
# Этим пользователям можно входить
AllowUsers evgeniy ssh-vpn
# systemctl restart ssh.service

3. Создаем TUN устройство при загрузке

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

# nano /etc/systemd/network/50-ssh-vpn.netdev
[NetDev]
Name=tun0
Kind=tun
[Tun]
User=ssh-vpn
# nano /etc/systemd/network/50-ssh-vpn.network
[Match]
Name=tun0
[Address]
Address=192.168.200.1/30
Peer=192.168.200.2/30
[Network]
Address=192.168.200.1/30
[Route]
Destination=192.168.250.0/24
Gateway=192.168.200.2

Здесь мы указываем маршрут до подсети 192.168.250.0/24 для интерфейса tun0 — пакеты надо отправлять через шлюз 192.168.200.2. Другими словами — отправлять пакеты на интерфейс tun0 маршрутизатора gateway. Маршрутизатор перекинет эти пакеты с интерфейса tun0 на интерфейс enp0s8 и отправит дальше — компьютеру pc1 или pc2.

4. Пересылка пакетов tun0→ens3 и ens3→tun0

Маршрутизатор будет направлять трафик в туннель, но что делать с этим трафиком — сервер пока не знает. Нужно включить пересылку пакетов между интерфейсами tun0 и ens3.

# nano /etc/sysctl.conf
net.ipv4.ip_forward=1
# iptables -P FORWARD DROP
# iptables -A FORWARD -i tun0 -o ens3 -s 192.168.250.0/24 -j ACCEPT
# iptables -A FORWARD -i ens3 -o tun0 -d 192.168.250.0/24 -j ACCEPT

Теперь добавим SNAT (подмена адреса источника), что позволит всем компьютерам подсети 192.168.250.0/24 выходить в интернет, используя единственный ip-адрес 123.123.123.123.

# iptables -t nat -A POSTROUTING -o ens3 -s 192.168.250.0/24 -j MASQUERADE

Правила мы добавили, но они пропадут при перезагрузке сервера. Так что их нужно сохранить и восстанавливать при перезагрузке. В этом нам поможет пакет iptables-persistent, который добавит новую службу netfilter-persistent.service:

# apt install iptables-persistent

При установке пакета будет предложено сохранить текущие правила iptables:

  • в файл /etc/iptables/rules.v4 для протокола IPv4
  • в файл /etc/iptables/rules.v6 для протокола IPv6

5. Перезагружаем сервер

Перезагружаем сервер и смотрим сетевые интерфейсы, маршруты и правила форвардинга:

$ ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:3c:57:5a brd ff:ff:ff:ff:ff:ff
    inet 123.123.123.123/24 brd 123.123.123.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe3c:575a/64 scope link 
       valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
    link/none 
    inet 192.168.200.1 peer 192.168.200.2/30 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::873f:8e56:6aec:88bf/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

На самом деле такой вывод команды ip addr будет только после того, как мы настроим маршрутизатор gateway. А в этот момент интерфейс tun0 будет выключен, потому что туннель еще не создан. Но мы это скоро исправим.

$ route -n
Destination     Gateway         Genmask           Flags   Metric   Ref   Use   Iface
------------------------------------------------------------------------------------
0.0.0.0         123.123.123.1   0.0.0.0           UG      0        0     0     ens3
123.123.123.0   0.0.0.0         255.255.255.0     U       0        0     0     ens3
192.168.200.0   0.0.0.0         255.255.255.252   U       0        0     0     tun0
192.168.250.0   192.168.200.2   255.255.255.0     UG      0        0     0     tun0

Красным выделены маршруты, которые были добавлены при создании TUN устройства.

# iptables -t filter -L -v --line-numbers 
..........
Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts   bytes   target   prot   opt   in     out    source             destination
1        0       0   ACCEPT   all    --    tun0   ens3   192.168.250.0/24   anywhere
2        0       0   ACCEPT   all    --    ens3   tun0   anywhere           192.168.250.0/24
..........
# iptables -t nat -L -v --line-numbers
..........
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts   bytes   target       prot   opt   in    out    source             destination
1        0       0   MASQUERADE   all    --    any   ens3   192.168.250.0/24   anywhere
..........

Настройка маршрутизатора

Перед настройкой нужно сделать небольшое лирическое отступление. Если бы мы просто настраивали маршрутизатор, нам нужно было включить пересылку пакетов между интерфейсами, создать несколько правил для netfilter с помошью утилиты iptables и добавить SNAT:

# nano /etc/sysctl.conf
net.ipv4.ip_forward=1
# iptables -P FORWARD DROP
# iptables -A FORWARD -i enp0s8 -o enp0s3 -s 192.168.250.0/24 -j ACCEPT # enp0s8 -> enp0s3
# iptables -A FORWARD -i enp0s3 -o enp0s8 -d 192.168.250.0/24 -j ACCEPT # enp0s3 -> enp0s8
# iptables -t nat -A POSTROUTING -o enp0s3 -s 192.168.250.0/24 -j MASQUERADE

Но, поскольку мы будем направлять весь трафик в туннель, порядок действий будет несколько иным.

1. Сетевые интерфейсы и форвардинг

Сначала настраиваем сетевые интерфейсы:

# nano /etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      dhcp4: no
      addresses: [192.168.150.2/24]
      gateway4: 192.168.150.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
    enp0s8:
      dhcp4: no
      addresses: [192.168.250.1/24]

Пересылка пакетов между интерфейсами по умолчанию отключена, так что редактируем файл /etc/sysctl.conf:

# nano /etc/sysctl.conf
net.ipv4.ip_forward=1

После этого настраиваем netfilter с помощью утилиты iptables:

# iptables -P FORWARD DROP
# iptables -A FORWARD -i enp0s8 -o tun0 -s 192.168.250.0/24 -j ACCEPT # enp0s8 -> tun0
# iptables -A FORWARD -i tun0 -o enp0s8 -d 192.168.250.0/24 -j ACCEPT # tun0 -> enp0s8

Правила мы добавили, но они пропадут при перезагрузке сервера. Так что их нужно сохранить и восстанавливать при перезагрузке. В этом нам поможет пакет iptables-persistent, который добавит новую службу netfilter-persistent.service:

# apt install iptables-persistent

При установке пакета будет предложено сохранить текущие правила iptables:

  • в файл /etc/iptables/rules.v4 для протокола IPv4
  • в файл /etc/iptables/rules.v6 для протокола IPv6

2. Создание пользователя ssh-vpn

Создаем пользователя ssh-vpn:

# useradd -mU ssh-vpn

Создаем публичный и приватный ключи:

# su ssh-vpn # дальше все команды выполянем от имени пользователя ssh-vpn
$ cd /home/ssh-vpn/
$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ssh-vpn/.ssh/id_rsa): Enter
Created directory '/home/ssh-vpn/.ssh/'.
Enter passphrase (empty for no passphrase): Enter
Enter same passphrase again: Enter
Your identification has been saved in /home/ssh-vpn/.ssh/id_rsa.
Your public key has been saved in /home/ssh-vpn/.ssh/id_rsa.pub.
$ exit # завершаем сеанс работы под пользователем ssh-vpn

Теперь нам надо скопировать публичный ключ на сервер с помощью команды scp. Но у нас нет доступа для пользователя evgeniy:

  • к директории /home/ssh-vpn/.ssh/ на маршрутизаторе
  • к директории /home/ssh-vpn/.ssh/ на сервере

Изменяем права на директорию /home/ssh-vpn/.ssh/ на маршрутизаторе:

# chmod 707 /home/ssh-vpn/.ssh/

Изменяем права на директорию /home/ssh-vpn/.ssh/ на сервере:

# chmod 707 /home/ssh-vpn/.ssh/

Копируем от имени пользователя evgeniy публичный ключ на сервер:

$ scp /home/ssh-vpn/.ssh/id_rsa.pub evgeniy@123.123.123.123:/home/ssh-vpn/.ssh/authorized_keys

Возвращаем обратно права на директорию на маршрутизаторе:

# chmod 700 /home/ssh-vpn/.ssh/

Задаем владельца и права для файла authorized_keys на сервере:

# chown ssh-vpn:ssh-vpn /home/ssh-vpn/.ssh/authorized_keys
# chmod 600 /home/ssh-vpn/.ssh/authorized_keys

Возвращаем обратно права на директорию на сервере:

# chmod 700 /home/ssh-vpn/.ssh/

И надо обязательно выполнить вход по ssh на сервер от имени пользователя ssh-vpn с маршрутизатора, чтобы был создан файл known_hosts. Иначе потом, при автоматическом создании туннеля в момент загрузки gateway, получим сообщение об ошибке «Host key verification failed».

# su ssh-vpn # команду выполяняем от имени пользователя ssh-vpn
$ ssh -i ~/.ssh/id_rsa ssh-vpn@123.123.123.123
..........
Are you sure you want to continue connecting (yes/no)? yes
..........
$ exit # завершаем ssh-сеанс c сервером 123.123.123.123
$ exit # завершаем сеанс работы под пользователем ssh-vpn

3. Создаем TUN устройство при загрузке

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

# nano /etc/systemd/network/50-ssh-vpn.netdev
[NetDev]
Name=tun0
Kind=tun
[Tun]
User=ssh-vpn
# nano /etc/systemd/network/50-ssh-vpn.network
[Match]
Name=tun0
[Address]
Address=192.168.200.2/30
Peer=192.168.200.1/30
[Network]
Address=192.168.200.2/30

4. Создаем туннель при загрузке

Для этого нам нужна служба, которая будет создавать туннель при загрузке системы. Кроме того, при обрыве связи эта служба будет пытаться снова установить соединение.

# nano /etc/systemd/system/ssh-vpn-tunnel-to-server.service
[Unit]
Description=SSH tunnel to 123.123.123.123 at startup
Requires=network-online.target
After=network-online.target
[Service]
User=ssh-vpn
ExecStartPre=/bin/sh -c 'until ping -c1 123.123.123.123; do sleep 1; done;'
ExecStart=/usr/bin/ssh -i /home/ssh-vpn/.ssh/id_rsa -N -w 0:0 ssh-vpn@123.123.123.123
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target

Сообщаем системе про новый unit-файл:

# systemctl daemon-reload

Добавляем новую службу в автозагрузку:

# systemctl enable ssh-vpn-tunnel-to-server.service

5. Заворачиваем трафик в туннель

Чтобы перенаправить весь трафик подсети 192.168.250.0/24 через туннель, нужно вместо старого шлюза — 192.168.150.1 (через интерфейс enp0s3) указать новый — 192.168.200.1 (через интерфейс tun0). Но при этом потеряется связь с сервером — поэтому перед заменой шлюза нужно добавить маршрут до сервера.

# ip route add 123.123.123.123/32 via 192.168.150.1 dev enp0s3
# ip route replace default via 192.168.200.1 dev tun0

Но эти два маршрута пропадут при перезагрузке системы, так что добавим две новые службы:

# nano /etc/systemd/system/ssh-vpn-route-to-server.service
[Unit]
Description=Route to server for SSH tunnel at startup
Requires=network-online.target ssh-vpn-tunnel-to-server.service
After=network-online.target ssh-vpn-tunnel-to-server.service
[Service]
ExecStartPre=/bin/sh -c 'until ping -c1 123.123.123.123; do sleep 1; done;'
ExecStart=/bin/ip route add 123.123.123.123 via 192.168.150.1 dev enp0s3
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
# nano /etc/systemd/system/ssh-vpn-new-default-route.service
Description=Replace default route for SSH tunnel at startup
Requires=network-online.target ssh-vpn-tunnel-to-server.service ssh-vpn-route-to-server.service
After=network-online.target ssh-vpn-tunnel-to-server.service ssh-vpn-route-to-server.service
[Service]
ExecStartPre=/bin/sh -c 'until ping -c1 192.168.200.1; do sleep 1; done;'
ExecStart=/bin/ip route replace default via 192.168.200.1 dev tun0
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

Сообщим системе про два новых unit-файла:

# systemctl daemon-reload

Добавляем новые службы в автозагрузку:

# systemctl enable ssh-vpn-route-to-server.service
# systemctl enable ssh-vpn-new-default-route.service

6. Перезагружаем маршрутизатор

Перезагружаем маршрутизатор, чтобы добавить TUN-устройство, создать SSH-туннель и завернуть трафик клиента в туннель:

# reboot

После этого смотрим сетевые интерфейсы, маршруты и правила форвардинга:

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:31:44:64 brd ff:ff:ff:ff:ff:ff
    inet 192.168.150.2/24 brd 192.168.150.255 scope global dynamic enp0s3
       valid_lft 24945sec preferred_lft 24945sec
    inet6 fe80::a00:27ff:fe31:4464/64 scope link 
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:06:4a:53 brd ff:ff:ff:ff:ff:ff
    inet 192.168.250.1/24 brd 192.168.250.255 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe06:4a53/64 scope link 
       valid_lft forever preferred_lft forever
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 500
    link/none 
    inet 192.168.200.2 peer 192.168.200.1/30 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::1f5a:a3e3:341e:96cf/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
$ route -n
Destination     Gateway          Genmask           Flags   Metric   Ref   Use   Iface
--------------------------------------------------------------------------------------
0.0.0.0           192.168.200.1   0.0.0.0           UG      0        0     0     tun0
0.0.0.0           192.168.150.1   0.0.0.0           UG      100      0     0     enp0s3
123.123.123.123   192.168.150.1   255.255.255.255   UGH     0        0     0     enp0s3
192.168.150.0     0.0.0.0         255.255.255.0     U       0        0     0     enp0s3
192.168.150.1     0.0.0.0         255.255.255.255   UH      100      0     0     enp0s3
192.168.200.0     0.0.0.0         255.255.255.252   U       0        0     0     tun0
192.168.250.0     0.0.0.0         255.255.255.0     U       0        0     0     enp0s8

Красным выделены маршруты, которые мы добавили. А зеленым — маршрут, который был добавлен при создании TUN-устройства.

# iptables -t filter -L -v --line-numbers
..........
Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts bytes   target   prot   opt   in       out      source             destination
1        0     0   ACCEPT   all    --    enp0s8   tun0     192.168.250.0/24   anywhere
2        0     0   ACCEPT   all    --    tun0     enp0s8   anywhere           192.168.250.0/24
..........

Теперь все готово

Теперь все готово, так что открываем на компьютере pc1 браузер и смотрим свой ip-адрес:

Поиск: Linux • SSH • Ubuntu • VPN • Клиент • Конфигурация • Настройка • Сервер • Туннель • TUN-устройство • Сетевой интерфейс

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.