Soluzione 1:
Ho utilizzato con successo quanto segue su Linux per testare il throughput su una nuova scheda a doppia porta da 10 Gbps in modalità "loopback", ovvero una porta collegata direttamente all'altra. Questo è solo un po 'di voodoo solo per forzare i pacchetti fuori dal cavo, ma se non lo fai, Linux cortocircuiterà semplicemente il traffico attraverso il kernel (da qui la domanda dell'OP). Nella risposta di Casey sopra, non sono sicuro se fosse davvero necessario disporre di un router esterno o meno, ma quanto segue è completamente autonomo. Le due interfacce sono eth2 e eth3.
Dai gli IP alle interfacce e mettili su 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 false utilizzate per raggiungere l'altra. All'uscita, fornisci il NAT alla tua falsa rete. All'ingresso, 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 precompila le voci arp (assicurati di sostituire i tuoi indirizzi MAC, non usare il mio):
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
Questo inganna Linux abbastanza da mettere effettivamente i pacchetti sul cavo. Ad esempio:
ping 10.60.1.1
esce eth2, l'IP di origine 10.50.0.1 viene NATtato a 10.60.0.1 e quando entra in eth3 la destinazione 10.60.1.1 viene NATtata a 10.50.1.1. E la risposta fa un viaggio simile.
Ora usa iperf per testare il throughput. Collegati agli IP corretti e assicurati quale IP stai contattando (l'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 sia realmente in uscita:
tcpdump -nn -i eth2 -c 500
Puoi anche guardare /proc/interrupts solo per essere assolutamente sicuro che la carta sia in uso:
while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done
Ad ogni modo, ho trovato questo post alla ricerca di come farlo, grazie per le domande e risposte ragazzi, e spero che questo aiuti chiunque altro a trovare questo post in futuro.
Soluzione 2:
Come sempre - sono un po' in ritardo - ma al giorno d'oggi si potrebbero usare gli spazi dei nomi di rete per isolare le interfacce e impedire qualsiasi inoltro locale (e giocherellare con iptables :)).
Crea spazi dei nomi (tutto fatto con le autorizzazioni richieste, ad esempio come root):
ip netns add ns_server
ip netns add ns_client
Tieni presente che ora è necessario accedere allo stato/configurazione delle interfacce all'interno del contesto dello spazio dei nomi assegnato, quindi non verranno visualizzate se esegui un ip link nudo poiché 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 la configurazione 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 stack di rete, l'interfaccia, il routing... è isolato dagli spazi dei nomi in modo che il kernel non sia in grado di far corrispondere 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 tutta la configurazione eseguita all'interno dello spazio dei nomi scompare (ad esempio, non è necessario eliminare gli indirizzi IP assegnati).
Soluzione 3:
Ho ampliato la risposta di caladona poiché non riuscivo a vedere i pacchetti di risposta. Per questo esempio:
- Sul mio PC locale ho NIC su diverse sottoreti, 192.168.1/24 , 192.168.2/24
- È presente un router/PC esterno che ha accesso a entrambe le sottoreti.
- Desidero inviare traffico bidirezionale sulle NIC del PC locale.
- La configurazione richiede due indirizzi IP inutilizzati per ciascuna sottorete.
Le rotte iptable del PC locale sono impostate sul traffico in uscita SNAT e DNAT 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:
- Riscrivi la sorgente 192.168.2.1 in 192.168.2.100 sui pacchetti in uscita
- Riscrivi la destinazione 192.168.1.100 in 192.168.1.1 sui pacchetti in arrivo
- Riscrivi la sorgente 192.168.1.1 in 192.168.1.100 sui pacchetti in uscita
- Riscrivi la destinazione 192.168.2.100 in 192.168.2.1 sui pacchetti in arrivo
Per riassumere, il sistema locale ora può comunicare con una macchina "virtuale" con 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 falso IP. Puoi farlo creando un percorso diretto agli IP attraverso il router. Vuoi assicurarti di forzare i pacchetti sull'opposto 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 questo, il router esterno deve sapere come raggiungere gli IP contraffatti sul tuo PC locale. Puoi farlo 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 forza l'uscita dei pacchetti dall'interfaccia .2. L'invio di dati alla sottorete .2 forza l'uscita dei pacchetti dall'interfaccia .1.
ping 192.168.1.100
ping 192.168.2.100
Soluzione 4:
Ok, finalmente sono riuscito a impostare la mia configurazione.
L'idea è di utilizzare un altro indirizzo falso, per forzare il percorso di questo indirizzo falso all'interfaccia 2 , quindi 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.
Forse è possibile utilizzare una configurazione più semplice con un solo cavo incrociato, ma siccome non ho provato preferisco fornire la mia soluzione funzionante.