Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Proxy, Man-In-The-Middle e testes

688 views

Published on

Using Man-In-The-Middle proxy to test webservice clients

Published in: Software
  • Be the first to comment

  • Be the first to like this

Proxy, Man-In-The-Middle e testes

  1. 1. Proxy, Man-In-The- Middle e testes Stanislaw Pusep YAPC::Br 2015
  2. 2. Contexto • Migração de LWP 5.x para LWP 6.x em todo o sistema • A partir do LWP 6, vários módulos não mais fazem parte da distribuição libwww-perl! • LWP::Protocol::https • LWP::Protocol::connect
  3. 3. Contexto • Firewall com whitelist • Conexões externas somente através do proxy Squid • SSL/TLS, pois os requests contém dados pessoais
  4. 4. Desafio • Message Service faz request HTTP • request handler acessa os dados • LWP cria request HTTP(S) para servidor externdo • Proxy Squid • API externa
  5. 5. Desafio • Código legado • Sem teste para a integração com o serviço externo • Importante demais para testar em produção • Sistema distribuído, mas impossível de fazer deploy gradual
  6. 6. Solução? • $ua->proxy('http', 'http://proxy:3128'); • GET http://api-remota.com/v1/… HTTP/1.1 • $ua->proxy('https', 'connect://proxy:3128'); • CONNECT api-remota.com:443 HTTP/1.1
  7. 7. Solução? • SOCKS? • SOCKS4/SOCKS4a/SOCKS5/SOCKS5h • LWP::Protocol::socks
  8. 8. Solução • Melhorar os testes de integração com o proxy! • Proxy = Servidor + Cliente • Instalar proxy customizado em DEV? (ngx_http_proxy_module) • HTTP::Daemon + HTTP::Proxy • Plack::Middleware::.*Connect.*
  9. 9. Solução!
  10. 10. Implementação • Primeiro, implementamos um servidor HTTP minimalista • AnyEvent::Socket::tcp_server() • Responde igualmente tanto “GET / HTTP/1.1” quanto “GET http://blabla.com/ HTTP/1.1” • Traduz CONNECT para GET
  11. 11. Implementação our %pool; my $srv = tcp_server( '127.0.0.1' => 0, sub { my ($fh, $host, $port) = @_; # código do servidor ...; } ); AE->cv->wait;
  12. 12. Implementação my $h = AnyEvent::Handle->new( fh => $fh, on_eof => &cleanup, on_error => &cleanup, timeout => 10, ); $pool{fileno($fh)} = $h;
  13. 13. Implementação $h->push_read(regex => qr{(015?012){2}}, sub { my ($h, $data) = @_; my ($req, $hdr) = split m{015?012}x, $data, 2; $req =~ s/s+$//sx; if ($hdr =~ m{bContent-length:s*(d+)b}is) { $h->push_read(chunk => int($1), sub { my ($h, $data) = @_; reply($h, $req, $hdr, $data); }); } else { reply($h, $req, $hdr); } });
  14. 14. Implementação sub cleanup { my ($h, $fatal, $msg) = @_; my $id = fileno($h->{fh}); delete $pool{$id} if defined $id; eval { no warnings; shutdown $h->{fh}, 2; }; $h->destroy; } sub reply { my ($h, $req, $hdr, $content) = @_; ...; $h->push_write(...); cleanup($h); }
  15. 15. Implementação sub reply { my ($h, $req, $hdr, $content) = @_; if ($req =~ m{^CONNECTs+([w.-]+):(d+)s+(HTTP/1.[01])$}ix) { $h->push_read(tls_autostart => ‘accept’); } ...; $h->push_write(...); cleanup($h); }
  16. 16. Implementação • Produto final: Test::HTTP::AnyEvent::Server • my $server = Test::HTTP::AnyEvent::Server->new; • Pré-configura @ENV{qw(no_proxy http_proxy https_proxy ftp_proxy all_proxy)} • GET /echo/head • GET /echo/body • GET /repeat/5/PADDING • GET /delay/5
  17. 17. Usando… my $server = Test::HTTP::AnyEvent::Server->new(     custom_handler => sub {         my ($response) = @_;         if ($response->request->uri eq '/hello') {             $response->content('world');             return 1;         }         return 0; # 404 Not Found     }, ); my $cv = AE::cv; $cv->begin; http_request     GET     => qq(http://ohhai/hello),     proxy   => [ $server->address => $server->port ], sub { like($_[0], qr{bHosts*:s*ohhaib}isx, q(fake host)); $cv->end; }; $cv->wait;
  18. 18. Obrigado! • stas@sysd.org • https://metacpan.org/pod/Test::HTTP::AnyEvent::Server • https://gist.github.com/creaktive/781246
  19. 19. We are hiring! workingatbooking.com

×