Маршрутизация на основе целевого домена не является невозможной, и с помощью подходящих инструментов не все так сложно.
Я представлю несколько методов, которые практически не требуют специальной настройки на стороне клиента. Все это предполагает, что вы используете OpenVPN для подключения. Это должно быть достижимо с другими VPN, но может потребовать больше ручной настройки после запуска VPN.
В качестве примера я буду использовать домены "example.com", "us1.example.com", "us2.example.com" и "geoblocked.com" для доменов, которые мы хотим направить через не-VPN интерфейс.
Все команды должны быть запущены от имени пользователя root.
Способ 1 - OpenVPN
Я бы порекомендовал это, только если вы уверены, что IP-адреса, которые вы маршрутизируете, имеют статические IP-адреса, которые никогда не меняются.
Плюсы:
Минусы:
- Надежно только для доменов с IP-адресами, которые никогда не меняются
- Нужна явная запись для каждого домена и субдомена
Метод:
Добавьте следующие строки в вашу конфигурацию OpenVPN:
route example.com 255.255.255.255 net_gateway
route us1.example.com 255.255.255.255 net_gateway
route us2.example.com 255.255.255.255 net_gateway
route geoblocked.com 255.255.255.255 net_gateway
Перезапустите OpenVPN.
Вот и все, но вам придется перезапустить VPN снова, если эти IP-адреса когда-либо изменятся.
ПРИМЕЧАНИЕ . Некоторые источники сообщают, что вам также необходимо указать allow-pull-fqdn
, но, по моему опыту, этого не произошло. YMMV.
Способ 2 - Маршрутизация на основе политик
Маршрутизация на основе политик - это возможность маршрутизации на основе определенных критериев; обычно адрес источника или протокол, но в этом случае мы проверяем имя домена назначения перед маршрутизацией и используем помеченные пакеты ("fwmark").
Сначала нам нужно создать отдельную таблицу для ваших маршрутизируемых VPN-пакетов, чтобы мы могли отмечать те, которые проходят через VPN и пропускают помеченные пакеты через не-VPN-интерфейс. (Имейте в виду, что это один из подходов, и есть много других способов приблизиться к нему, например, позволить VPN делать свою маршрутизацию как обычно через основную таблицу и создавать отдельную таблицу для трафика не-VPN.)
Ваше ядро должно быть достаточно новым и иметь надлежащие модули, хотя современные системы, вероятно, содержат их в своих ядрах по умолчанию.
Имя "vpn_table" (имя таблицы маршрутизации) и числа "201" (идентификатор таблицы маршрутизации) и "3" (fwmark) выбираются произвольно.
Создайте новую таблицу маршрутизации (от имени root):
echo 201 vpn_table >> /etc/iproute2/rt_tables
Настройте OpenVPN:
Создайте где-нибудь следующий скрипт (я называю его «/etc/openvpn/client/setup-routing») и сделайте его исполняемым:
#!/bin/bash
ip route add 0.0.0.0/1 via $route_vpn_gateway dev $dev scope global table vpn_table
ip route add 128.0.0.0/1 via $route_vpn_gateway dev $dev scope global table vpn_table
sysctl -w net.ipv4.conf.$dev.rp_filter=2
# You can optionally leave the next two lines out but run the `ip rule add`
# command at each boot instead
ip rule del fwmark 3 table vpn_table &>/dev/null # This might fail but that's ok
ip rule add fwmark 3 table vpn_table
Переменные в вышеприведенном скрипте будут заполнены OpenVPN как переменные среды. Также обратите внимание, что это устанавливает маршрутизацию ко всем адресам через шлюз VPN в таблице маршрутизации "vpn_table". Если для вашей настройки VPN требуется более сложная маршрутизация, обратитесь к документации OpenVPN и выполните соответствующие настройки.
Добавьте следующее в вашу конфигурацию OpenVPN:
## Policy routing
route-noexec
script-security 2
route-up /etc/openvpn/client/setup-routing
Строка "route-noexec" позволяет OpenVPN извлекать маршрут с сервера, но не позволяет ему фактически заполнять маршруты. Вместо этого вызывается скрипт маршрутизации. «script-security 2» необходим для вызова пользовательского сценария.
Это все, что необходимо для маршрутизации помеченных пакетов, но нам нужно настроить способ их фактической маркировки. Два варианта - использовать dnsmasq с ipset или настроить прокси-сервер squid.
Способ 2a - Маршрутизация на основе политик с использованием ipset и dnsmasq
Я бы порекомендовал этот метод, если вы уже запускаете его на маршрутизаторе на основе dnsmasq или ваши клиенты не поддерживают настройку прокси. По сути, это то же самое, что и кэширующий DNS, который обновляет таблицу маршрутизации при поиске доменного имени.
Плюсы:
- Управляет поддоменами
- Работает на устройствах, которые не могут получить доступ к прокси (существуют ли они?)
Минусы:
- Не обрабатывает поле реферера (см. Метод 2b)
- Нужны сложные конфиги ipset и iptables
- Требуется, чтобы система, подключенная по VPN, была настроена в качестве маршрутизатора (необходим выделенный интерфейс)
- Я понятия не имею, как масштабируемый ipset (мой вариант использования для всего ccTLD)
Это предполагает, что вы уже настроили и настроили dnsmasq и выступаете в качестве шлюза и DNS-сервера для клиентов, подключенных к выделенному интерфейсу "eth1".
Создайте ipset:
ipset create SKIP_VPN_IPSET iphash
Скажите iptables, чтобы пометить пакеты ipset (примечание, это необходимо сделать после создания списка ipset):
# Mark ALL packets coming in on eth1 - change this to the interface dnsmasq listens on
iptables -A PREROUTING -i eth1 -t mangle -j MARK --set-mark 3
# REMOVE mark on any addresses that match our ipset
iptables -A PREROUTING -t mangle -m set --match-set SKIP_VPN_IPSET dst -j MARK --set-mark 0/3
ПРИМЕЧАНИЕ . Приведенные выше команды (ipset
и iptables
) должны выполняться при каждой загрузке. В качестве альтернативы ваша ОС может предоставлять некоторые параметры для сохранения / восстановления правил iptable и ipsets.
ПРИМЕЧАНИЕ 2: Там задокументировано обратное ! --match-set
но в результате все пакеты просто исчезли, когда я попробовал.
Добавьте следующее в ваш dnsmasq.conf:
ipset=/example.com/geoblocked.com/SKIP_VPN_IPSET
Очевидно, настройте эту строку слишком сильно, независимо от того, какие доменные имена вы хотите перенаправить. Это также добавит ВСЕ субдомены в ipset, поэтому вам не нужно явно указывать их. Даже использование TLD будет работать.
Перезапустите dnsmasq и настройте своих клиентов на использование системы, подключенной к VPN, в качестве шлюза и DNS (что следует понимать, если она настроена в качестве сервера DHCP).
Это мой любимый метод, и он хорошо работает с моим PS4 и другими устройствами, которые я использую для подключения.
Плюсы:
- Управляет поддоменами
- Обрабатывает поле реферера
- Не требует замены существующего маршрутизатора
- Клиенты (браузеры) могут по желанию использовать его или нет
Минусы:
- Клиенты должны поддерживать прокси-соединение
Это предполагает, что у вас есть работающая настройка squid и базовые знания по настройке squid.
Добавьте следующие строки в squid.conf:
# redirect example domains
acl domain_to_remote_proxy dstdomain .example.com
acl ref_to_remote_proxy referer_regex [^.]*\.example.com.*
# redirect geoblocked domain
acl domain_to_remote_proxy dstdomain .geoblocked.com
acl ref_to_remote_proxy referer_regex [^.]*\.geoblocked.com.*
# mark packets that we want routed through the VPN
tcp_outgoing_mark 0x03 !ref_to_remote_proxy !domain_to_remote_proxy
Обратите внимание, что на каждый домен приходится 2 строки, и поддомены совпадают. Первая строка проверяет домен назначения, а вторая соответствует заголовку "Referer". Это полезно, потому что браузеры отправляют реферер при извлечении контента на веб-странице, такой как изображения, CSS или javascript; это означает, что контент, запрашиваемый сайтом, также будет направляться через не-VPN-адрес, даже если он размещен в другом домене (например, example-cdn.com).
На клиентах настройте соединение как обычно, но настройте параметры прокси-сервера, чтобы использовать прокси-сервер и порт для этой системы. Большинство устройств (включая игровые приставки) допускают общесистемную настройку. На ПК большинство браузеров могут быть настроены на использование прокси независимо от настроек системы.
Последнее замечание. Мой вариант использования - для маршрутизации определенных доменов через VPN, а все остальное - без VPN. Методы аналогичны приведенным выше, но инвертированы.