Skonfiguruj routing i iptables dla nowego połączenia VPN, aby przekierowywać ** tylko ** porty 80 i 443

8

Mam nowe połączenie VPN (korzystające z openvpn), które pozwala mi ominąć niektóre ograniczenia ISP. Chociaż działa dobrze, przejmuje cały ruch przez VPN. Powoduje to problemy z pobieraniem (moje połączenie internetowe jest znacznie szybsze niż pozwala na to VPN) i ze zdalnym dostępem. Pracuję na serwerze ssh i mam uruchomionego demona, który pozwala mi pobierać pliki przez mój telefon.

Mam istniejące połączenie Ethernet na eth0, a nowe połączenie VPN na tun0.

Wydaje mi się, że muszę skonfigurować domyślną trasę korzystania z mojego istniejącego połączenia eth0 w sieci 192.168.0.0/24 i ustawić domyślną bramę na 192.168.0.1 (moja wiedza jest niepewna, ponieważ nie robiłem tego przez wiele lat ). Jeśli to prawda, to nie jestem do końca pewien, jak to zrobić! Moja obecna tabela routingu to:

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

Po naprawieniu routingu, wydaje mi się, że muszę użyć iptables do skonfigurowania routingu lub maskowania, aby wymusić wszystko dla portu docelowego 80 lub 443 przez tun0. Znów nie jestem pewien, jak to zrobić!

Wszystko, co znalazłem w Internecie, próbuje zrobić coś o wiele bardziej skomplikowanego, a próba oddzielenia drewna od drzew okazuje się trudna.

Każda pomoc będzie mile widziana.

AKTUALIZACJA

Jak dotąd, z różnych źródeł, zebrałem razem następujące elementy:

#!/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

Teraz wydaje się, że to działa. Tyle że nie jest!

Połączenia do zablokowanych stron internetowych przeżywa, nie połączenia na portach 80 i 443 za pomocą połączenia non-VPN.

Jednak połączenia portów 80 i 443, które nie są z zablokowanymi stronami internetowymi, również korzystają z połączenia innego niż VPN!

Po osiągnięciu ogólnego celu jestem stosunkowo szczęśliwy, ale fajnie byłoby wiedzieć, dlaczego nie działa dokładnie tak, jak powinien.

Jakieś pomysły?

Dla porównania mam teraz 3 tabele routingu, main, internet i VPN. Ich lista jest następująca ...

Główny:

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 

Internet:

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
Steve
źródło
Powyższy skrypt działa zgodnie z oczekiwaniami. Po prostu spodziewałem się zobaczyć ruch pochodzący z 10. adresu w netstat. Cały ruch pochodzi jednak z 192., ale port 80 i 443 jest kierowany przez VPN. Odpowiem całe rozwiązanie, ale podpiera @anttir za sugerowanie iproute2 i fwmark. Nie spotkałem ich, a bez nich nadal waliłbym głową w ścianę z cegieł!
Steve,

Odpowiedzi:

4

Więc większość tego jest powyżej, ale całe rozwiązanie było następujące:

Edytuj / etc / iproute2 / rt_tables i dodaj 2 linie na dole:

101 internet
102 vpn

Możesz nadać tym tabelom inne nazwy, które będą bardziej sensowne, po prostu spójne.

Następnie musisz utworzyć skrypt (nazwałem go rt_setup) w /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

Następnie, oczywiście, połącz go z /etc/rc2.d (używam ubuntu, poziom uruchamiania może się dla ciebie różnić). Upewnij się, że podałeś mu liczbę S wyższą niż link openvpn!

Skrypt robi wiele rzeczy. W górnej części konfigurowane są zmienne, z niektórymi instrukcjami perla i awk używanymi do pobierania dynamicznych adresów IP i adresów bram. Druga sekcja czyści tabele ustawione w ipruote2 i kopiuje do nich bieżącą tabelę routingu. Następnie tworzy dwie nowe trasy i dwie domyślne bramy, z których jedna VPN przechodzi przez VPN, a Internet przez moją sieć lokalną.

Nie jestem przekonany, że kolejne 2 linie są konieczne, ale umożliwiają przekazywanie adresu IP do użycia w iptables.

Następnie skrypt tworzy reguły dotyczące tego, gdzie szukać ruchu pochodzącego z odpowiedniego adresu IP i gdzie sprawdzić, czy ruch jest specjalnie oznaczony.

POSTROUTING i PREROUTING zapewnia, że ​​ruch pochodzący z adresu otrzymuje odpowiedź!

Końcowe WSTĘPNE iptables to część, która taguje ruch i zapewnia, że ​​wszystko, co przechodzi do portów 80 lub 443, jest oznaczone do użycia w Tabeli 2 (VPN)

Ostatnie dwa wiersze usuwają bramę VPN z domyślnej tabeli routingu i dodają z powrotem moją bramę sieci lokalnej.

Na obecnym etapie proces działa doskonale. VPN jest uruchamiany wraz z uruchomieniem maszyny, a ten skrypt jest uruchamiany kilka sekund później (mogę dodać komunikat uśpienia, aby upewnić się, że VPN jest w pełni zainicjowany przed uruchomieniem tego skryptu). Moje połączenie dostępu zdalnego (ssh itp.) Działa świetnie. Moje połączenia, które nie wychodzą na porty 80 lub 443, używają mojego połączenia lokalnego, ale cały ruch internetowy przechodzi przez VPN i omija elementy sterujące wprowadzone przez mojego dostawcę usług internetowych!

Jak powiedziałem w moim komentarzu pod moim pytaniem, nawet nie zacząłem patrzeć na tę trasę bez sugestii @anttir. Poza tą sugestią strony http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/ i http://linux-ip.net/ HTML / adv-multi-internet.html były bardzo przydatne (nawet jeśli kod nie jest w 100% kompletny!)

Steve
źródło
1
Po ostatnim dodaniu sleep 20dodałem na początku skryptu, ponieważ połączenie openvpn nie kończyło się na czas. Dodałem również echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filterdo skryptu, ponieważ konieczne jest wyłączenie filtru pakietów zwrotnych dla tun0. Gdy odpowiedź wraca z tun0 z adresem źródłowym S, filtr pakietów zwrotnych sprawdza „jeśli miałbym skierować pakiet do adresu S i nie przejdzie on przez tun0, porzucę pakiet” - i ponieważ robiąc to wyszukiwanie nie ma prawidłowego znaku fw, określa, że ​​trasa byłaby zwykłą trasą domyślną, więc opuszcza pakiet.
Steve,
Musiałem edytować twój skrypt, aby działał dla mnie. Ostatnia linia route add default gw 192.168.0.1 eth0zdawała się kierować ruchem portu 80/443 przez lokalną bramę zamiast tun0 zgodnie z przeznaczeniem. Zmiana ostatniej linii route add default tun0wydaje się załatwić sprawę.
1

routing według protokołu jest trochę skomplikowany. Zwykle tabela routingu służy do sprawdzania bramy zgodnie z docelowym adresem IP i korzystania z domyślnej bramy openvpn lub 192.168.0.1.

Łatwiej byłoby skonfigurować np. Proxy HTTP Squid na drugim końcu sieci VPN i ustawić przeglądarkę, aby korzystała z proxy.

Nie użyłbyś iptables, ponieważ zmieniłoby to docelowy adres IP połączenia HTTP i nie działałoby.

Możesz utworzyć nową tabelę routingu (/ etc / iproute2 / rt_tables) z domyślną trasą ustawioną na punkt końcowy VPN, użyć iptables fwmark (-j MARK) do oznaczenia wszystkich pakietów HTTP, a następnie użyć reguły ip do utworzenia niestandardowej reguły dla zaznaczono pakiety, aby użyć nowej tabeli routingu.

Antti Rytsölä
źródło
Dzięki za pomoc. Z pewnością przyjrzę się tym. Sprawy są trochę trudne, ponieważ nie mam kontroli nad końcem serwera, tylko moja strona. Ponadto nie mogę używać kałamarnicy, ponieważ muszę kierować ruchem https przez połączenie, a kałamarnica nie działa z tym tak dobrze.
Steve,
Co powiesz na routing tylko kilku adresów IP przez VPN i resztę świata poza VPN?
Antti Rytsölä
Zastanawiałem się nad routingiem tylko kilku adresów IP, ale lista zmienia się, gdy strony się zmieniają, i muszę to ułatwić innym użytkownikom komputera. Zacząłem patrzeć na konfigurowanie nowej tabeli routingu i oznaczanie pakietów. Pakowanie oznaczeń było łatwe, nie jestem tego pewien. Mogę skonfigurować jedną dla VPN, która wygląda dobrze, i drugą dla wszystkiego, co wygląda poprawnie, ale nie jestem pewien, co zrobić z głównym, ponieważ nadal jest ustawiony na wartości domyślne (którym jest VPN). Nadal gra ...
Steve,
linux-ip.net/html/adv-multi-internet.html Pokaż regułę ip i regułę ip dodaj fwmark 4 tabela 4 priorytet 10000
Antti Rytsölä
Dodano aktualizację do oryginału, która zawiera szczegółowe informacje na temat tego, co robię do tej pory! AH! Właśnie zdałem sobie sprawę, że zredagowałem twoją odpowiedź, a nie moje pytanie. Przepraszam! Nie korzystałem tak często i nie zdawałem sobie sprawy, że mogę edytować odpowiedź innej osoby!
Steve,