Forza il traffico IP locale verso un'interfaccia esterna


30

Ho una macchina con diverse interfacce che posso configurare come voglio, ad esempio:

  • eth1: 192.168.1.1
  • eth2: 192.168.2.2

Vorrei inoltrare tutto il traffico inviato a uno di questi indirizzi locali attraverso l'altra interfaccia. Ad esempio, tutte le richieste a un server iperf, ftp, http a 192.168.1.1 non devono essere semplicemente instradate internamente, ma inoltrate tramite eth2 (e la rete esterna si occuperà di reindirizzare il pacchetto a eth1).

Ho provato e guardato diversi comandi, come iptables, ip route, ecc ... ma niente ha funzionato.

Il comportamento più vicino che ho potuto ottenere è stato fatto con:

ip route change to 192.168.1.1/24 dev eth2

che invia tutti i 192.168.1.x su eth2, ad eccezione di 192.168.1.1 che viene comunque instradato internamente. Potrei quindi fare l'inoltro NAT di tutto il traffico diretto al falso 192.168.1.2 su eth1, reindirizzato internamente al 192.168.1.1? In realtà sto lottando con iptables, ma è troppo difficile per me.

L'obiettivo di questa configurazione è eseguire i test del driver di interfaccia senza utilizzare due PC.

Sto usando Linux, ma se sai come farlo con Windows, lo comprerò!

Modificare:

La rete esterna è solo un cavo incrociato tra eth1 ed eth2. Diciamo che ho un server http sulla mia macchina. Ora voglio accedere a questo server dalla stessa macchina, ma voglio forzare il traffico TCP / IP a passare attraverso questo cavo eth1 / eth2. Come devo configurare le mie interfacce per questo?


Stai dicendo che vuoi che tutto il traffico venga replicato attraverso l'interfaccia 1 e 2 ma che venga restituito all'interfaccia 2 solo da un altro router? Non potrebbe fare qualcosa di piuttosto strano sulla rete? Sarebbe meglio indirizzare il traffico con mirroring dall'interfaccia 2 a un altro sistema che ha appena lasciato cadere il traffico e quindi è possibile monitorarlo o utilizzare un software di virtualizzazione per acquisire il traffico? Forse mi manca qualcosa nella descrizione.
Bart Silverstrim,

Sembra che voglia generare un pacchetto per, diciamo, 192.168.1.1 che è l'IP di eth1. Ma invece che lo stack Linux riceva quel pacchetto interamente internamente, desidera che il pacchetto venga espulso eth2 (che verrà consegnato esternamente in eth1 e quindi nello stack Linux). Non sono sicuro che ciò sia possibile; una volta che il livello di rete rileva che l'indirizzo è un'interfaccia interna, avrà poche ragioni per esaminare le tabelle di routing. Qualcun altro potrebbe conoscerlo meglio.
PP.

Risposte:


14

Ho ampliato la risposta di Caladona poiché non ho potuto vedere i pacchetti di risposta. Per questo esempio:

  1. Sul mio PC locale ho schede di rete su diverse sottoreti, 192.168.1 / 24 , 192.168.2 / 24
  2. Esiste un router / PC esterno che ha accesso a entrambe le sottoreti.
  3. Voglio inviare traffico bidirezionale tramite le schede di rete sul PC locale.
  4. La configurazione richiede due indirizzi IP inutilizzati per ciascuna sottorete.

Le route iptable del PC locale sono impostate su SNAT e DNAT traffico in uscita verso l'IP "falso".

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100
iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1
iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100
iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

Le regole fanno quanto segue:

  1. Riscrivi la fonte 192.168.2.1 su 192.168.2.100 sui pacchetti in uscita
  2. Riscrivi la destinazione 192.168.1.100 su 192.168.1.1 sui pacchetti in arrivo
  3. Riscrivi la fonte 192.168.1.1 su 192.168.1.100 sui pacchetti in uscita
  4. Riscrivi la destinazione 192.168.2.100 su 192.168.2.1 sui pacchetti in entrata

Per riassumere, il sistema locale ora può parlare con una macchina "virtuale" con gli indirizzi 192.168.1.100 e 192.168.2.100.

Successivamente devi forzare il tuo PC locale a utilizzare il router esterno per raggiungere il tuo IP falso. Puoi farlo creando un percorso diretto verso l'IP attraverso il router. Vuoi assicurarti di forzare i pacchetti sul contrario della sottorete di destinazione.

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 
ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

Infine, per far funzionare tutto ciò, il router esterno deve sapere come raggiungere gli IP falsi sul PC locale. Puoi fare le cose attivando gli ARP proxy per il tuo sistema.

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

Con questa configurazione, ora puoi trattare gli IP falsi come un vero sistema sul tuo PC locale. L'invio di dati alla sottorete .1 costringerà i pacchetti a uscire dall'interfaccia .2. L'invio di dati alla sottorete .2 costringerà i pacchetti a uscire dall'interfaccia .1.

ping 192.168.1.100
ping 192.168.2.100

Molto meglio a modo tuo! Nota che ho anche bisogno di un ip_forward per far funzionare le cose ARP: echo 1> / proc / sys / net / ipv4 / ip_forward
calandoa

28

Ho usato con successo quanto segue su Linux per testare il throughput su una nuova scheda da 10 Gbps a doppia porta in modalità "loopback", ovvero una porta collegata direttamente all'altra. Questo è solo un po 'di voodoo solo per forzare i pacchetti fuori dal filo, ma se non lo fai, Linux cortocircuiterà il traffico attraverso il kernel (da qui la domanda dell'OP). Nella risposta di Casey sopra, non sono sicuro che fosse davvero necessario avere un router esterno o non sopra, ma quanto segue è completamente autonomo. Le due interfacce sono eth2 ed eth3.

Fornisci gli IP alle interfacce e inseriscili in reti separate:

ifconfig eth2 10.50.0.1/24
ifconfig eth3 10.50.1.1/24

Successivamente creeremo un doppio scenario NAT: due nuove reti fasulle utilizzate per raggiungere l'altra. Sulla via d'uscita, fonte NAT alla tua rete falsa. Sulla strada, fissa la destinazione. E viceversa per l'altra rete:

# nat source IP 10.50.0.1 -> 10.60.0.1 when going to 10.60.1.1
iptables -t nat -A POSTROUTING -s 10.50.0.1 -d 10.60.1.1 -j SNAT --to-source 10.60.0.1

# nat inbound 10.60.0.1 -> 10.50.0.1
iptables -t nat -A PREROUTING -d 10.60.0.1 -j DNAT --to-destination 10.50.0.1

# nat source IP 10.50.1.1 -> 10.60.1.1 when going to 10.60.0.1
iptables -t nat -A POSTROUTING -s 10.50.1.1 -d 10.60.0.1 -j SNAT --to-source 10.60.1.1

# nat inbound 10.60.1.1 -> 10.50.1.1
iptables -t nat -A PREROUTING -d 10.60.1.1 -j DNAT --to-destination 10.50.1.1

Ora dì al sistema come raggiungere ogni rete falsa e prepopola le voci arp (assicurati di sostituire i tuoi indirizzi MAC, non usare i miei):

ip route add 10.60.1.1 dev eth2
arp -i eth2 -s 10.60.1.1 00:1B:21:C1:F6:0F # eth3's mac address

ip route add 10.60.0.1 dev eth3 
arp -i eth3 -s 10.60.0.1 00:1B:21:C1:F6:0E # eth2's mac address

Ciò inganna Linux abbastanza da mettere effettivamente i pacchetti sul filo. Per esempio:

ping 10.60.1.1

esce eth2, l'IP 10.50.0.1 di origine diventa NATted a 10.60.0.1 e quando entra in eth3 la destinazione 10.60.1.1 diventa NATted a 10.50.1.1. E la risposta prende un viaggio simile.

Ora usa iperf per testare il throughput. Associa gli IP corretti e assicurati quale IP stai contattando (indirizzo falso dell'altra estremità):

# server
./iperf -B 10.50.1.1 -s

# client: your destination is the other end's fake address
./iperf -B 10.50.0.1 -c 10.60.1.1 -t 60 -i 10

Assicurati che il traffico stia davvero arrivando al cavo:

tcpdump -nn -i eth2 -c 500

Puoi anche guardare / proc / interrupt solo per essere assolutamente sicuro che la scheda sia in uso:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

Comunque, ho trovato questo post alla ricerca di come farlo, grazie per i ragazzi di domande e risposte, e spero che questo aiuti chiunque altro a trovare questo post in futuro.


+1 Ottima soluzione - questo non richiede nemmeno l'attivazione dell'IP-forwarding! Questo è proprio quello di cui avevo bisogno in questo momento (per test da 10 GB tramite loopback).
Nils,

16

Come sempre - sono un po 'in ritardo - ma oggigiorno si possono usare gli spazi dei nomi di rete per isolare le interfacce e prevenire qualsiasi inoltro locale (e armeggiare con iptables :)).

Creare spazi dei nomi (tutto fatto con le autorizzazioni necessarie, ad es. Come root):

ip netns add ns_server
ip netns add ns_client

Si noti che ora è necessario accedere allo stato / alla configurazione delle interfacce nel contesto dello spazio dei nomi assegnato, quindi non verranno visualizzati se si esegue un collegamento ip nudo poiché questo viene eseguito nel contesto dello spazio dei nomi predefinito. L'esecuzione di un comando all'interno di uno spazio dei nomi può essere eseguita utilizzando

ip netns exec <namespace-name> <command>

come prefisso.

Ora assegna gli spazi dei nomi alle interfacce, applica config e imposta le interfacce:

ip link set eth1 netns ns_server
ip netns exec ns_server ip addr add dev eth1 192.168.1.1/24
ip netns exec ns_server ip link set dev eth1 up
ip link set eth2 netns ns_client
ip netns exec ns_client ip addr add dev eth2 192.168.1.2/24
ip netns exec ns_client ip link set dev eth2 up

Ora puoi eseguire le applicazioni all'interno dello spazio dei nomi - per l'esecuzione del server iperf

ip netns exec ns_server iperf -s -B 192.168.1.1

e il cliente:

ip netns exec ns_client iperf -c 192.168.1.1 -B 192.168.1.2

Il traffico verrà ora inviato tramite le interfacce fisiche poiché l'intero networkstack, l'interfaccia, il routing ... è isolato dagli spazi dei nomi, quindi il kernel non è in grado di abbinare gli indirizzi utilizzati all'interno del traffico con le interfacce locali (disponibili).

Se hai finito con i tuoi esperimenti, elimina semplicemente gli spazi dei nomi:

ip netns del <namespace-name>

Le interfacce verranno riassegnate allo spazio dei nomi predefinito e scompare tutta la configurazione effettuata nello spazio dei nomi (ad es. Non è necessario eliminare gli indirizzi IP assegnati).


Questo è molto più semplice della magia a doppia natura che viene suggerita, e non richiede alcun coordinamento da altri computer sulla rete né assume alcuna topologia fisica. La mia unica richiesta sarebbe quella di aggiungere comandi per aggiungere percorsi.
Huckle,

2

Ok, finalmente sono riuscito a configurare la mia configurazione.

L'idea è di utilizzare un altro indirizzo falso, per forzare il percorso di questo indirizzo falso all'interfaccia 2, quindi per tradurre l'indirizzo falso con l'indirizzo reale 2 con NAT / iptables.

La mia configurazione è in realtà composta da un router che posso telnet tra IF1 (interfaccia 1) e IF2

Nella mia configurazione, FAKE_ADDR e IF1_ADDR si trovano sulla stessa sottorete.

ifconfig $IF1 $IF1_ADDR netmask 255.255.255.0
ifconfig $IF2 $IF2_ADDR netmask 255.255.255.0

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR
iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

E sul router:

route add $FAKE_ADDR gw $IF2_ADDR

Se invio qualcosa a FAKE_ADDR, pkt viene inoltrato tramite IF1 al router, inoltrato nuovamente a IF2, quindi FAKE_IP viene sostituito da IF2_ADDR. Il pacchetto viene elaborato dal server, il risultato viene rispedito a IF1_ADDR, da IF2_ADDR che viene sostituito da FAKE_ADDR.

Potrebbe essere possibile utilizzare una configurazione più semplice con un solo cavo crossover, ma come non ho provato preferisco dare la mia soluzione di lavoro.


se il router invia $ FAKE_ADDR a $ IF2_ADDR, la tua regola DNAT non deve essere "-i $ IF2" anziché "-i $ IF1"?
cmcginty

Hai ragione Casey, correzione fatta.
calandoa,

1

La risposta data sopra da Thomas Tannhäuser è stata perfetta!

Ho avuto una situazione simile: una singola macchina con due interfacce enet. Il mio piano era di utilizzare un'interfaccia come server (destinatario) e l'altra come client (mittente). Ogni interfaccia verrebbe collegata al router e iperf indirizzerebbe il traffico attraverso il router per misurare throughput, PPS, ritardo, ecc.

Sfortunatamente, l'approccio iptables era non intuitivo e pieno di problemi. Dopo alcune ore frustranti, ho abbandonato questo piano di attacco. Ispirato al suggerimento di Thomas, ho fatto un po 'di compiti a casa su Linux IP Namespace e ho iniziato ad apprezzare la semplicità e l'eleganza di questa soluzione.

Di seguito è riportato un elenco dei comandi esatti che ho usato per configurare il mio Fedora FC26 per servire con questa capacità. Le due interfacce sono enp1s0 e enp3s0. Il router ha due interfacce con gli indirizzi 192.168.2.112 e 172.16.16.2. Ogni connettore ENET FC26 è collegato direttamente alla corrispondente interfaccia del router.

# How to configure the IP Namespaces
ip netns add iperf-server
ip netns add iperf-client
ip link set enp1s0 netns iperf-server
ip link set enp3s0 netns iperf-client
ip netns exec iperf-server ip addr add dev enp1s0 192.168.2.139/20
ip netns exec iperf-client ip addr add dev enp3s0 172.16.16.2/24
ip netns exec iperf-client ip link set dev enp3s0 up
ip netns exec iperf-server ip link set dev enp1s0 up
ip netns exec iperf-server route add default gw 192.168.2.112
ip netns exec iperf-client route add default gw 172.16.16.1

# Test the interfaces and network using ping
ip netns exec iperf-client ping -c1 172.16.16.1
ip netns exec iperf-server ping -c1 192.168.2.112
ip netns exec iperf-server ping -c1 172.16.16.2
ip netns exec iperf-client ping -c1 192.168.2.139

# Start Iperf Server for UDP test
ip netns exec iperf-server iperf -u -s
# Run Client against Iperf server for UDP test
ip netns exec iperf-client iperf -u -c 192.168.2.139

0

Sembra che tu voglia trasformare il tuo box Linux in un box router / bridge / gateway / firewall. Le seguenti risorse potrebbero essere quello che stai cercando:

Il progetto del router Linux

Elenco delle distribuzioni di router o firewall

Router LiveCD Linux

Linux Journal - Il router Linux

Aggiornamento basato su ulteriori informazioni:

Non penso che sarai in grado di fare quello che vuoi. Il sistema operativo guarderà sempre la sua tabella di routing interna e 'vedrà' entrambi gli indirizzi IP localmente. Quindi indirizzerà il traffico all'interno del sistema operativo e non lo inserirà mai nel cavo. Avrai bisogno di una seconda macchina o due macchine virtuali (controlla Xen ).


0

Un sacco di cose da fare qui, quindi non posso garantire totalmente la mia precisione, ma la domanda originale sembra essere alla ricerca di ciò che è noto come tecnica "invia a se stesso" . La ricerca collegata mostra quella che penso sia la patch del kernel meglio mantenuta come collegamento principale + discussioni e patch con altri approcci su varie mailing list, esp. LKML.

Penso che si dovrebbe anche guardare agli spazi dei nomi di rete , fatto con "ip netns" di iproute2 . Questo richiede anche qualche interfaccia aggiuntiva e magia di routing, quindi potrebbe non essere nemmeno meno complesso del massiccio hoopla di iptables nelle altre risposte.

Commenti sicuramente graditi se qualcuno trovasse qualcosa di utile con questi: il come, il cosa, il dove sulla tua implementazione.



-1

ecco come l'ho fatto funzionare per IPV6

IP statici assegnati

/sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
/sbin/ifconfig eth3 inet6 add 2001:db8::2/127 

imposta percorsi solo host verso indirizzi "FALSO"

ip -6 route add 2001:db8::2/128 dev eth1 metric 1
ip -6 route add 2001:db8::1/128 dev eth3 metric 1

popolato il tavolo Neighbor ... come l'arp

ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address

aggiunte le voci ip6tables

ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2

Quale distribuzione stai usando? L'ultima volta che ho controllato, il kernel non ha una tabella NAT per IPv6.
fukawi2,
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.