Настройте маршрутизацию и iptables для нового VPN-подключения для перенаправления ** только ** портов 80 и 443

8

У меня новое VPN-соединение (использующее openvpn), чтобы позволить мне обходить некоторые ограничения ISP. Хотя он работает нормально, он принимает весь трафик через VPN. Это вызывает у меня проблемы с загрузкой (мое интернет-соединение намного быстрее, чем позволяет vpn) и удаленным доступом. Я запускаю ssh-сервер и у меня работает демон, который позволяет мне планировать загрузку через мой телефон.

У меня есть существующее соединение Ethernet на eth0, а новое VPN-соединение на tun0.

Я считаю, что мне нужно настроить маршрут по умолчанию для использования моего существующего соединения eth0 в сети 192.168.0.0/24 и установить шлюз по умолчанию на 192.168.0.1 (мои знания шатки, так как я не делал этого в течение ряда лет ). Если это правильно, то я не совсем уверен, как это сделать! Моя текущая таблица маршрутизации:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface    MSS   Window irtt
0.0.0.0         10.51.0.169     0.0.0.0         UG    0      0        0 tun0     0     0      0
10.51.0.1       10.51.0.169     255.255.255.255 UGH   0      0        0 tun0     0     0      0
10.51.0.169     0.0.0.0         255.255.255.255 UH    0      0        0 tun0     0     0      0
85.25.147.49    192.168.0.1     255.255.255.255 UGH   0      0        0 eth0     0     0      0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth0     0     0      0
192.168.0.0     0.0.0.0         255.255.255.0   U     1      0        0 eth0     0     0      0

После исправления маршрутизации я считаю, что мне нужно использовать iptables для настройки предварительной маршрутизации или маскирования, чтобы принудительно настроить все для порта назначения 80 или 443 через tun0. Опять же, я не совсем уверен, как это сделать!

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

Любая помощь приветствуется.

ОБНОВИТЬ

Пока из разных источников я собрал воедино следующее:

#!/bin/sh

DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`

ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
    ip route add table $TABLE1 $ROUTE
    ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2

echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2

iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2

iptables -t nat -A PREROUTING           -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables        -A OUTPUT               -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1  -m state --state NEW                          -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2  -m state --state NEW                          -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING           -m connmark --mark 1                          -j MARK --set-mark 1
iptables -t nat -A PREROUTING           -m connmark --mark 2                          -j MARK --set-mark 2
iptables -t nat -A PREROUTING           -m state --state NEW -m connmark ! --mark 0   -j CONNMARK --save-mark

iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport  80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2

route del default
route add default gw 192.168.0.1 eth0

Теперь это, кажется, работает. За исключением того, что это не так!

Подключение к заблокированным веб - сайты будут идти через, соединение не на порты 80 и 443 будут использовать соединение без VPN.

Однако порты 80 и 443, которые не подключены к заблокированным веб-сайтам, также используют не-VPN-подключение!

Поскольку общая цель достигнута, я относительно счастлив, но было бы неплохо узнать, почему она работает не совсем правильно.

Любые идеи?

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

Главный:

default via 192.168.0.1 dev eth0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1 

Интернет:

default via 192.168.0.1 dev eth0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1 
192.168.0.1 dev eth0  scope link  src 192.168.0.73

VPN:

default via 10.38.0.205 dev tun0 
10.38.0.1 via 10.38.0.205 dev tun0 
10.38.0.205 dev tun0  proto kernel  scope link  src 10.38.0.206 
85.removed via 192.168.0.1 dev eth0 
169.254.0.0/16 dev eth0  scope link  metric 1000 
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.73  metric 1
Стив
источник
Приведенный выше скрипт работает как положено. Я просто ожидал увидеть трафик, исходящий с 10. адреса в netstat. Однако весь трафик начинается с 192. Но порты 80 и 443 направлены через VPN. Я поставлю все решение в ответе, но призываю @anttir предлагать iproute2 и fwmark. Я не сталкивался с ними, и без них я бы все еще бился головой о кирпичную стену!
Стив

Ответы:

4

Итак, большая часть этого выше, но все решение было следующим:

Отредактируйте / etc / iproute2 / rt_tables и добавьте 2 строки внизу:

101 internet
102 vpn

Вы можете дать этим таблицам другие имена, которые имеют больше смысла, просто быть последовательными.

Затем вам нужно создать скрипт (я назвал его rt_setup) в /etc/init.d

#!/bin/sh

DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`

ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
    ip route add table $TABLE1 $ROUTE
    ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2

echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2

iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2

iptables -t nat -A PREROUTING           -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables        -A OUTPUT               -m state --state ESTABLISHED,RELATED          -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1  -m state --state NEW                          -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2  -m state --state NEW                          -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING           -m connmark --mark 1                          -j MARK --set-mark 1
iptables -t nat -A PREROUTING           -m connmark --mark 2                          -j MARK --set-mark 2
iptables -t nat -A PREROUTING           -m state --state NEW -m connmark ! --mark 0   -j CONNMARK --save-mark

iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport  80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2

route del default
route add default gw 192.168.0.1 eth0

Затем, очевидно, свяжите его с /etc/rc2.d (я использую ubuntu, уровень запуска может отличаться для вас). Убедитесь, что вы даете ему номер S выше, чем ссылка openvpn!

Сценарий делает несколько вещей. В верхней части настраиваются переменные, с некоторыми операторами perl и awk, используемыми для получения динамических IP-адресов и адресов шлюзов. Во втором разделе очищаются таблицы, настроенные в ipruote2, и копируется в них текущая таблица маршрутизации. Затем он создает два новых маршрута и два шлюза по умолчанию для них, при этом VPN-соединение проходит через VPN, а интернет-подключение - через мою локальную сеть.

Я не уверен, что следующие 2 строки необходимы, но они позволяют пересылку ip для использования в iptables.

Затем сценарий создает некоторые правила о том, где искать трафик, исходящий с соответствующего IP-адреса, и где искать, если трафик специально помечен.

POSTROUTING и PREROUTING гарантирует, что трафик, исходящий от адреса, получит ответ!

Окончательное ПРЕДУПРЕЖДЕНИЕ iptables является частью тегов трафика и гарантирует, что все, что идет к портам 80 или 443, помечено для использования Таблицы 2 (VPN)

Последние две строки удаляют шлюз VPN из таблицы маршрутизации по умолчанию и добавляют обратно мой шлюз локальной сети.

В настоящее время процесс работает блестяще. VPN запускается при включении компьютера, и этот сценарий запускается через несколько секунд (я могу добавить оператор ожидания только для того, чтобы убедиться, что VPN полностью инициализирована перед запуском этого сценария). Мое подключение удаленного доступа (SSH и т. Д.) Отлично работает. Мои соединения, которые не идут к портам 80 или 443, используют мое локальное соединение, но весь веб-трафик проходит через VPN, и в обход элементов управления, установленных моим провайдером!

Как я сказал в своем комментарии к моему вопросу, я бы даже не начал искать этот маршрут без предложения @anttir. За спиной этого предложения, сайты http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/ и http://linux-ip.net/ html / adv-multi-internet.html были очень полезны (даже если код не завершен на 100%!)

Стив
источник
1
Последнее добавление, я добавил a sleep 20в начало скрипта, так как соединение openvpn не завершалось вовремя. Я также добавил echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filterв скрипт, так как необходимо отключить фильтр обратных пакетов для tun0. Когда ответ возвращается из tun0 с адресом источника S, обратный фильтр пакетов проверяет, «если я должен был направить пакет на адрес S, и он не прошел через tun0, я отброшу пакет» - и потому, что при этом при поиске нет действительного fwmark, он определяет, что маршрут будет обычным маршрутом по умолчанию, поэтому отбрасывает пакет.
Стив
Мне пришлось отредактировать ваш скрипт, чтобы он работал на меня. Последняя строка, route add default gw 192.168.0.1 eth0казалось, направляла трафик порта 80/443 через локальный шлюз вместо tun0, как предполагалось. Изменение последней строки, route add default tun0кажется, помогает мне.
1

маршрутизация по протоколу немного сложна. Обычно таблица маршрутизации используется для проверки шлюза по IP-адресу назначения и использования шлюза по умолчанию openvpn или 192.168.0.1.

Было бы проще настроить, например, Squid http proxy на другом конце VPN и настроить браузер на использование прокси.

Вы не будете использовать iptables, так как это изменит целевой IP-адрес HTTP-соединения, и это не будет работать.

Вы можете создать новую таблицу маршрутизации (/ etc / iproute2 / rt_tables) с маршрутом по умолчанию, установленным для конечной точки VPN, использовать iptables fwmark (-j MARK), чтобы отметить все пакеты HTTP, а затем использовать правило ip, чтобы создать собственное правило для помечены пакеты для использования новой таблицы маршрутизации.

Антти Рыцёля
источник
Спасибо за вашу помощь. Я обязательно посмотрю на них. Вещи немного хитры в том, что у меня нет контроля над концом сервера, только моя сторона. Кроме того, я не могу использовать squid, потому что мне нужно маршрутизировать трафик https через соединение, и squid не очень хорошо с этим работает.
Стив
Как насчет маршрутизации всего нескольких IP-адресов через VPN и остальной мир за пределами VPN?
Антти Рыцёля
Я задумывался о маршрутизации всего нескольких IP-адресов, но список меняется по мере перемещения сайтов, и мне нужно сделать это простым для использования другими пользователями на ПК. Я начал смотреть на настройку новой таблицы маршрутизации и маркировки пакетов. Маркировка пакетов была легкой задачей, я не уверен в таблицах маршрутизации. Я могу настроить один для VPN, который выглядит правильно, и один для всего остального, который выглядит правильным, но я не уверен, что делать с main, так как он все еще установлен на значения по умолчанию (который является VPN). Все еще играет ...
Стив
linux-ip.net/html/adv-multi-internet.html ip rule show и ip rule добавьте fwmark 4, таблица 4, приоритет 10000
Antti Rytsölä
В оригинал добавлено обновление, в котором подробно я до сих пор! AH! Просто понял, что я отредактировал твой ответ, а не мой вопрос. Сожалею! Я не использовал это так много, и не понимал, что смогу отредактировать ответ другого человека!
Стив