Come fare in modo che tutto il traffico passi attraverso un'unica interfaccia in Linux


12

Ho un'interfaccia auto-scritta tun0 ( basata su TUN / TAP ) che emette ciò che riceve.
Ho bisogno che tutto il traffico del sistema scorra attraverso questa interfaccia.
Il ruolo dell'interfaccia è:

  1. Per capire i pacchetti che potrebbero essere censurati e scavalcarli.
  2. Passa tutto il resto del traffico intatto.

Come indovini, sto cercando di costruire uno strumento anticensorship.
La decisione sul tunneling deve essere presa all'interno del processo tun0
perché solo lì possiamo usare DNS fidato.

Ho bisogno del tuo aiuto per mostrarmi come far fluire tutto il traffico attraverso un'interfaccia auto-scritta tun0. Se tun0 necessita di modifiche, ti chiedo di fornire tali modifiche.

Di seguito è riportato il modo in cui ho provato a far passare tutto il traffico attraverso tun0 e non è riuscito (ping fallito).

compilazione

  1. gcc tun0.c
  2. sudo ./a.out

Configurazione

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. crea un tavolo John

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

L'ordine è importante:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

Risoluzione dei problemi

  1. sudo tcpdump -i wlp2s0 -qtln icmpe quindi ping -I tun0 8.8.8.8non mostra pacchetti catturati, significa che nessun pacchetto viene trasmesso da tun0 a wlp2s0 tramite iif tun0 lookup mainregola.

  2. Quando ho sostituito tun0con loovunque, allora ha funzionato per me.

Ho anche provato

  1. Disattivazione del filtro del percorso inverso, rp_filter=0in/etc/sysctl.conf

Rispondi alla risoluzione dei problemi

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

Fonti modificate dalla risposta sono anche qui .

Risposte:


10

Quindi, nella tua configurazione, tutti i pacchetti che provi a inviare alla rete originariamente originari 10.0.0.1(perché stanno attraversando l' tun0interfaccia e il suo indirizzo locale è 10.0.0.1). Catturi i pacchetti, tutto va bene finora.
Ora tun0invia ulteriormente i pacchetti. L'indirizzo di origine è 10.0.0.1e vuoi che i pacchetti escano attraverso un'interfaccia diversa ( wlp2s0nel tuo caso). Questo è il routing, quindi abilitiamo prima il routing:

sysctl -w net.ipv4.ip_forward=1

Dopo di che, se si guarda a tcpdumpper wlp2s0è possibile notare i pacchetti in uscita con indirizzo sorgente 10.0.0.1e non con l'indirizzo sorgente dell'interfaccia wlan (quello che ti aspetteresti credo). Quindi dobbiamo cambiare l'indirizzo di origine e si chiama sorgente NAT . In linux è facile con l'aiuto di netfilter / iptables :

iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE

Controlla anche che la tua FORWARDcatena abbia una ACCEPTpolitica o che dovresti consentire l'inoltro con qualcosa come:

iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT

Ora tutto dovrebbe funzionare: il kernel Linux esegue il routing, sta spostando i pacchetti tun0dall'interfaccia a wlp2s0. netfilter dovrebbe cambiare l'IP di origine 10.0.0.1al vostro wlp2s0interfaccia indirizzo assegnato per i pacchetti in uscita. Memorizza tutte le connessioni e quando i pacchetti di risposta tornano (se presenti) cambia l'indirizzo di destinazione dell'indirizzo wlp2s0assegnato all'interfaccia in 10.0.0.1(la funzione "conntrack").
Bene, dovrebbe ma non lo fa. Sembra che netfilter si confonda con questa complicata configurazione di routing e con il fatto che lo stesso pacchetto passa prima attraverso la OUTPUTcatena e poi viene instradato e arriva alla PREROUTINGcatena. Almeno su Debian 8 box non funziona.
Il modo migliore per risolvere netfilter è la TRACEfunzione:

modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE

Abilito solo la traccia per i pacchetti ICMP, è possibile utilizzare altri filtri per il debug.
Mostrerà quali tabelle e catene attraversa il pacchetto. E vedo che il pacchetto non va oltre la FORWARDcatena (e non viene catturato dalla nat/POSTROUTINGcatena che effettivamente lo fa SNAT).
Di seguito sono riportati diversi approcci per farlo funzionare.

APPROCCIO # 1

Il modo migliore per annullare la confusione di netfilter è cambiare l'indirizzo IP di origine dei pacchetti tun0.cnell'applicazione. È anche il modo più naturale. Dobbiamo cambiare da 10.0.0.1 a 10.0.0.2 sulla strada verso l'esterno e da 10.0.0.2 a 10.0.0.1 sulla via del ritorno.
Ho modificato tun0.ccon il codice di modifica dell'indirizzo di origine. Ecco il nuovo file ed ecco il file di patch per il tuo tun0.c. Le modifiche all'intestazione IP implicano anche la correzione del checksum , quindi ho preso del codice dal progetto OpenVPN . Ecco l'elenco completo dei comandi che eseguo dopo un riavvio pulito e tun0_changeip.clancio:

ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE

In questo caso non è necessario disattivare il filtro del percorso inverso , poiché tutto è legale: tun0riceve e invia solo pacchetti che appartengono alla sua sottorete. Inoltre è possibile eseguire un routing basato sull'origine anziché basato sull'interfaccia.

APPROCCIO # 2

È possibile farlo SNATprima che l' tun0interfaccia del pacchetto raggiunga . Non è molto corretto però. In questo caso dovrai sicuramente disattivare il filtro del percorso inverso :

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Ora, SNATesegui: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT - to-source ip.address.of.your.wlan.interface

Qui cambiamo l'indirizzo sorgente appena prima che i pacchetti raggiungano il tun0dispositivo. tun0.cil codice invia nuovamente questi pacchetti "così come sono" (con l'indirizzo di origine modificato) e vengono instradati correttamente attraverso l'interfaccia wlan. Ma potresti avere un IP dinamico sull'interfaccia wlan e vuoi usarlo MASQUERADE(per non specificare esplicitamente l'indirizzo dell'interfaccia). Ecco come è possibile utilizzare MASQUERADE:

iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE

Si prega di notare l '" 10.0.55.1" indirizzo IP - è diverso. Puoi usare qualsiasi IP qui, non importa. I pacchetti raggiungono la nat/POSTROUTINGcatena wlp2s0sull'interfaccia se prima cambiamo l'IP di origine. E ora non dipende da un IP statico per l'interfaccia wlan.

APPROCCIO # 3

Puoi anche usare fwmark. In questo modo non è necessario SNATma dovrete catturare i pacchetti solo in uscita:
In primo luogo abbiamo bisogno di disabilitare il percorso inverso di filtraggio per tun0perché sarà inoltrare i pacchetti che appartengono a un'altra rete:

sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0

Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John

# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John

Questo è un altro "hack" per routing e netfilter che funziona sul mio Debian 8 box, ma consiglio comunque di adottare il primo approccio in quanto è più naturale e non usa alcun hack.


Puoi anche considerare di creare la tua applicazione come proxy trasparente . Penso che sarebbe molto più semplice invece di analizzare i pacchetti dal dispositivo tun.


Ho dovuto usare -j SNAT, non-s SNAT
ilyaigpetrov il

Funziona ma le prestazioni sono molto intermittenti (potrebbe bloccarsi per 10 secondi, quindi continuare a funzionare). Ho intenzione di capire perché succede e come risolverlo.
ilyaigpetrov,

1
Mi dispiace è stato il mio errore di battitura. Ho aggiunto un altro approccio alla mia risposta. Non ho idea del problema delle prestazioni. A proposito, perché non utilizzare un proxy trasparente con DNAT iptables per filtrare e deviare il traffico?
tifssoft,

Non sono in grado di riprodurre il tuo approccio mark, l'ho aggiunto solo sudo ip rule add iif tun0 lookup main priority 500ad esso, ma comunque non ha funzionato. Mi piace questo approccio, peccato che non riesca a riprodurlo.
ilyaigpetrov,

1
Grazie per il tuo nuovo approccio, l'ho seguito passo dopo passo e ha funzionato perfettamente. Eppure non capisco perché dobbiamo cambiare ips, soprattutto funziona. Nel caso in cui i miei piani con proxy TCP falliscano, potrò tornare alla tua risposta. Hai mostrato molte abilità di networking qui e non dubito che le tue abilità saranno ambite. In bocca al lupo!
ilyaigpetrov,
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.