2012-07-10 16 views
6

Witryna http://openbook.etoro.com/#/main/ ma ywo co jest generowany przez javascript poprzez XHR keep-alive wniosków i uzyskiwanie odpowiedzi od serwera jako gzip skompresowane JSON ciąg.Perl - HTTP :: Proxy przechwytywania XHR/komunikacja JSON

Chcę przechwycić kanał do pliku.

Zwykły sposób (WWW :: Mech ..) jest (prawdopodobnie) nieopłacalny, ponieważ potrzeba zaawansowanej inżynierii wszystkich Javascriptów na stronie i symulowania przeglądarki jest naprawdę trudnym zadaniem, więc poszukuje alternatywnego rozwiązania.

Mój pomysł polega na zastosowaniu taktyki Man-in-the-middle, więc broswer wykona swoją pracę i chcę przechwycić komunikację za pośrednictwem perl proxy - dedykowanego tylko do tego zadania.

Jestem w stanie złapać początkową komunikację, ale nie sam plik danych. Proxy działa poprawnie, ponieważ w przeglądarce kanał działa tylko moje pliki nie działają.

use HTTP::Proxy; 
use HTTP::Proxy::HeaderFilter::simple; 
use HTTP::Proxy::BodyFilter::simple; 
use Data::Dumper; 
use strict; 
use warnings; 

my $proxy = HTTP::Proxy->new(
    port => 3128, max_clients => 100, max_keep_alive_requests => 100 
); 

my $hfilter = HTTP::Proxy::HeaderFilter::simple->new(
    sub { 
     my ($self, $headers, $message) = @_; 
     print STDERR "headers", Dumper($headers); 
    } 
); 

my $bfilter = HTTP::Proxy::BodyFilter::simple->new(
    filter => sub { 
     my ($self, $dataref, $message, $protocol, $buffer) = @_; 
     print STDERR "dataref", Dumper($dataref); 
    } 
); 

$proxy->push_filter(response => $hfilter); #header dumper 
$proxy->push_filter(response => $bfilter); #body dumper 
$proxy->start; 

Firefox jest skonfigurowany przy użyciu powyższego proxy dla całej komunikacji.

Kanał jest uruchomiony w przeglądarce, więc serwer proxy podaje dane. (Kiedy zatrzymuję proxy, kanał również się zatrzymuje). Losowo (nie mogę zrozumieć kiedy) i otrzymuję następujący błąd:

[Tue Jul 10 17:13:58 2012] (42289) ERROR: Getting request failed: Client closed 

Czy ktoś może mi pokazać drogę, jak construt prawidłowy filtr HTTP :: Proxy dla Dumper całą komunikację między przeglądarką a serwerem regardles z keep_alive XHR?

+0

Wymyślasz koło. Wpisz ctrl + shift + i, aby uruchomić Firefox Firebug/Opera Dragonfly/Chromium Inspecter i sprawdź w panelu sieci, jak wyglądają pary żądań/odpowiedzi HTTP. Alternatywnie, użyj Wireshark, zakończ przechwytywanie, filtruj wyrażenie 'http' w polu kombi w górnej części, wybierz pakiet, który rozpoczyna żądanie, menu Analizuj → Obserwuj strumień TCP, aby zobaczyć tekstową reprezentację pary żądanie/odpowiedź HTTP . – daxim

+1

Przepraszam @daxim, ale to nie jest rozwiązanie.Ofc, mogę użyć firebuga lub dowolnego innego panelu sterowania przeglądarki (i użyć go do analizy). Mogę też używać tcpdump i/lub tcpflow. Chcę dokładnie uchwycić kanał (do późniejszej pracy) na serwerze bez nagłówków (bez X), bez przeglądarki. Dzięki za odpowiedź w każdym razie - ale jeśli chcę przechwytywanie zwykłych pakietów nie będzie prosić o rozwiązanie perla. – kobame

+0

@daxim, rozumiem twój punkt widzenia, ale pytanie jest uzasadnione i pokazuje prawdziwy problem. (i IMO, jest o wiele lepsze niż zwykłe pytania związane z SO-perlami, takie jak używanie tr /// :) Próbowałem skryptu, a ja sam też nie znam odpowiedzi - czy możesz pomóc? – jm666

Odpowiedz

5

Oto coś, co myślę, że robi to, co jesteś po:

#!/usr/bin/perl 

use 5.010; 
use strict; 
use warnings; 

use HTTP::Proxy; 
use HTTP::Proxy::BodyFilter::complete; 
use HTTP::Proxy::BodyFilter::simple; 
use JSON::XS  qw(decode_json); 
use Data::Dumper qw(Dumper); 

my $proxy = HTTP::Proxy->new(
    port      => 3128, 
    max_clients    => 100, 
    max_keep_alive_requests => 100, 
); 

my $filter = HTTP::Proxy::BodyFilter::simple->new(
    sub { 
     my ($self, $dataref, $message, $protocol, $buffer) = @_; 
     return unless $$dataref; 
     my $content_type = $message->headers->content_type or return; 
     say "\nContent-type: $content_type"; 
     my $data = decode_json($$dataref); 
     say Dumper($data); 
    } 
); 

$proxy->push_filter(
    method => 'GET', 
    mime  => 'application/json', 
    response => HTTP::Proxy::BodyFilter::complete->new, 
    response => $filter 
); 

$proxy->start; 

Nie sądzę, trzeba osobny filtr nagłówka, ponieważ można uzyskać dostępu do żadnych nagłówków chcesz przyjrzeć przy użyciu $message->headers w filtrze ciała.

Należy zauważyć, że wepchnąłem dwa filtry na rurociąg. Pierwszy z nich to typ HTTP::Proxy::BodyFilter::complete, a jego zadaniem jest zbieranie fragmentów odpowiedzi i upewnienie się, że prawdziwy filtr, który następuje, zawsze otrzymuje kompletny komunikat w postaci $dataref. Jednak porcja foreach, która jest odbierana i buforowana, następujący filtr zostanie wywołany i przekazany pusty $dataref. Mój filtr ignoruje je, powracając wcześniej.

ja również skonfigurować rurociągu filtra do ignorowania wszystko oprócz żądań GET, które doprowadziły w odpowiedzi JSON - ponieważ te wydają się być najbardziej interesujący.

Dzięki za tym pytaniem - to był ciekawy mały problem i wydawało się, że odbywa się większość ciężkiej pracy już.

+0

Tak! Rozwiązałeś oba problemy, a.) Dostając aplikację/json i b.) Także fragmentację. Dziękuje bardzo. :) – kobame

2

Ustaw mime parameter, domyślnie filtruje tylko typy tekstowe.

$proxy->push_filter(response => $hfilter, mime => 'application/json'); 
$proxy->push_filter(response => $bfilter, mime => 'application/json'); 
+0

Dziękuję, Daxim, jest to rozwiązanie dla większości problemów;) – kobame