Подключение OpenWrt к OpenConnect серверу
Приветствую!

В этой статье настроим OpenWrt для подключения к OpenConnect серверу (ocserv) и организуем гибкую маршрутизацию: весь трафик, только нужные домены или конкретные IP-подсети.

podklyuchenie-openwrt-k-openconnect-serveru

Подготовка

Самое главное — подразумевается, что у вас уже есть:

для выполнения дальнейших действий из данной статьи.

Бэкап конфигурации роутера

Перед началом любой работы с OpenWrt необходимо сделать резервную копию текущей конфигурации роутера и знать, как из нее восстановиться. Как и множество других операций, бэкап в OpenWrt можно сделать двумя способами: с помощью консоли (SSH)🖥️ и веб интерфейса (LUCI)🌐.

Очевидно, что хранить бэкапы нужно не на самом роутере. Ниже представлена команда бэкапа конфига OpenWrt с помощью консоли:

BASH
ssh root@openwrt.lan 'sysupgrade --create-backup -' | cat > ./backup.tar.gz
Нажмите, чтобы развернуть и увидеть больше

Восстановление из бэкапа рекомендуется выполнять с последующим перезапуском роутера.

В случае такой необходимости выполните команды:

BASH
cat ./backup.tar.gz | ssh root@openwrt.lan 'sysupgrade --restore-backup -'

ssh root@openwrt.lan reboot
Нажмите, чтобы развернуть и увидеть больше

Также удобно делать и восстанавливать бэкап через графический интерфейс роутера. Раздел: System — Backup / FLash firmware — [Generate archive | Upload archive]

Хорошо, с бэкапом и восстановлением разобрались. Приступаем к внесению изменений в конфигурацию.

Установка пакета dnsmasq-full

Немного контекста: в прошивке OpenWrt dnsmasq (DNS и DHCP сервер) является ключевым элементом системы. В OpenWrt по умолчанию используется облегчённая версия dnsmasq для экономии пространства постоянной памяти роутера💽.

Для настройки выборочной маршрутизации по списку доменов нам понадобится полная версия: dnsmasq-full, доступная из стандартных репозиториев проекта OpenWrt.

dnsmasqdansmasq-full
DNS-serverDNS-server
DHCP-serverDHCP-server
DNSSEC
DHCPV6
Auth DNS
IPset
Nfsets
Conntrack
TFTP server

Функционал пакетов dnsmasq и dnsmasq-full

И так, открываем сессию SSH на роутере:

BASH
ssh root@openwrt.lan
Нажмите, чтобы развернуть и увидеть больше

Перед установкой dnsmasq-full необходимо удалить стандартный dnsmasq, что приведет к сбоям работы DNS на роутере. Поэтому предварительно нужно выгрузить установочный пакет dnsmasq-full в виде файла на роутер. И только потом выполнять удаление и установку:

BASH
opkg update

mkdir /tmp/dnsmasq_full && cd /tmp/dnsmasq_full

opkg download dnsmasq-full

opkg remove dnsmasq && opkg install dnsmasq-full --cache /tmp/dnsmasq_full
Нажмите, чтобы развернуть и увидеть больше

В составе пакета dnsmasq-full также идет свой файл конфигурации DHCP. Но т.к. у нас ранее был установлен dnsmasq, который уже использовал /etc/config/dhcp, то конфиг файл dnsmasq-full сохранился по пути /etc/config/dhcp-opkg:

BASH
Collected errors:
 * resolve_conffiles: Existing conffile /etc/config/dhcp is different from the conffile in the new package. The new conffile will be placed at /etc/config/dhcp-opkg.
Нажмите, чтобы развернуть и увидеть больше

Если у вас были специфические настройки DHCP на роутере, то перенесите их из /etc/config/dhcp в /etc/config/dhcp-opkg, например, с помощью vim, после чего сделайте новый конфиг основным:

BASH
mv /etc/config/dhcp-opkg /etc/config/dhcp
Нажмите, чтобы развернуть и увидеть больше

И перезапустите модуль dhcp:

BASH
service dnsmasq restart
Нажмите, чтобы развернуть и увидеть больше

В случае проблем, у нас есть бэкап, который мы сделали вначале данного руководства. Ведь сделали?😬

Установка клиента openconnect

Теперь необходимо установить клиентские пакеты openconnect, а также утилиту curl, которая понадобится нам для проверки защищенных подключений. Выполняем:

BASH
opkg install openconnect luci-proto-openconnect curl
Нажмите, чтобы развернуть и увидеть больше

Пакет luci-proto-openconnect предоставляет возможность управлять конфигурациями OpenConnect подключений в GUI роутера:

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

В этой статье я покажу пример конфигурации с помощью консольной утилиты uci, которая управляет настройкой модулей, одноименные файлы конфигурации которых расположены в /etc/config/.

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

На этом этапе задаём ключевую переменную OC_ID прямо в консоли, с произвольным именем виртуального сетевого интерфейса OpenConnect, например:

BASH
OC_ID="oc0"
Нажмите, чтобы развернуть и увидеть больше

Подключение с помощью пары логин/пароль

Ниже приведены консольные команды конфигурации модуля network для создания нового туннельного подключения. Подставьте свои значения в параметры:

BASH
uci set network.${OC_ID}=interface
uci set network.${OC_ID}.proto="openconnect"
uci set network.${OC_ID}.uri="vpn.r4ven.me:4443"
uci set network.${OC_ID}.username="openwrt"
uci set network.${OC_ID}.password="PaSSw0rD"
uci set network.${OC_ID}.vpn_protocol="anyconnect"
uci set network.${OC_ID}.defaultroute="0"
Нажмите, чтобы развернуть и увидеть больше

Применяем внесенные изменения фиксацией конфига модуля network и его перезапуска:

BASH
uci commit network

service network restart
Нажмите, чтобы развернуть и увидеть больше

Подключение с помощью файла-сертификата

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

BASH
uci set network.${OC_ID}=interface
uci set network.${OC_ID}.proto="openconnect"
uci set network.${OC_ID}.uri='vpn.r4ven.me:4443/?SeCrEt_WoRd'
uci set network.${OC_ID}.username="openwrt"
uci set network.${OC_ID}.vpn_protocol="anyconnect"
uci set network.${OC_ID}.defaultroute="0"
Нажмите, чтобы развернуть и увидеть больше

Затем нужно взять файлы ключа и сертификата пользователя и, как указано в официальном README OpenWrt, положить их на роутере по пути:

BASH
/etc/openconnect/user-cert-vpn-${OC_ID}.pem
/etc/openconnect/user-key-vpn-${OC_ID}.pem
Нажмите, чтобы развернуть и увидеть больше

Где OC_ID, как мы помним, это имя сетевого устройства, которое мы определили вначале раздела. Обратите внимание, что пути и имена файлов на роутере обязательно должны быть, как в примере выше. Они зашиты в скрипт подключения /lib/netifd/proto/openconnect.sh. Например файл ключа там выглядит так: /etc/openconnect/user-key-vpn-$config.pem.

Фиксируем и применяем изменения:

BASH
uci commit network

service network restart
Нажмите, чтобы развернуть и увидеть больше

Под спойлером ниже инструкция для параноиков😅, как задать параметр servershash.

Настройка зоны firewall

Чтобы трафик из локальной сети роутера мог ходить через интерфейс OpenConnect необходимо настроить фаервол (в последних версиях OpenWrt используется nftables).

Создаём новую зону, ассоциированную с интерфейсом OpenConnect и с использованием маскарадинга:

BASH
uci set firewall.zone_${OC_ID}="zone"
uci set firewall.zone_${OC_ID}.name="zone_${OC_ID}"
uci set firewall.zone_${OC_ID}.device="vpn-${OC_ID}"
uci set firewall.zone_${OC_ID}.input="REJECT"
uci set firewall.zone_${OC_ID}.output="ACCEPT"
uci set firewall.zone_${OC_ID}.forward="REJECT"
uci set firewall.zone_${OC_ID}.masq="1"
uci set firewall.zone_${OC_ID}.mtu_fix="1"
uci set firewall.zone_${OC_ID}.family="ipv4"
Нажмите, чтобы развернуть и увидеть больше

Теперь создаём правило переадресации трафика из зоны lan в зону OpenConnect:

BASH
uci set firewall.lan_to_${OC_ID}="forwarding"
uci set firewall.lan_to_${OC_ID}.src="lan"
uci set firewall.lan_to_${OC_ID}.dest="zone_${OC_ID}"
uci set firewall.lan_to_${OC_ID}.family="ipv4"
Нажмите, чтобы развернуть и увидеть больше

Применяем изменения:

BASH
uci commit firewall
service firewall restart
Нажмите, чтобы развернуть и увидеть больше

Поделючение настроено.

Проверка подключения

После настройки необходимо убедиться, что подключение появилось и работает. Выполняем следующие команды в консоли роутера:

BASH
# статус туннельного интерфейса
ip address show dev vpn-${OC_ID}

# пинг через туннель
ping -c3 -I vpn-${OC_ID} r4ven.me

# внешний IP (должен быть разный)
curl eth0.me
curl --interface vpn-${OC_ID} eth0.me

# подробный статус подключения
ifstatus $OC_ID
Нажмите, чтобы развернуть и увидеть больше

Обратите внимание:

В случае проблем смотрим логи:

BASH
logread -e openconnect

# или

logread -f
Нажмите, чтобы развернуть и увидеть больше

Настройка маршрутизации трафика через OpenConnect

Маршрутизация всего трафика

Если ваша цель отправлять весь трафик роутера через OpenConnect, то необходимо настроить 2 маршрута: 1й маршрут до OpenConnect сервера через WAN, 2й маршрут по умолчанию для остального трафика.

Перед настройкой необходимо определить IP адрес вашего OpenConnect сервера и IP адрес шлюза вашего провайдера:

BASH
OC_ID="oc0"
OC_IP=$(nslookup vpn.r4ven.me | awk '/^Address: / {print $2}')
WAN_GTW=$(ip route show default | awk '{print $3}')

echo -e "OC_ID=$OC_ID\nOC_IP=$OC_IP\nWAN_GTW=$WAN_GTW"
Нажмите, чтобы развернуть и увидеть больше

Теперь настраиваем сохранение маршрута к OC-серверу через WAN:

BASH
uci set network.route_${OC_ID}="route"
uci set network.route_${OC_ID}.name="route_${OC_ID}"
uci set network.route_${OC_ID}.interface="wan"
uci set network.route_${OC_ID}.target="$OC_IP"
uci set network.route_${OC_ID}.gateway="$WAN_GTW"
Нажмите, чтобы развернуть и увидеть больше

И задаем маршрут по умолчанию в настройках OpenConnect соединения:

BASH
uci set network.${OC_ID}.defaultroute="1"
Нажмите, чтобы развернуть и увидеть больше

Ранее мы устанавливали нулевое значение для параметра defaultroute. Значение 1 — создаст правило типа default via для всего трафика, кроме маршрута до OC сервера.

В конце настройки применяем изменения:

BASH
uci commit network

service network restart
Нажмите, чтобы развернуть и увидеть больше

И проверяем внешний IP:

BASH
curl eth0.me

curl --interface vpn-${OC_ID} eth0.me
Нажмите, чтобы развернуть и увидеть больше

IP адрес в выводе обеих команд должен быть адресом OpenConnect сераера.

Выборочная маршрутизация по списку доменов

Более востребованной на мой взгляд вариант маршрутизации — по заданному списку доменов.

Коротко о том, как это работает:

Одним из преимуществ данного способа является формирование ipset по wildcard, другими словами, вы добавляете домен example.com в список и при обращении к доменам нижнего уровня, например test.example.com, трафик автоматически пойдет через OpenConnect.

И так, переменные:

BASH
OC_IF="oc0"
OC_TABLE="91"
OC_MARK="0x1"
OC_ID="${OC_IF}_${OC_MARK}"
Нажмите, чтобы развернуть и увидеть больше

Где:

Добавляем новую таблицу маршрутизации:

BASH
grep -q "${OC_TABLE} table_${OC_ID}" /etc/iproute2/rt_tables || \
    echo "${OC_TABLE} table_${OC_ID}" >> /etc/iproute2/rt_tables
Нажмите, чтобы развернуть и увидеть больше

Добавляем маршрут по умолчанию (0.0.0.0/0) в указанную таблицу:

BASH
uci set network.route_${OC_ID}="route"
uci set network.route_${OC_ID}.interface="${OC_IF}"
uci set network.route_${OC_ID}.table="table_${OC_ID}"
uci set network.route_${OC_ID}.target="0.0.0.0/0"
Нажмите, чтобы развернуть и увидеть больше

Говорим ядру: если пакет с меткой ${OC_MARK}, использовать таблицу table_${OC_ID}:

BASH
uci set network.rule_${OC_ID}="rule"
uci set network.rule_${OC_ID}.name="rule_${OC_ID}"
uci set network.rule_${OC_ID}.mark="$OC_MARK"
uci set network.rule_${OC_ID}.priority="100"
uci set network.rule_${OC_ID}.lookup="table_${OC_ID}"
Нажмите, чтобы развернуть и увидеть больше

Создаём ipset в firewall, куда будут попадать IP, соответствующие нужным доменам:

BASH
uci set firewall.ipset_${OC_ID}="ipset"
uci set firewall.ipset_${OC_ID}.name="ipset_${OC_ID}"
uci set firewall.ipset_${OC_ID}.match="dst_net"
Нажмите, чтобы развернуть и увидеть больше

Маркируем пакеты, если их адрес есть в ipset:

BASH
uci set firewall.mark_${OC_ID}="rule"
uci set firewall.mark_${OC_ID}.name="mark_${OC_ID}"
uci set firewall.mark_${OC_ID}.src="lan"
uci set firewall.mark_${OC_ID}.dest="*"
uci set firewall.mark_${OC_ID}.proto="all"
uci set firewall.mark_${OC_ID}.ipset="ipset_${OC_ID}"
uci set firewall.mark_${OC_ID}.set_mark="$OC_MARK"
uci set firewall.mark_${OC_ID}.target="MARK"
uci set firewall.mark_${OC_ID}.family="ipv4"
Нажмите, чтобы развернуть и увидеть больше

Указываем, какие домены нужно резолвить в ipset через dnsmasq:

BASH
uci set dhcp.ipset_${OC_ID}="ipset"
uci set dhcp.ipset_${OC_ID}.table_family="inet"
uci add_list dhcp.ipset_${OC_ID}.name="ipset_${OC_ID}"
uci add_list dhcp.ipset_${OC_ID}.domain="eth0.me"
uci add_list dhcp.ipset_${OC_ID}.domain="example.com"
uci add_list dhcp.ipset_${OC_ID}.domain="kernel.org"
Нажмите, чтобы развернуть и увидеть больше

Применяем изменения:

BASH
uci commit network
uci commit firewall
uci commit dhcp

service network restart
service firewall restart
service dnsmasq restart
Нажмите, чтобы развернуть и увидеть больше

На предыдущем шаге мы добавили ресурс eth0.me в список доменов для выборочной маршрутизации. Выполним проверку на клиентском устройстве (подключенном к LAN роутера) с помощью curl:

BASH
# должна вернуть IP провайдера
curl ifconfig.me

# должна вернуть IP OpenConnect
curl eth0.me

# маршрут должен идти через туннель
tracepath eth0.me
Нажмите, чтобы развернуть и увидеть больше

Если вторая команда возвращает IP, который совпадает с адресом OpenConnect сервера — выборочная маршрутизация работает🥳.

Добавление новых доменов в список

Чтобы добавить новый домен в список обновляем ipset в модуле dhcp и перезапускаем dnsmasq:

BASH
uci add_list dhcp.ipset_${OC_ID}.domain="openwrt.org"

uci commit dhcp

service dnsmasq restart
Нажмите, чтобы развернуть и увидеть больше

Список Ipset можно удобно изменять и в GUI в разделе Network — DHCP and DNS — IP Sets:

В отличие от консоли, для применения изменений в GUI необходимо перезагрузить роутер🤷♂️ (или перезапустить модуль network по SSH).

Проверка на клиентском устройстве:

BASH
tracepath openwrt.org
Нажмите, чтобы развернуть и увидеть больше

Маршрут должен идти через туннель.

Выборочная маршрутизация по IP подсетям

Если вам необходимо направлять в OpenConnect отдельные IP-подсети, то необходимо:

Для расширения списка подсетей, маршрут до которых должен лежать через туннель OpenConnect достаточно будет создать новый маршрут и добавить подсеть в существующий список для маркировки в правиле фаервола.

Приступаем к настройке, начиная с переменных:

BASH
OC_IF="oc1"
OC_MARK="0x2"
OC_TABLE="92"
OC_NET="172.30.30.0/24"
OC_ID="${OC_IF}_${OC_MARK}"
ROUTE_ID="172_30_30_0"
Нажмите, чтобы развернуть и увидеть больше

Добавляем новую таблицу:

BASH
grep -q "${OC_TABLE} table_${OC_ID}" /etc/iproute2/rt_tables || \
    echo "${OC_TABLE} table_${OC_ID}" >> /etc/iproute2/rt_tables
Нажмите, чтобы развернуть и увидеть больше

Указываем маршрут до нужной подсети:

BASH
uci set network.route_${OC_ID}_${ROUTE_ID}="route"
uci set network.route_${OC_ID}_${ROUTE_ID}.name="route_${OC_ID}_${ROUTE_ID}"
uci set network.route_${OC_ID}_${ROUTE_ID}.interface="$OC_IF"
uci set network.route_${OC_ID}_${ROUTE_ID}.table="table_${OC_ID}"
uci set network.route_${OC_ID}_${ROUTE_ID}.target="$OC_NET"
Нажмите, чтобы развернуть и увидеть больше

Маркируем пакеты с помощью и направляем их через таблицу table_${OC_ID}:

BASH
uci set network.rule_${OC_ID}="rule"
uci set network.rule_${OC_ID}.mark="$OC_MARK"
uci set network.rule_${OC_ID}.priority="100"
uci set network.rule_${OC_ID}.lookup="table_${OC_ID}"
Нажмите, чтобы развернуть и увидеть больше

Настраиваем правило, которое будет отлавливать IP-пакеты к нужной подсети и макировать их:

BASH
uci set firewall.mark_${OC_ID}="rule"
uci set firewall.mark_${OC_ID}.name="mark_${OC_ID}"
uci set firewall.mark_${OC_ID}.src="lan"
uci set firewall.mark_${OC_ID}.dest="*"
uci set firewall.mark_${OC_ID}.dest_ip="$OC_NET"
uci set firewall.mark_${OC_ID}.proto="all"
uci set firewall.mark_${OC_ID}.set_mark="$OC_MARK"
uci set firewall.mark_${OC_ID}.target="MARK"
uci set firewall.mark_${OC_ID}.family="ipv4"
Нажмите, чтобы развернуть и увидеть больше

Применяем изменения:

BASH
uci commit network
uci commit firewall

service network restart
service firewall restart
Нажмите, чтобы развернуть и увидеть больше

Проверка на клиентском устройстве:

BASH
tracepath 172.30.30.1
Нажмите, чтобы развернуть и увидеть больше

Добавление новых подсетей в список

Как и сказал ранее, нужно только добавить маршрут и расширить dest_ip в firewall.mark_${OC_ID}:

BASH
OC_IF="oc1"
OC_MARK="0x2"
OC_NET="10.11.11.0/24"
OC_ID="${OC_IF}_${OC_MARK}"
ROUTE_ID="10_11_11_0"

uci set network.route_${OC_ID}_${ROUTE_ID}="route"
uci set network.route_${OC_ID}_${ROUTE_ID}.name="route_${OC_ID}_${ROUTE_ID}"
uci set network.route_${OC_ID}_${ROUTE_ID}.interface="$OC_IF"
uci set network.route_${OC_ID}_${ROUTE_ID}.table="table_${OC_ID}"
uci set network.route_${OC_ID}_${ROUTE_ID}.target="$OC_NET"

uci add_list firewall.mark_${OC_ID}.dest_ip="$OC_NET"

uci commit network
uci commit firewall

service network restart
service firewall restart
Нажмите, чтобы развернуть и увидеть больше

Выборочная маршрутизация DNS запросов

Этот шаг является опциональным.

Если в вашей сети OpenConnect есть собственный DNS сервер, то выборочная маршрутизация DNS запросов — отличное дополнение к выборочному туннелированию трафика по списку доменов. Ведь резолвинг хоста, происходит до того, как трафик пойдет через туннель, если вы конечно не туннелируете полностью весь трафик.

Добавить домены в список можно следующим способом:

BASH
uci add_list dhcp.@dnsmasq[0].server="/example.com/10.11.11.100"
uci add_list dhcp.@dnsmasq[0].server="/kernel.org/10.11.11.100"

uci commit dhcp

service dnsmasq restart
Нажмите, чтобы развернуть и увидеть больше

Где 10.11.11.100 — адрес DNS сервера в OpenConnect сети.

Для проверки необходимо установить и запустить утилиту tcpdump на роутере для прослушивания трафика отправленного в сторону DNS сервера:

BASH
opkg update

opkg install tcpdump

tcpdump -nn -i any host 10.11.11.100
Нажмите, чтобы развернуть и увидеть больше

При работающем tcpdump переходим на клиентское устройство выполняем резолвинг:

BASH
nslookup example.com

nslookup kernel.org
Нажмите, чтобы развернуть и увидеть больше

В консоли OpenWrt должны быть записи о трафике DNS, идущего через OpenConnect туннель:

BASH
10:49:05.680946 vpn-oc0 Out IP 10.11.11.15.43005 > 10.11.11.100.53: 14686+ [1au] A? example.com. (39)
10:49:05.841774 vpn-oc0 In  IP 11.11.11.100.53 > 10.11.11.15.43005: 14686 2/0/1 A 11.22.33.44, A 55.66.77.88 (71)
Нажмите, чтобы развернуть и увидеть больше

Возможные проблемы

Изменение MTU

По умолчанию для туннеля устанавливается MTU 1500, что может аффектить на работу сети. Изменить этот параметр можно так:

BASH
OC_ID="oc0"

uci set network."${OC_ID}".mtu="1434"

uci commit network

service network restart
Нажмите, чтобы развернуть и увидеть больше

Заключение

Тэк.. вот мы настроили OpenWrt так, чтобы он мог направлять трафик в туннель OpenConnect максимально гибко: весь целиком, только по нужным доменам или отдельным IP-подсетям.

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

Надеюсь, статья оказалась вам полезной😌. Спасибо, что читаете!

Используемые материалы

Авторские права

Автор: Иван Чёрный

Ссылка: https://r4ven.me/networking/podklyuchenie-openwrt-k-openconnect-serveru/

Лицензия: CC BY-NC-SA 4.0

Использование материалов блога разрешается при условии: указания авторства/источника, некоммерческого использования и сохранения лицензии.

Начать поиск

Введите ключевые слова для поиска статей

↑↓
ESC
⌘K Горячая клавиша