Installa routing e iptables per la nuova connessione VPN per reindirizzare ** solo ** le porte 80 e 443


8

Ho una nuova connessione VPN (usando openvpn) per permettermi di aggirare alcune restrizioni ISP. Mentre funziona bene, sta prendendo tutto il traffico sulla VPN. Questo mi sta causando problemi per il download (la mia connessione a Internet è molto più veloce di quanto consente la VPN) e per l'accesso remoto. Eseguo un server SSH e ho un demone in esecuzione che mi permette di scaricare i download tramite il mio telefono.

Ho la mia connessione ethernet esistente su eth0 e la nuova connessione VPN su tun0.

Credo di dover configurare il percorso predefinito per utilizzare la mia connessione eth0 esistente sulla rete 192.168.0.0/24 e impostare il gateway predefinito su 192.168.0.1 (la mia conoscenza è traballante poiché non lo faccio da diversi anni ). Se è corretto, allora non sono esattamente sicuro di come farlo !. La mia tabella di routing corrente è:

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

Dopo aver corretto il routing, credo di dover usare iptables per configurare il prerouting o il masquerading per forzare tutto per la porta di destinazione 80 o 443 su tun0. Ancora una volta, non sono esattamente sicuro di come farlo!

Tutto ciò che ho trovato su Internet sta provando a fare qualcosa di molto più complicato, e cercare di separare il legno dagli alberi si sta rivelando difficile.

Qualsiasi aiuto sarebbe molto apprezzato.

AGGIORNARE

Finora, dalle varie fonti, ho messo insieme i seguenti elementi:

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

Ora sembra funzionare. Solo che non lo è!

Connessioni ai siti bloccati sono attraversando, collegamenti non sulle porte 80 e 443 sono con l'accesso non-VPN.

Tuttavia, le connessioni delle porte 80 e 443 che non sono ai siti Web bloccati utilizzano anche la connessione non VPN!

Dato che l'obiettivo generale è stato raggiunto, sono relativamente felice, ma sarebbe bello sapere perché non funziona esattamente bene.

Qualche idea?

Per riferimento, ora ho 3 tabelle di routing, main, internet e vpn. L'elenco di questi è il seguente ...

Principale:

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

Lo script sopra funziona come previsto. Mi aspettavo solo di vedere il traffico proveniente dall'indirizzo 10. in netstat. Tuttavia, tutto il traffico proviene da 192., ma le porte 80 e 443 sono dirette su VPN. Metterò l'intera soluzione in una risposta, ma propongo a @anttir per aver suggerito iproute2 e fwmark. Non li avevo incontrati, e senza di loro avrei comunque sbattuto la testa contro un muro di mattoni!
Steve,

Risposte:


4

Quindi, la maggior parte di questo è sopra, ma l'intera soluzione era la seguente:

Modifica / etc / iproute2 / rt_tables e aggiungi 2 righe in fondo:

101 internet
102 vpn

Puoi dare a queste tabelle altri nomi che hanno più senso, solo essere coerenti.

Quindi è necessario creare uno script (l'ho chiamato rt_setup) in /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

Quindi, ovviamente, collegalo da /etc/rc2.d (io uso Ubuntu, il runlevel potrebbe differire per te). Assicurati di assegnargli un numero S superiore al link openvpn!

La sceneggiatura fa diverse cose. La parte superiore imposta le variabili, con alcune istruzioni perl e awk usate per raccogliere gli IP dinamici e gli indirizzi gateway. La seconda sezione pulisce le tabelle che hai impostato in ipruote2 e copia su esse l'attuale tabella di routing. Crea quindi due nuovi percorsi e due gateway predefiniti per loro, con quello VPN che passa attraverso la VPN e quello Internet che passa attraverso la mia rete locale.

Non sono convinto che le prossime 2 righe siano necessarie, ma abilitano l'inoltro ip per l'uso in iptables.

Successivamente lo script crea alcune regole su dove cercare il traffico proveniente dal relativo indirizzo IP e dove cercare se il traffico è specificamente contrassegnato.

POSTROUTING e PREROUTING assicurano che il traffico proveniente da un indirizzo ottenga la risposta!

L'IPtables finale PREROUTING è la parte dei tag del traffico e garantisce che tutto ciò che va alle porte 80 o 443 sia contrassegnato per utilizzare la Tabella 2 (VPN)

Le ultime due righe rimuovono il gateway VPN dalla tabella di routing predefinita e aggiungono nuovamente il mio gateway di rete locale.

Allo stato attuale, il processo funziona in modo brillante. La VPN viene avviata all'avvio della macchina e questo script viene eseguito pochi secondi dopo (posso aggiungere un'istruzione sleep solo per garantire che la VPN sia completamente inizializzata prima di eseguire questo script). La mia connessione di accesso remoto (ssh ecc.) Funziona alla grande. Le mie connessioni che non vanno alle porte 80 o 443 utilizzano la mia connessione locale, ma tutto il traffico web passa attraverso la VPN e ignora i controlli messi in atto dal mio ISP!

Come ho detto nel mio commento sotto la mia domanda, non avrei nemmeno iniziato a guardare questo percorso senza il suggerimento di @anttir. Sul retro di quel suggerimento, i siti http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/ e http://linux-ip.net/ html / adv-multi-internet.html sono stati molto utili (anche se il codice non è completo al 100%!)


1
Un'ultima aggiunta, ho aggiunto a sleep 20all'inizio dello script poiché la connessione openvpn non si stava completando in tempo. Ho anche aggiunto echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filterallo script in quanto è necessario disabilitare il filtro pacchetto inverso per tun0. Quando una risposta ritorna da tun0 con l'indirizzo sorgente S, il filtro pacchetto inverso controlla "se dovessi indirizzare un pacchetto verso l'indirizzo S, e non passerei attraverso tun0, lascerò cadere il pacchetto" - e perché quando lo faccio ricerca non esiste un marchio valido, determina che la route sarebbe la solita route predefinita, quindi rilascia il pacchetto.
Steve,

Ho dovuto modificare il tuo copione per farlo funzionare per me. L'ultima linea route add default gw 192.168.0.1 eth0sembrava instradare il traffico della porta 80/443 attraverso il gateway locale anziché tun0 come previsto. Cambiare l'ultima riga in route add default tun0sembra fare il trucco per me.

1

il routing per protocollo è un po 'complicato. Di solito la tabella di routing viene utilizzata per controllare il gateway in base all'IP di destinazione e utilizzare openvpn o il gateway predefinito 192.168.0.1.

Sarebbe più semplice impostare ad esempio il proxy http Squid sull'altra estremità della VPN e impostare il browser per utilizzare il proxy.

Non useresti iptables in quanto cambierebbe l'IP di destinazione della connessione HTTP e non funzionerebbe.

È possibile creare una nuova tabella di routing (/ etc / iproute2 / rt_tables) con route predefinita impostata sull'endpoint VPN, utilizzare iptables fwmark (-j MARK) per contrassegnare tutti i pacchetti HTTP e quindi utilizzare la regola ip per creare una regola personalizzata per il pacchetti contrassegnati per utilizzare la nuova tabella di routing.


Grazie per l'aiuto. Certamente darò un'occhiata a quelli. Le cose sono un po 'complicate in quanto non ho il controllo dell'estremità del server, solo dalla mia parte. Inoltre, non posso usare squid perché devo instradare il traffico https sulla connessione, e squid non funziona così bene con quello.
Steve,

Che ne dici di instradare solo pochi IP sulla VPN e il resto del mondo al di fuori della VPN?
Antti Rytsölä,

Ho pensato di instradare solo pochi IP, ma l'elenco cambia mentre i siti si spostano e devo renderlo facile da usare per altri utenti sul PC. Ho iniziato a esaminare la creazione di una nuova tabella di routing e la marcatura dei pacchetti. I pacchetti di marcatura sono stati facili, sono le tabelle di routing di cui non sono così sicuro. Posso impostarne uno per VPN che appaia giusto e uno per tutto ciò che sembra giusto, ma non sono sicuro di cosa fare con main in quanto è ancora impostato sui valori predefiniti (ovvero VPN). Ancora giocando ...
Steve,

linux-ip.net/html/adv-multi-internet.html show regole ip e regole ip aggiungono fwmark 4 tabella 4 priorità 10000
Antti Rytsölä

Aggiunto un aggiornamento all'originale che specifica dove sto lavorando finora! AH! Ho appena realizzato che ho modificato la tua risposta, non la mia domanda. Scusate! Non ho usato così tanto, e non avevo capito che avrei potuto modificare la risposta di un'altra persona!
Steve,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.