LINUX.ORG.RU
ФорумAdmin

Как расшарить соединение к корпоративной VPN (cisco, openconnect) на устройства в домашней сети

 


0

1

Работаем на удаленке.

Из под Windows обычно подключаемся к корпоративной сети с помощью Cisco AnyConnect, из под Linux с помощью openconnect, и далее к серверам по RDP, ssh, etc.

В том числе работает IP-телефония. Кто-то использует приложение для PC, я - приложение на смартфоне.

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

И вот захотелось иметь одно такое VPN-подключение в домашней сети и использовать его с любого устройства: desktop PC, notebook, iPhone etc.

В сети готовых, рабочих и подходящих мануалов не нашёл, решил исследовать сам…

И вот хочу поделиться тем, как я это у себя настроил, может, кому-то пригодится. Всё это не очень сложно, но есть пара нюансов…

Может, кто-то еще дополнит или в чем-то поправит…

В общем, всё реализовано с помощью openconnect.

В домашней сети работает роутер Keenetic Extra. На нем встроенный клиент openconnect настраивается не очень гибко, Entware устанавливать не хотелось.

Так же, дома постоянно работает Raspberry Pi, на которой крутится пара полезных для дома сервисов -там и решил настроить openconnect.

А на роутере через GUI просто прописал маршруты к серверам в корпоративной сети через Raspberry.

Т.е., если IP Raspberry 192.168.1.3, а нужный сервер имеет IP 10.20.20.20, то там так и прописываем: маршрут до узла, адрес узла назначения: 10.20.20.20, адрес шлюза 192.168.1.3, интерфейс - любой, поднимать автоматически - да.

Теперь настраиваем Raspberry…

Установка openconnect:

sudo apt install openconnect

Пробуем запустить:

sudo openconnect --protocol=anyconnect --user=my_username --authgroup=my_group login.company.ru

Вводим пароль - подключились, пингуем сервер внутри сети - пингуется.

В процессе подключения было предупреждение о том, что сертификат сервера не валидный (самоподписанный) и задавался вопрос, типа, «Вы точно туда хотите?», нужно было ответить yes. После этого openconnect вывел строчку, которую можно использовать в параметрах для того, чтобы вопрос не задавался. В дальнейшем она будет использоваться.

Если запускать openconnect с такими параметрами, то он сам пропишет нужные маршруты - это настроено на стороне сервера.

Однако нам нужно выполнить некоторые действия при подключении и отключении openconnect от сервера.

Для этих целей можно использовать параметр --script.

И вот при использовании этого параметра openconnect сам добавлять маршруты не будет, более того, он даже не поднимет tun-интерфейс и не настроит его. Всё это нужно будет прописать в скрипте.

В моем случае скрипт получился такой:

#!/bin/bash

#echo "REASON: $reason"

case "$reason" in
    PRE_INIT|pre_init)
        #echo "before connection"
        ;;
    CONNECT|connect)
        #echo "connected"
        /usr/bin/ip link set dev "$TUNDEV" up mtu "$INTERNAL_IP4_MTU"
        /usr/bin/ip addr add "$INTERNAL_IP4_ADDRESS/32" peer "$INTERNAL_IP4_ADDRESS" dev "$TUNDEV"
        /usr/bin/ip route add 10.20.20.20 dev "$TUNDEV" # сие первый нужный мне сервер в корпоративной сети
        /usr/bin/ip route add 10.11.11.11 dev "$TUNDEV" # второй сервер
        /usr/bin/ip route add 10.30.30.30 dev "$TUNDEV" # третий сервер
        /usr/sbin/iptables -t nat -A POSTROUTING -o "$TUNDEV" -j MASQUERADE # без этой строки пакетики не будут маршрутизироваться корректно
        /usr/sbin/sysctl -w net.ipv4.ip_forward=1 # включение форвардинга пакетов между интерфейсами
        ;;
    DISCONNECT|disconnect)
        #echo "disconnected"
        /usr/sbin/iptables -t nat -D POSTROUTING -o "$TUNDEV" -j MASQUERADE
        /usr/sbin/sysctl -w net.ipv4.ip_forward=0
        /usr/bin/ip link set dev "$TUNDEV" down
        ;;
esac

На всякий случай приведу перечень параметров (переменные среды окружения), которые возможно использовать в скрипте:


################
#
# List of parameters passed through environment
#* reason                       -- why this script was called, one of: pre-init connect disconnect reconnect attempt-reconnect
#* VPNGATEWAY                   -- VPN gateway address (always present)
#* TUNDEV                       -- tunnel device (always present)
#* IDLE_TIMEOUT                 -- gateway's idle timeout in seconds (OpenConnect v8.06+); unused
#* INTERNAL_IP4_ADDRESS         -- address (always present)
#* INTERNAL_IP4_MTU             -- MTU (often unset)
#* INTERNAL_IP4_NETMASK         -- netmask (often unset)
#* INTERNAL_IP4_NETMASKLEN      -- netmask length (often unset)
#* INTERNAL_IP4_NETADDR         -- address of network (only present if netmask is set)
#* INTERNAL_IP4_DNS             -- list of DNS servers
#* INTERNAL_IP4_NBNS            -- list of WINS servers
#* INTERNAL_IP6_ADDRESS         -- IPv6 address
#* INTERNAL_IP6_NETMASK         -- IPv6 netmask
#* INTERNAL_IP6_DNS             -- IPv6 list of dns servers
#* CISCO_DEF_DOMAIN             -- default domain name
#* CISCO_BANNER                 -- banner from server
#* CISCO_SPLIT_DNS              -- DNS search domain list
#* CISCO_SPLIT_INC              -- number of networks in split-network-list
#* CISCO_SPLIT_INC_%d_ADDR      -- network address
#* CISCO_SPLIT_INC_%d_MASK      -- subnet mask (for example: 255.255.255.0)
#* CISCO_SPLIT_INC_%d_MASKLEN   -- subnet masklen (for example: 24)
#* CISCO_SPLIT_INC_%d_PROTOCOL  -- protocol (often just 0); unused
#* CISCO_SPLIT_INC_%d_SPORT     -- source port (often just 0); unused
#* CISCO_SPLIT_INC_%d_DPORT     -- destination port (often just 0); unused
#* CISCO_IPV6_SPLIT_INC         -- number of networks in IPv6 split-network-list
#* CISCO_IPV6_SPLIT_INC_%d_ADDR -- IPv6 network address
#* CISCO_IPV6_SPLIT_INC_$%d_MASKLEN -- IPv6 subnet masklen
#
# The split tunnel variables above have *_EXC* counterparts for network
# addresses to be excluded from the VPN tunnel.

Далее, чтобы автоматизировать ввод пароля можно использовать параметр openconnect --passwd-on-stdin.

В итоге получилась такая строка запуска:

echo "$(sudo cat /home/pi/openconnect/.pd)" | sudo openconnect --interface=tun1 --script='/home/pi/openconnect/script.sh' --protocol=anyconnect --user=my_username --passwd-on-stdin --authgroup=my_group --servercert=pin-sha256:RsvEb/VnfeBX5j+9f0Yd8xw8Lk1m/KRO+agYp7o8i+n= login.company.ru

где

  • /home/pi/openconnect/.pd - файл с паролем.
  • pin-sha256:RsvEb/VnfeBX5j+9f0Yd8xw8Lk1m/KRO+agYp7o8i+n= - строка с хэшем сертификата сервера, о которой упоминал выше.

можно выполнить, убедиться, что всё работает…

Теперь засунем это в юнит systemd openconnect.service:

[Unit]
After=network.target

[Service]
User=root
Group=root
WorkingDirectory=/home/pi/openconnect
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN
Type=simple
ExecStart=/bin/sh -c 'echo $(cat /home/pi/openconnect/.pd) | openconnect --interface=tun1 --script="/home/pi/openconnect/script.sh" --protocol=anyconnect --user=my_username --passwd-on-stdin --authgroup=my_group --servercert=pin-sha256:RsvEb/VnfeBX5j+9f0Yd8xw8Lk1m/KRO+agYp7o8i+n= login.company.ru'
ExecStop=/usr/bin/killall -SIGINT openconnect
ExecStopPost=/usr/sbin/iptables -t nat -D POSTROUTING -o tun1 -j MASQUERADE
Restart=always
RestartSec=1

[Install]
WantedBy=multi-user.target

Копируем в /usr/lib/systemd/system/, стартуем, проверяем…

sudo systemctl start openconnect.service
sudo systemctl status openconnect.service
#то, что ниже - для проверки
sudo iptables -t nat -S
sudo ip route
sudo ip a
ping 10.20.20.20
#ping так же можно попробовать выполнить с другого устройства

Если всё Ок, то теперь с любого устройства в домашней сети можно сразу получить доступ к серверам корпоративной сети, не устанавливая отдельное VPN соединение…

sudo systemctl enable openconnect.service

Стоит заметить, что таким образом мы осознанно (обдуманно, оценив риски, подготовив новый паспорт, деньги и пути бегства из села/города/страны) снизили безопасность серверов в корпоративной сети и безопасность своей учетной записи, поставили под угрозу уничтожения базы данных, документы и прочие важные файлы, размещенные на серверах корпоративной сети, а так же потенциально скомпрометировали учетные данные всех сотрудников компании и, если имеются, учетные данные, переписку, документы всех пользователей сервисов нашей замечательной компании.

Для описанного снижения безопасности по расписанию можно использовать systemd.timer, но это уже совсем другая история…