Я пытаюсь настроить клиент OpenVPN на ArchLinux с PrivateInternetAccess. По умолчанию PIA проталкивает маршруты так, что весь трафик проходит через VPN. Я только хочу, чтобы некоторые приложения использовали VPN.

Для этого я использую "политику на основе маршрутизации". Я создал новую таблицу маршрутизации с именем "vpn" и буду выборочно отправлять пользователей в эту таблицу маршрутизации.

После этих команд пользователь "media" будет перенаправлен в таблицу маршрутизации "vpn":

$ echo 100 vpn >> /etc/iproute2/rt_tables
$ iptables -t mangle -I OUTPUT -m owner --uid-owner media -j MARK --set-mark 0x1
$ ip rule add fwmark 0x1 table vpn

Я дополнительно изменил свою конфигурацию клиента OpenVPN, чтобы мои таблицы маршрутизации были заполнены правильно:

$ cat /etc/openvpn/client.conf
    client
    dev tun
    proto udp
    remote us-newyorkcity.privateinternetaccess.com 1194
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    ca /etc/openvpn/ca.crt
    tls-client
    remote-cert-tls server
    auth-user-pass /etc/openvpn/login.conf
    comp-lzo
    verb 1
    reneg-sec 0
    crl-verify /etc/openvpn/crl.pem

    # This will override PIA so that traffic will route through our normal gateway
    route 0.0.0.0 192.0.0.0 net_gateway
    route 64.0.0.0 192.0.0.0 net_gateway
    route 128.0.0.0 192.0.0.0 net_gateway
    route 192.0.0.0 192.0.0.0 net_gateway

    # Calling these scripts will add the PIA routes to the vpn table
    script-security 2
    up /etc/openvpn/up.sh
    down /etc/openvpn/down.sh

$ cat /etc/openvpn/up.sh
    #!/bin/sh
    ip route add table vpn default via $ifconfig_remote

$ cat /etc/openvpn/down.sh
    #!/bin/sh
    ip route flush table vpn

Вот мои таблицы маршрутизации после запуска openvpn /etc/openvpn/client.conf:

$ ip route show table main
    0.0.0.0/2 via 192.168.1.1 dev eth0
    0.0.0.0/1 via 10.197.1.5 dev tun0
    default via 192.168.1.1 dev eth0  src 192.168.1.124  metric 202
    10.197.1.1 via 10.197.1.5 dev tun0
    10.197.1.5 dev tun0  proto kernel  scope link  src 10.197.1.6
    64.0.0.0/2 via 192.168.1.1 dev eth0
    128.0.0.0/2 via 192.168.1.1 dev eth0
    128.0.0.0/1 via 10.197.1.5 dev tun0
    192.0.0.0/2 via 192.168.1.1 dev eth0
    192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.124  metric 202
    209.95.50.86 via 192.168.1.1 dev eth0

$ ip route show table vpn
    default via 10.197.1.5 dev tun0

Все работает как пользователь, который НЕ перенаправляется в таблицу "vpn":

$ whoami
    jordan

$ ping -c 2 8.8.8.8
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=46 time=38.9 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=46 time=39.0 ms

    --- 8.8.8.8 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1001ms
    rtt min/avg/max/mdev = 38.952/38.999/39.047/0.203 ms

Тем не менее, происходит сбой для пользователя, который попадает в таблицу "vpn":

$ whoami
media

$ ping -c 2 8.8.8.8
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.

    --- 8.8.8.8 ping statistics ---
    2 packets transmitted, 0 received, 100% packet loss, time 999ms

Я посмотрел на tcpdump -i tun0 чтобы увидеть, что происходит. Кажется, что запрос icmp идет через tun0, но не возвращается?

$ tcpdump -i tun0
    listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
    15:37:30.134399 IP keep > google-public-dns-a.google.com: ICMP echo request, id 10256, seq 1, length 64
    15:37:31.143217 IP keep > google-public-dns-a.google.com: ICMP echo request, id 10256, seq 2, length 64

Мысли? :(

==== РЕДАКТИРОВАТЬ # 1 ====

В качестве проверки работоспособности, если мы отправляем весь трафик через VPN (удаляя строки «route xxxx 192.0.0.0 net_gateway» в /etc/openvpn/client.conf), мы получаем ответы icmp просто отлично:

$ tcpdump -i tun0
    listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
    16:26:54.401732 IP keep > google-public-dns-a.google.com: ICMP echo request, id 10480, seq 1, length 64
    16:26:54.483122 IP google-public-dns-a.google.com > keep: ICMP echo reply, id 10480, seq 1, length 64
    16:26:55.403465 IP keep > google-public-dns-a.google.com: ICMP echo request, id 10480, seq 2, length 64
    16:26:55.485068 IP google-public-dns-a.google.com > keep: ICMP echo reply, id 10480, seq 2, length 64

==== РЕДАКТИРОВАТЬ # 2 ====

Следуя совету MariusMatutiae, я попытался с помощью --route-noexec вручную установить маршруты в /etc/openvpn/up.sh . Мы также отключаем фильтрацию обратного пути в /etc/openvpn/up.sh и повторно включаем его в /etc/openvpn/down.sh:

$ cat /etc/openvpn/up.sh
    #!/bin/sh
    ip route add table vpn 0.0.0.0/1 via $ifconfig_remote
    ip route add table vpn 128.0.0.0/1 via $ifconfig_remote
    ip route add table vpn $route_network_1 via $ifconfig_remote
    ip route add table vpn $trusted_ip via $route_net_gateway

    ip route add table vpn $ifconfig_remote dev tun0 proto kernel src $ifconfig_local
    ip route add table vpn 192.168.1.0/24 dev eth0 proto kernel src 192.168.1.124 metric 202

    ip route del table main $ifconfig_remote

    # Disable reverse path filtering
    for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
            echo 0 > $f;
    done

$ cat /etc/openvpn/down.sh
    #!/bin/sh
    ip route flush table vpn

    # Re-enable reverse path filtering
    for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
            echo 1 > $f;
    done

После этого мои таблицы маршрутизации выглядят так:

$ ip route show table main
    default via 192.168.1.1 dev eth0  src 192.168.1.124  metric 202
    192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.124  metric 202

$ ip route show table vpn
    0.0.0.0/1 via 10.173.1.5 dev tun0
    10.173.1.1 via 10.173.1.5 dev tun0
    10.173.1.5 dev tun0  proto kernel  scope link  src 10.173.1.6
    128.0.0.0/1 via 10.173.1.5 dev tun0
    192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.124  metric 202
    209.95.50.133 via 192.168.1.1 dev eth0

Тем не менее, пользователь "media" по-прежнему не может ping 8.8.8.8 . tcpdump -i tun0 прежнему сообщает, что ответы не возвращаются :(

2 ответа2

1

Вы неправильно разбили свои маршруты на две таблицы маршрутизации. Следующие маршруты, появляющиеся в main таблице, относятся к таблице vpn :

0.0.0.0/1 via 10.197.1.5 dev tun0
128.0.0.0/1 via 10.197.1.5 dev tun0
10.197.1.1 via 10.197.1.5 dev tun0     
10.197.1.5 dev tun0  proto kernel  scope link  src 10.197.1.6
209.95.50.86 via 192.168.1.1 dev eth0

Следующий маршрут принадлежит обеим таблицам:

192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.124  metric 202

Причина этого в том, что: первые четыре правила включают интерфейс tun0 , виртуальный сетевой адаптер , созданный OpenVPN, который явно не имеет ничего общего с main таблицей. Пятое правило учит ваше ядро, как получить доступ к вашему серверу PIA. Последнее правило позволяет обеим таблицам иметь доступ к локальным компьютерам, таким как принтеры, NAS и так далее.

Что касается того, как настроить это автоматически, это немного усложняется тем фактом, что ваш сервер OpenVPN может назначать вам IP-адрес tun0 который каждый раз отличается: так как вы не управляете сервером, вы можете не настроить его для назначения вашего tun0 интерфейс статический адрес.

Так что вам нужно научиться использовать, во-первых, опцию --route-no-exec . В Руководстве говорится:

не --route-нет-Exec

Не добавляйте и не удаляйте маршруты автоматически. Вместо этого передайте маршруты скрипту --route-up, используя переменные среды.

Затем вы должны научиться использовать переменные среды (в конце руководства есть целый раздел), особенно те, которые называются ifconfig-- что-то.

Кроме того, вы найдете необходимым отключить фильтрацию обратного пути ядром,

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done

Я бы поместил эту команду в ваш скрипт up , а обратный

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done

в вашем down сценарии. Это необходимо, потому что у вас есть основной шлюз на главной таблице, что означает, что, когда ядро проверяет, есть ли спуфинг, любой пакет помечается.

В качестве альтернативы и более просто вы можете рассмотреть вопрос о переключении роли двух таблиц: пусть OpenVPN сделает свое дело автоматически, и настроит маршруты для main таблицы маршрутизации, и настроит новую таблицу маршрутизации под названием non-vpn которая имеет вашу обычную конфигурацию,

# ip route show
  default via 192.168.0.1 dev eth0  proto static 
  192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.74  metric 1 

(или что-то подобное) для пакетов, не соответствующих марке выше. Это намного проще в настройке.

0

Я отказался от работы маршрутизации на основе политик. Вместо этого я использовал сетевые пространства имен для достижения своей цели. Хорошее руководство по началу работы можно найти здесь https://schnouki.net/posts/2014/12/12/openvpn-for-a-single-application-on-linux/

Отдельное спасибо MariusMatutiae за помощь!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .