OpenVPN и таблицы маршрутизации

()

OpenVPN-клиент умеет получать маршруты от OpenVPN-сервера. На Linux-машинах клиент по умолчанию добавляет полученные маршруты в таблицу "main", что не всегда удобно. Кроме того может возникнуть необходимость отклонить часть маршрутов. О возможных способах решениях этих задач и пойдёт речь далее.

В конфигурацию OpenVPN-клиента можно добавить опцию "route-noexec", которая запрещает автоматическое добавление маршрутов, и позволяет с помощью параметра "route-up" указать скрипт, которому будут переданы маршруты, и который сможет их обработать.

В итоге в конфигурацию клиента надо добавить примерно такие строки:

route-noexec
route-up "/etc/openvpn/routes.sh"

И далее остаётся только написать сам скрипт. Перед написанием скрипта следует знать что все необходимые параметры передаются через параметры окружения. Основные параметры окружения:

  • dev: имя интерфейса, пример: "tun_work";
  • dev_type: тип интерфейса, пример: "tun";
  • route_net_gateway: шлюз по умолчанию на стороне клиента, пример: "1.1.1.1";
  • route_vpn_gateway: шлюз внутри VPN-сети, пример: "10.14.0.1";
  • route_network_X: сеть номер X, пример: "172.16.1.0";
  • route_netmask_X: маска сети номер X, пример: "255.255.255.0";
  • route_gateway_X: маршрут для сети номер X, пример: "10.14.0.1";

Количество переданных маршрутов заранее неизвестно и надо последовательно перебирать маршруты начиная с X=1 до тех пор, пока соответствующие переменные окружения не окажутся пустыми.

Скрипт на bash, добавляющий маршруты в таблицу net_main_clients будет выглядеть так:

#!/bin/bash

# Settings
RTTABLE="net_main_clients"
IPROUTE="/sbin/ip"

# Variable examples
#
# dev=tun_work
# dev_type=tun
# route_net_gateway=1.1.1.1
# route_vpn_gateway=10.14.0.1
# route_gateway_1=10.14.0.1
# route_network_1=172.16.0.1
# route_netmask_1=255.255.255.0

echo "Process routes..."

ROUTENUM=1
while true; do
        R_NETWORK=`eval "echo \\$route_network_${ROUTENUM}"`
        R_NETMASK=`eval "echo \\$route_netmask_${ROUTENUM}"`
        R_GATEWAY=`eval "echo \\$route_gateway_${ROUTENUM}"`
        ROUTENUM=$((ROUTENUM+1))

        if [ "${R_NETWORK}" = "" ]; then
                break;
        fi

        ROUTECMD="${IPROUTE} route add ${R_NETWORK}/${R_NETMASK} via ${R_GATEWAY} table ${RTTABLE}"
        echo ${ROUTECMD}
        ${ROUTECMD}
done

К сожалению скрипт состоит почти исключительно из bash-специфичных конструкций. Написать подобный скрипт на POSIX Shell вряд ли получится, но в качестве альтернативы для тех, кто не очень любит bash, приведём листинг полностью аналогичного скрипта на fish:

#!/usr/bin/fish

# Settings
set RTTABLE "net_localnet"
set IPROUTE "/sbin/ip"

# Variable examples
#
# dev=tun_work
# dev_type=tun
# route_net_gateway=1.1.1.1
# route_vpn_gateway=10.14.0.1
# route_gateway_1=10.14.0.1
# route_network_1=172.16.0.1
# route_netmask_1=255.255.255.0

echo "Process routes..."

set ROUTENUM 1
while true
        eval "set R_NETWORK \$route_network_$ROUTENUM"
        eval "set R_NETMASK \$route_netmask_$ROUTENUM"
        eval "set R_GATEWAY \$route_gateway_$ROUTENUM"
        set ROUTENUM (math $ROUTENUM+1 )

        if test "$R_NETWORK" = ""
                break;
        end

        set ROUTECMD "$IPROUTE route add $R_NETWORK/$R_NETMASK via $R_GATEWAY table $RTTABLE"
        echo $ROUTECMD
        eval $ROUTECMD
end

Допустим мы хотим отклонять маршруты для сетей, начинающихся на 192.168. для этого в bash-скрипт перед добавлением маршрута надо добавить примерно такую проверку:

        if [[ "${R_NETWORK}" =~ ^192\.168\. ]]; then
               continue;
        fi

В случае скрипта на fish код условия, вставляемый перед добавлением маршрута будет немного отличаться:

        if string match -rai "^192\.168\." "$R_NETWORK"
               continue;
        end

Возможны и более сложные сценарии использования скриптов-обработчиков маршрутов OpenVPN, здесь показана только общая идея. Ну и для более сложных вариантов лучше использовать полноценные языки программирования. На этом всё. Приятной работы!

Ключевые слова: openvpn, route, bash, fish.

Подписаться на обновления: RSS-лента Канал в TamTam Telegram канал Канал в ICQ

Комментарии:

Новый комментарий

Жирный текстКурсивный текстПодчёркнутый текстЗачёркнутый текстПрограммный кодСсылкаИзображение




© 2006-2024 Вадим Калинников aka MooSE
Политика конфиденциальности