So lassen Sie den gesamten Datenverkehr unter Linux über eine Schnittstelle laufen

11

Ich habe eine selbstgeschriebene Schnittstelle tun0 ( TUN / TAP- basiert), die ausgibt, was sie empfängt.
Ich brauche den gesamten Datenverkehr des Systems, um durch diese Schnittstelle zu fließen.
Die Rolle der Schnittstelle ist:

  1. Um Pakete herauszufinden, die wahrscheinlich zensiert werden, und sie zu tunneln.
  2. Übergeben Sie den gesamten anderen Verkehr unberührt.

Wie Sie vermuten, versuche ich, ein Antizensur-Tool aufzubauen.
Die Entscheidung über das Tunneln muss innerhalb des tun0-Prozesses getroffen werden,
da nur dort vertrauenswürdiges DNS verwendet werden kann.

Ich brauche Ihre Hilfe, um mir zu zeigen, wie der gesamte Datenverkehr über eine selbst geschriebene Schnittstelle tun0 fließen kann. Wenn tun0 Änderungen benötigt, bitte ich Sie, solche Änderungen bereitzustellen.

Im Folgenden wird beschrieben, wie ich versucht habe, den gesamten Datenverkehr durch tun0 zu leiten, was fehlgeschlagen ist (Pings schlagen fehl).

Kompilieren

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

Konfigurieren

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. Tabelle erstellen John

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

Ordnung ist wichtig:

  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 
    

Fehlerbehebung

  1. sudo tcpdump -i wlp2s0 -qtln icmpund ping -I tun0 8.8.8.8zeigt dann an , dass keine Pakete erfasst wurden. Dies bedeutet, dass keine Pakete über die iif tun0 lookup mainRegel von tun0 an wlp2s0 übertragen werden .

  2. Als ich ersetzt tun0mit loüberall dann funktionierte es für mich.

Auch versucht

  1. Ausschalten der Rückwärtsfilterung, rp_filter=0in/etc/sysctl.conf

Antwort Fehlerbehebung

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

Geänderte Quellen aus der Antwort sind auch hier .

ilyaigpetrov
quelle

Antworten:

10

In Ihrer Konfiguration stammen also alle Pakete, von denen Sie versuchen, sie ursprünglich an das Netzwerk zu senden 10.0.0.1(weil sie über die tun0Schnittstelle gehen und deren lokale Adresse lautet 10.0.0.1). Sie erfassen die Pakete, alles ist soweit in Ordnung.
Nun tun0sendet die Pakete weiter. Die Quelladresse lautet 10.0.0.1und Sie möchten, dass die Pakete über eine andere Schnittstelle ( wlp2s0in Ihrem Fall) gesendet werden. Das ist Routing. Aktivieren Sie also zuerst das Routing:

sysctl -w net.ipv4.ip_forward=1

Wenn man sich danach sucht , wird tcpdumpfür wlp2s0Sie die Pakete mit Quelladresse verlassen bemerken können 10.0.0.1und nicht mit der Quelladresse des WLAN - Schnittstelle (was man erwarten würde glaube ich). Wir müssen also die Quelladresse ändern und sie heißt Quell-NAT . Unter Linux ist es mit Hilfe von Netfilter / Iptables einfach :

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

Bitte überprüfen Sie auch, ob Ihre FORWARDKette ACCEPTRichtlinien hat , oder Sie müssten die Weiterleitung mit etwas erlauben wie:

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

Jetzt sollte alles funktionieren: Der Linux-Kernel übernimmt das Routing, er verschiebt Pakete von der tun0Schnittstelle zur wlp2s0. netfilter sollte die Quell-IP 10.0.0.1in die von Ihrer wlp2s0Schnittstelle zugewiesene Adresse für Ausgabepakete ändern . Es speichert alle Verbindungen und wenn die Antwortpakete zurückgehen (falls sie), ändert es die Zieladresse der der wlp2s0Schnittstelle zugewiesenen Adresse 10.0.0.1(die "Conntrack" -Funktion).
Nun, es sollte, aber es tut es nicht. Es scheint, dass netfilter mit dieser komplizierten Routing-Konfiguration und der Tatsache verwechselt wird, dass dasselbe Paket zuerst die OUTPUTKette durchläuft und dann geroutet wird und zur PREROUTINGKette kommt. Zumindest bei Debian 8 Box funktioniert es nicht.
Der beste Weg zur Fehlerbehebung bei Netfilter ist die folgende TRACEFunktion:

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

Ich aktiviere nur die Ablaufverfolgung für ICMP-Pakete. Sie können zum Debuggen einen anderen Filter verwenden.
Es wird angezeigt, welche Tabellen und Ketten das Paket durchläuft. Und ich kann sehen, dass das Paket nicht weiter die FORWARDKette geht (und es wird nicht von der nat/POSTROUTINGKette gefangen, die es tatsächlich tut SNAT).
Im Folgenden finden Sie einige Ansätze, um diese Arbeit zu machen.

Ansatz Nr. 1

Der beste Weg, um den Netzfilter zu verwirren, besteht darin, die Quell-IP-Adresse der Pakete in der tun0.cAnwendung zu ändern . Es ist auch der natürlichste Weg. Wir müssen 10.0.0.1 auf dem Weg nach außen auf 10.0.0.2 und auf dem Rückweg auf 10.0.0.2 auf 10.0.0.1 ändern .
Ich habe tun0.cmit Quellcode geändert. Hier ist die neue Datei und hier ist eine Patchdatei für Ihre tun0.c. Änderungen am IP-Header beinhalten auch eine Prüfsummenkorrektur , daher habe ich Code aus dem OpenVPN-Projekt übernommen . Hier ist die vollständige Liste der Befehle, die ich nach einem sauberen Neustart und tun0_changeip.cStart ausführe :

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

Bitte beachten Sie, dass Sie in diesem Fall die Umkehrpfadfilterung nicht deaktivieren müssen , da alles legal ist - tun0nur Pakete empfangen und senden, die zu seinem Subnetz gehören. Sie können auch ein quellenbasiertes Routing anstelle eines schnittstellenbasierten Routings durchführen.

Ansatz Nr. 2

Dies ist möglich, SNATbevor die Paketschnittstelle erreicht tun0wird. Es ist jedoch nicht sehr richtig. In diesem Fall müssen Sie auf jeden Fall die Umkehrpfadfilterung deaktivieren :

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

Nun tun SNAT: iptables -t nat -A POSTROUTING- -o tun0 es 10.0.0.1 -j SNAT --to-Quelle ip.address.of.your.wlan.interface

Hier ändern wir die Quelladresse kurz bevor die Pakete das tun0Gerät erreichen. tun0.cCode sendet diese Pakete "wie sie sind" (mit geänderter Quelladresse) erneut und sie werden erfolgreich über die WLAN-Schnittstelle weitergeleitet. Möglicherweise haben Sie jedoch eine dynamische IP-Adresse für die WLAN-Schnittstelle und möchten diese verwenden MASQUERADE(um die Schnittstellenadresse nicht explizit anzugeben). So können Sie Folgendes nutzen 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

Bitte beachten Sie die " 10.0.55.1" IP-Adresse - es ist anders. Sie können hier jede IP verwenden, es spielt keine Rolle. Die Pakete erreichen die nat/POSTROUTINGKette auf der wlp2s0Schnittstelle, wenn wir zuvor die Quell-IP ändern. Und jetzt ist es nicht mehr von einer statischen IP für die WLAN-Schnittstelle abhängig.

Ansatz Nr. 3

Sie können auch verwenden fwmark. Auf diese Weise brauchen Sie nicht , SNATaber Sie werden nur ausgehende Pakete erfassen:
Erstens wir deaktivieren müssen umgekehrten Weg Filterung für , tun0weil es Pakete weiterleiten , die zu einem anderen Netzwerk gehören:

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

Das ist ein weiterer "Hack" für Routing und Netfilter , der auf meiner Debian 8-Box funktioniert, aber ich empfehle trotzdem, den ersten Ansatz zu wählen , da er natürlicher ist und keine Hacks verwendet.


Sie können Ihre Anwendung auch als transparenten Proxy erstellen . Ich denke, es wäre viel einfacher, als Pakete vom Tun-Gerät zu analysieren.

tifssoft
quelle
Ich musste verwenden -j SNAT, nicht-s SNAT
ilyaigpetrov
Es funktioniert, aber die Leistung ist sehr sporadisch (es kann für 10 Sekunden stehen bleiben und dann weiterarbeiten). Ich werde herausfinden, warum es passiert und wie man das behebt.
ilyaigpetrov
1
Entschuldigung, es war mein Tippfehler. Ich habe meiner Antwort einen anderen Ansatz hinzugefügt. Habe keine Ahnung von dem Leistungsproblem. Warum nicht einen transparenten Proxy mit iptables DNAT verwenden, um den Datenverkehr zu filtern und umzuleiten?
Tifssoft
Ich kann Ihren Markierungsansatz nicht reproduzieren. Ich habe nur hinzugefügt sudo ip rule add iif tun0 lookup main priority 500, aber es hat immer noch nicht funktioniert. Ich mag diesen Ansatz, schade, dass ich ihn nicht reproduzieren kann.
ilyaigpetrov
1
Vielen Dank für Ihren neuen Ansatz. Ich habe ihn Schritt für Schritt verfolgt und er hat perfekt funktioniert. Ich verstehe jedoch nicht, warum wir ips ändern müssen, vor allem funktioniert es. Falls meine Pläne mit dem TCP-Proxy fehlschlagen, kann ich zu Ihrer Antwort zurückkehren. Sie haben hier viele Netzwerkfähigkeiten gezeigt, und ich bezweifle nicht, dass Ihre Fähigkeiten begehrt sein werden. Viel Glück!
ilyaigpetrov