Уровень сложности материала — средний.
Иногда, возникает необходимость перенаправлять трафик к некоторым сайтам через другой сетевой интерфейс. Простой пример: сотрудники филиала большой компании, должны работать со служебными разделами корпоративного портала через VPN. Из сети Интернет, доступ к данным разделам закрыт, в связи с требованиями безопасности.
У нас есть Linux сервер, который, помимо прочего, функционирует в качестве маршрутизатора. Весьма распространенная ситуация, ее и будем рассматривать, как пример. На схеме изображена типичная структура сети основного офиса и филиала:
Задача настроить Linux роутер таким образом, чтобы обращения к сайту example.org шли через VPN.
Нам понадобятся:
- Dnsmasq — рекурсивный кэширующий DNS сервер для обслуживания запросов клиентов (сотрудников)
- ipset — утилита и поддержка одноименного модуля в ядре
- iptables – утилита для конфигурирования netfilter, c поддержкой ipset
- iproute2 – пакет для расширенного управления маршрутизацией и QoS
Будем исходить из того, что VPN соединение уже настроено; при подключении создается устройство соответствующего типа (ppp или tun).
Логически решение выглядит так:
- Сотрудник набирает адрес example.org в браузере
- Dnsmasq «видит» домен в конфигурационном файле, резолвит, как обычно, + заносит IP адрес(-а) в таблицу ipset с названием VIAVPN
- Правилом iptables, пакеты с соответствующим «тэгом» ipset — VIAVPN, помечаются меткой 1 (—set-mark 1)
- В таблице маршрутизации, все пакеты с меткой 1, отправляются через интерфейс VPN
Рассказывать как установить пакеты на вашей версии Linux я не буду, надеюсь вы уже можете это сделать самостоятельно. Тем более дистрибутивы разные, и приводить в качестве примера какой-то конкретный, считаю неправильным.
Для начала настроим dnsmasq.
В первую очередь, нас интересуют вышестоящие (upstream) DNS серверы, к которым будут направляться запросы. Сам по себе, dnsmasq является, своего рода, прокси сервером. По умолчанию данная информация берется из системных настроек, файла resolv.conf. Однако можно указать альтернативный файл с помощью строки (dnsmasq.conf)
resolv-file=/etc/resolv.dnsmasq
Укажем список доменов для занесения соответствующих им IP адресов в ipset list с именем VIAVPN
ipset=/example.org/example2.com/example3.edu/VIAVPN
Через разделитель «/» можно указать любое количество доменов. Обращаю внимание, что все субдомены тоже попадут в ipset. В конце строки указывается название листа, в нашем случае VIAVPN.
Теперь самое время завести тот самый список VIAVPN
# ipset create VIAVPN hash:ip family inet
Указывается тип списка – ip адреса со структурой хранения hash. То есть, с очень быстрым, фактически мгновенным, поиском IP адреса в огромном списке. Именно по этой причине используется ipset, а не напрямую правила iptables. Family inet говорит об адресах протокола IPv4.
Правило iptables, которое будет маркировать пакеты, к IP адресам доменов (то есть с пометкой VIAVPN), маркером 1. По сути, мы меняем одну метку на другую, но беда в том, что селкторы ip rule не могут работать с ipset, лишь с fwmark. Данное правило как раз служит исключительно для этого:
# iptables -I PREROUTING -t mangle -m set --match-set VIAVPN dst -j MARK --set-mark 1
Команда не требует каких-то особых разъяснений, всё достаточно очевидно. Единственное, dst говорит о направлении трафика. То есть, извлекаем из пакета адрес назначения и проверяем его наличие в списке VIAVPN. Если присутствует, помечаем такой пакет меткой 1.
Переходим к маршрутизации
Ну, первое, конечно, заводим отдельную таблицу, назовем ее vpnrouting. Идем в файлик /etc/iproute2/rt_tables и добавляем туда строку
252 vpnrouting
ID может быть любым свободным положительным числом до 255
Добавляем маршрут по умолчанию (default gateway) в созданную таблицу. Кроме него, в нашем случае, больше ничего не понадобится, однако, сюда можно добавить другие, более точные маршруты при необходимости
# ip route add table vpnrouting default dev tun0
Поскольку, интерфейс VPN, как правило, point-to-point — можно указать вместо адреса соседнего маршрутизатора, устройство, с которого следует отправлять пакеты. Что мы и сделали.
Почти всё готово! Осталось указать, в какой таблице искать маршруты для пакетов с меткой (fwmark) 1. Если добавлять маршруты через упрощенную утилиту route, то они, на самом деле, прописываются, в таблицу main. А правило для всех пакетов, по умолчанию, ищет маршруты именно в ней.
Выведем список всех правил поиска маршрута для наглядности:
# ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
Тут всё просто, число слева — это приоритет. Для поступившего пакета ищется маршрут, начиная с наименьшего, по возрастанию. Сначала, в таблице local, там содержится информация о широковещании и адреса локальных интерфейсов. Таким образом ядро распознает широковещательные пакеты, а так же те, которые адресованы данной машине. Если маршрут для пакета не найден, проверяется следующая таблица – main. В ней всё то, что мы видим по команде «route –n». В том числе маршрут по умолчанию.
Задача указать правило поиска ДО таблицы main. По умолчанию, оно будет добавлено с приоритетом 32765. Нам это вполне подходит (хотя можем указать приоритет явным образом, например 100):
# ip rule add prio 100 fwmark 1 lookup vpnrouting
ВАЖНОЕ ЗАМЕЧАНИЕ!
Не забудьте проверить состояние rp_filter
# cat /proc/sys/net/ipv4/conf/tun0/rp_filter
Для нормальной работы, результат должен быть либо 0, либо 2. Смысл данного фильтра в следующем. Когда пакет приходит на интерфейс, ядро проверяет для него обратный маршрут. И если ответ предполагает отправку через другой интерфейс, а не тот же самый, то он считается мусорным и сбрасывается. Структура, которую мы настроили, не позволяет ядру корректно определить маршрут через тот же интерфейс. Поскольку на данном этапе он еще не маркирован, и предполагает отправку через default gateway таблицы main.
Для более полной информации, стоит прочитать что такое rp_filter, для чего он нужен и смысл значений его параметров. Я рекомендую переводить его в значение 2 для интерфейса tun0, и 1 для всех остальных.
Удачного администрирования!
root4root aka admin
Добавить комментарий
X