Назад | Перейти на главную страницу

подключиться к стороннему серверу VPN, но не использовать его в качестве маршрута по умолчанию?

Я хотел бы подключиться к стороннему VPN-серверу в Linux (например, Debian Jessie), но по умолчанию по-прежнему использую мой интерфейс eth0 lan в качестве маршрута по умолчанию, и мне любопытно, как этого добиться. Я буду использовать маршрутизацию политик или сетевые пространства имен или наборы правил, чтобы выбрать, когда я хочу использовать стороннюю VPN.

Но мне непонятно, что openvpn делает за кулисами, что заставляет его направлять весь трафик через него. Чтобы преодолеть это, достаточно ли просто переопределить «шлюз перенаправления» при подключении с моего клиента?

Вот полное решение с использованием групп управления (cgroups), которое позволяет управлять ресурсами для каждого процесса. Группа управления сетью позволяет изолировать маршрут VPN, легко позволяет любому процессу и его дочерним процессам выборочно запускаться в нем, позволяет пользователям без полномочий root получать доступ к запущенным процессам в cgroup, а использование второго экземпляра dnsmasq может изолировать DNS запросы тоже. Предполагается, что у вас есть openvpn, dnsmasq, cgroup и версия 1.6+ iptables с установленной поддержкой cgroup. Все это было сделано на Debian Jessie

Первый шаг - создать контрольную группу и соответствующим образом настроить iptables. Это нужно делать при каждой перезагрузке, поэтому я помещаю следующее в /etc/rc.local

# enable ip forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# create cgroup for 3rd party VPN (can change 'vpn' to your name of choice)
mkdir -p /sys/fs/cgroup/net_cls/vpn

# give it an arbitrary id 
echo 11 > /sys/fs/cgroup/net_cls/vpn/net_cls.classid

# grant a non-root user access (change user:group accordingly)
cgcreate -t user:group -a user:group -g net_cls:vpn

# mangle packets in cgroup with a mark
iptables -t mangle -A OUTPUT -m cgroup --cgroup 11 -j MARK --set-mark 11

# NAT packets in cgroup through VPN tun interface
iptables -t nat -A POSTROUTING -m cgroup --cgroup 11 -o tun0 -j MASQUERADE

# redirect DNS queries to port of second instance, more on this later
iptables -t nat -A OUTPUT -m cgroup --cgroup 11 -p tcp --dport 53 -j REDIRECT --to-ports 5354
iptables -t nat -A OUTPUT -m cgroup --cgroup 11 -p udp --dport 53 -j REDIRECT --to-ports 5354

# create separate routing table
ip rule add fwmark 11 table vpn

# add fallback route that blocks traffic, should the VPN go down
ip route add blackhole default metric 2 table vpn

# disable reverse path filtering for all interfaces
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done

Следующим шагом является редактирование файла конфигурации вашего стороннего VPN-клиента, например /etc/openvpn/client.conf. Оставьте остальную часть вашей конфигурации без изменений.

# redirect-gateway def1  <--- comment or remove the redirect-gateway line if it exists

# disable automatically configuring routes and run our own routeup.sh script instead
route-noexec
route-up /etc/openvpn/routeup.sh

# run our own update-dnsmasq-conf script on interface up/down; comment out existing up/down lines
up /etc/openvpn/update-dnsmasq-conf
down /etc/openvpn/update-dnsmasq-conf

Теперь нам нужно создать /etc/openvpn/routeup.sh сценарий

#!/bin/bash
# add default route through vpn gateway to our separate routing table
/sbin/ip route add default via $route_vpn_gateway dev $dev metric 1 table vpn
exit 0

И теперь нам нужно создать модифицированную версию update-resolv-conf, которая обычно устанавливается в / etc / openvpn, чтобы создать второй экземпляр dnsmasq. Я называю это / и т. д. / openvpn / update-dnsmasq-conf

#!/bin/bash

[ "$script_type" ] || exit 0

split_into_parts()
{
    part1="$1"
    part2="$2"
    part3="$3"
}

case "$script_type" in
  up)
    NMSRVRS=""
    for optionvarname in ${!foreign_option_*} ; do
        option="${!optionvarname}"
        split_into_parts $option
        if [ "$part1" = "dhcp-option" ] ; then
            if [ "$part2" = "DNS" ] ; then
                NMSRVRS="${NMSRVRS:+$NMSRVRS }--server $part3"
            fi
        fi
    done
    dnsmasq $NMSRVRS --no-hosts --no-resolv --listen-address=127.0.0.1 \
        --port=5354 --bind-interfaces --no-dhcp-interface=* \
        --pid-file=/var/run/dnsmasq/dnsmasq2.pid
    ;;
  down)
    kill -9 $(cat /var/run/dnsmasq/dnsmasq2.pid)
    ;;
esac

Так и должно быть. Теперь вы можете запустить VPN-соединение и выборочно запускать процессы через этот интерфейс (опция --sticky гарантирует, что дочерние процессы запускаются в одной контрольной группе).

cgexec -g net_cls:vpn --sticky chromium &

ПРИМЕЧАНИЕ. Для dnsmasq убедитесь, что /etc/resolv.conf указывает на локальный хост (сервер имен 127.0.0.1). Ваш основной экземпляр dnsmasq будет обрабатывать запросы на вашем обычном маршруте, отличном от VPN, и использовать (/var/run/dnsmasq/resolv.conf), который обычно состоит из вашего шлюза по умолчанию или некоторого общедоступного DNS (например, Google 8.8.8.8). Второй экземпляр используется только изолированной контрольной группой

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

У наших друзей на nx.xc есть хорошие отзывы об этом.