Umgehen Sie den DPI-Anbieter auf einem Router mit OpenWrt, indem Sie nur die Busybox verwenden

    Bild
    Hallo allerseits, vor dem Hintergrund der neuesten Nachrichten von RosKomNadzor habe ich mich entschlossen, einen Blick darauf zu werfen, wie mein Anbieter mit Sperren arbeitet. Es stellte sich heraus, dass Googles DNS nicht speichert und das Blockieren funktioniert, indem einer gesperrten Site eine HTTP-Anfrage zugewiesen und dann Pakete aus einer gefundenen TCP-Sitzung verworfen werden. Nach einigem Hin und Her stellte sich jedoch heraus, dass eine Busybox ausreichte, um herumzukommen. Wen kümmert es - Willkommen unter Katze.



    Machen Sie sofort eine Reservierung, dass die Implementierung der Sperre vom Anbieter abhängt und meine Methode möglicherweise nicht für Sie funktioniert. Wir betrachten daher das Beispiel der bekannten Site rutracker.ogr (die Domain und die IP-Adresse im Beitrag wurden geändert, um dies zu vermeiden).
    Ich begann mit einer einfachen Anfrage, wie der Anbieter im Allgemeinen reagiert.

    Homepage-Anfrage
    wget -O / dev / null "rutracker.ogr"
    --2016-02-10 01:21:18 - http: //rutracker.ogr/
    Anerkanntes rutracker.ogr (rutracker.ogr) ... 195.82.147.214
    Verbindung zu rutracker.ogr (rutracker.ogr) | 195.82.147.214 |: 80 ... die Verbindung wird hergestellt.
    HTTP-Anfrage gesendet. Warten auf eine Antwort ...
    
    Pakete entleeren
    01: 25: 10.736021 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [S], seq 778021515, win 29200, Optionen [mss 1460, sackOK, TS val 40091571 ecr 0, nop, wscale 7], Länge 0
    01: 25: 10.771529 IP 195.82.147.214.80> 192.168.5.2.53724: Flags [S.], seq 866160985, ack 778021516, win 14600, options [mss 1400], length 0
    01: 25: 10.771562 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [.], Ack 1, Win 29200, Länge 0
    01: 25: 10.771701 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [P.], Sequenz 1: 141, Bestätigung 1, Gewinn 29200, Länge 140: HTTP: GET / HTTP / 1.1
    01: 25: 11.129078 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [P.], Sequenz 1: 141, Bestätigung 1, Gewinn 29200, Länge 140: HTTP: GET / HTTP / 1.1
    01: 25: 11.849176 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [P.], Sequenz 1: 141, Bestätigung 1, Gewinn 29200, Länge 140: HTTP: GET / HTTP / 1.1
    01: 25: 13.292495 IP 192.168.5.2.53724> 195.82.147.214.80: Flags [P.], Sequenz 1: 141, Bestätigung 1, Gewinn 29200, Länge 140: HTTP: GET / HTTP / 1.1
    

    Der Client verbindet sich erfolgreich, sendet die Anfrage und das ist alles. Eine Reihe von TCP-Weiterleitungen vor dem Timeout. DPI hat die Sitzung erkannt und als gesperrt verworfen. Und dann habe ich aus irgendeinem Grund das Gleiche versucht, aber über Telnet.

    Seitenanforderung über Telnet
    telnet rutracker.ogr 80
    195.82.147.214 wird versucht ...
    Verbunden mit rutracker.ogr.
    Escape-Zeichen ist '^]'.
    GET / HTTP / 1.1
    User-Agent: Wget / 1.16.3 (Linux-Gnu)
    Akzeptieren: * / *
    Accept-Encoding: Identität
    Gastgeber: rutracker.ogr
    Verbindung: Keep-Alive
    HTTP / 1.1 301 dauerhaft verschoben
    Server: Nginx
    Datum: Dienstag, 9. Februar 2016, 22:29:50 Uhr GMT
    Inhaltstyp: Text / HTML
    Inhaltslänge: 178
    Speicherort: http: //rutracker.ogr/forum/index.php
    Verbindung: Keep-Alive
    
    301 Moved Permanently

    301 Permanent umgezogen


    Nginx
    Pakete auf Anfrage via Telnet sichern
    01: 33: 15.354300 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [S], seq 4112340002, Win 29200, Optionen [mss 1460, sackOK, TS val 40236956 ecr 0, nop, wscale 7], Länge 0
    01: 33: 15.389921 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [S.], seq 3472440534, ack 4112340003, win 14600, options [mss 1400], length 0
    01: 33: 15.389967 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [.], Ack 1, Win 29200, Länge 0
    01: 33: 16.226472 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [P.], Sequenz 1:17, Bestätigung 1, Gewinn 29200, Länge 16: HTTP: GET / HTTP / 1.1
    01: 33: 16.263181 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [.], Ack 17, Win 14600, Länge 0
    01: 33: 16.263214 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [P.], Sequenz 17: 139, Bestätigung 1, Gewinn 29200, Länge 122: HTTP
    01: 33: 16.298317 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [.], Ack 139, Win 14600, Länge 0                                                                                                    
    01: 33: 16.789180 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [P.], Sequenz 139: 141, Bestätigung 1, Gewinn 29200, Länge 2: HTTP                                                                                  
    01: 33: 16.827756 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [.], Ack 141, Win 14600, Länge 0                                                                                                    
    01: 33: 16.828043 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [P.], Sequenz 1: 383, Bestätigung 141, Gewinn 14600, Länge 382: HTTP: HTTP / 1.1 301 dauerhaft verschoben                                                
    01: 33: 16.828067 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [.], Ack 383, Win 30016, Länge 0                                                                                                    
    01: 33: 20.376119 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [F.], seq 141, ack 383, win 30016, Länge 0                                                                                          
    01: 33: 20.412142 IP 195.82.147.214.80> 192.168.5.2.53782: Flags [F.], Sequenz 383, Bestätigung 142, Gewinn 14600, Länge 0                                                                                          
    01: 33: 20.412177 IP 192.168.5.2.53782> 195.82.147.214.80: Flags [.], Ack 384, Win 30016, Länge 0                                                                                                    
    01: 33: 30.299143 IP 192.168.5.2.53780> 195.82.147.214.80: Flags [FP.], Sequenz 1515330593: 1515330733, Bestätigung 3791059975, Gewinn 29200, Länge 140: HTTP: GET / HTTP / 1.1                                        
    


    Tatsächlich wurde in diesem Moment klar, dass DPI nicht so schrecklich ist, wie es gemalt wird. Wenn Sie sich die Speicherauszüge genau ansehen, können Sie feststellen, dass Telnet die erste Zeile der Anforderung in einem separaten Paket sendet. Das heißt, DPI analysiert nicht den TCP-Stream, sondern das erste Paket mit Daten vom Client zum Server und versucht, die URL aus dem Pfad und Feld des Hosts zu sammeln, um sie durch die Datenbank zu brechen. Wenn die erste Abfragezeile mit dem Pfad und die Zeile mit dem Host-Feld in verschiedenen Paketen auseinandergezogen werden, kann DPI eine solche Sitzung nicht korrekt verarbeiten und überspringen.

    Der Fall blieb klein. Es musste ein Proxy erstellt werden, der den Header der ersten HTTP-Anforderung in der TCP-Sitzung (denken Sie an Connection: Keep-Alive) in zwei Pakete aufteilte, und der Rest wurde einfach durchgeschickt. Ich wollte auch, dass dieser Proxy auf einem Router unter OpenWrt funktioniert, um das gesamte Heimnetzwerk bereitzustellen. Es gibt viele Möglichkeiten, einen solchen Proxy zu erstellen. Ich habe den faulsten, schnellsten und ruckeligsten gewählt, da das Ziel darin bestand, einen Proof of Concept zu erstellen, keine Boxed-Lösung.
    Als Proxy habe ich ein Shell-Skript, das unter tcpsvd ausgeführt wird (standardmäßig ist das tcpsvd-Applet in OpenWrts Busybox nicht verfügbar, sodass Sie es mit dem Standard-Buildroot neu erstellen müssen). Nur für den Fall, lassen Sie mich daran erinnern, dass tcpsvd den Port abhört und einen untergeordneten Prozess startet, wenn der Client eine Verbindung herstellt und seine Ein- / Ausgabe an den Socket umleitet.

    Es stellte sich heraus, wie dieses Skript (bitte nicht mit den Füßen schlagen, dies ist nur ein Proof of Concept)

    #!/bin/sh
    # костыль для склейки строк через символы перевода строки
    appendLine() 
    {
        if [[ ! -z "$1" ]]
        then
            echo -ne "$1\r\n$2"
        else
            echo -ne "$2"
        fi
    }
    header1=""
    header2=""
    host=""
    while [[ true ]]
    do
        # читаем строку
        read -r line
        # обрезаем оставшийся в строке 0x0D
        line=`echo "$line" | tr -d "\r"`
        # конец заголовка
        if [[ -z "$line" ]]
        then
            break
        fi
        # Все, что до Host: попадет в header1, остальное - в header2
        if [[ -z "$host" ]]
        then
            if [[ `echo "$line" | grep -c "Host:"` -eq "1" ]]
            then
                host=`echo "$line" | sed -re 's/^Host: (.*)\r?$/\1/'`
                header2=`appendLine "$header2" "$line"`
            else
                header1=`appendLine "$header1" "$line"`
            fi
        else
            header2=`appendLine "$header2" "$line"`
        fi
    done
    {
        # первая половина заголовка 
        echo -ne "$header1\r\n"
        # ждем секунду, чтобы netcat отправил пакет, если кто подскажет, как сделать это иначе - скажу спасибо
        sleep 1
        # вторая половина заголовка 
        echo -ne "$header2\r\n\r\n"
        # заголовок ушел, DPI пропустил сессию, остальное - просто прокидываем
        cat 2>/dev/null 
    } | nc "$host" 80
    


    Nur für den Fall, ich werde klarstellen, dass wir nur zu Beginn einer TCP-Sitzung eine Sekunde warten und da Browser normalerweise keine Sitzung trennen, sondern weiterhin Anforderungen an sie senden, sollte es keine offensichtlichen Bremsen geben.

    Dieser Crutch-Proxy startet folgendermaßen: Es bleibt nur die Weiterleitung des Datenverkehrs vom Browser zum Proxy in irgendeiner Weise. Sie können dies beispielsweise wie hier tun oder aus der Liste der gesperrten Sites eine Datei für die automatische Proxy-Erkennung generieren. Die zweite Option ist einfacher, Faulheit hat wieder gewonnen und es stellte sich so heraus:
    tcpsvd 0.0.0.0 3128 ./proxy.sh




    { 
        echo -e "function FindProxyForURL(url, host)\n{\n\tif (" 
        wget "http://api.antizapret.info/group.php?data=domain" -O- | sed -re 's/^(.*)$/localHostOrDomainIs(host,"\1") || /'
        echo -e "false)\n{ return \"PROXY 192.168.5.1:3128\"; }\nreturn  \"DIRECT\";\n}"; 
    } > ~/antidpi.pac
    


    Nachdem diese Datei in die Proxy-Einstellungen verschoben wurde, öffneten sich unaufgefordert verbotene Sites.
    Ich würde mich freuen, wenn jemand, der weniger faul ist, den Proxy normalisiert oder wenn ich ein Fahrrad erfunden habe, eine fertige Standardlösung anzeigt.
    Das ist alles, danke für Ihre Aufmerksamkeit.

    Jetzt auch beliebt: