On the Wire: Network Capture Tools for API Developers

Lane LiaBraaten, equipe de APIs de dados do Google
junho de 2007

Introdução

O desenvolvimento de aplicativos que interagem com serviços da Web apresenta um conjunto exclusivo de problemas. Uma fonte comum de frustração é não saber exatamente qual mensagem foi enviada ao servidor ou qual resposta foi recebida. Alguns dos bugs mais difíceis de rastrear são causados por uma desconexão entre o que achamos que estamos enviando ao servidor e o que realmente está sendo transmitido.

Este artigo apresenta várias ferramentas que podem ajudar a tornar os dados na rede mais visíveis e úteis. Essas ferramentas, comumente chamadas de "farejadores de pacotes", capturam todos os pacotes de rede que se movem pela sua interface de rede. Examinar o conteúdo desses pacotes e a ordem em que foram enviados e recebidos pode ser uma técnica de depuração útil.

Exemplo: como recuperar um feed público

Estou montando uma equipe de ciclismo para um passeio beneficente e criei uma agenda para eventos como sessões de informações, arrecadações de fundos da equipe e treinos. Tornei essa agenda pública para que os membros da equipe e outros ciclistas possam acessar e participar dos eventos. Também quero enviar uma newsletter com os próximos eventos. Em vez de copiar as informações do site do Google Agenda, posso usar a API de dados do Google Agenda para consultar essa agenda e recuperar eventos.

A documentação da API Google Calendar tem informações sobre como usar a API Google Data RESTful para interagir com meu calendário de forma programática. Observação do editor:a partir da v3, a API Google Agenda não usa mais o formato de dados do Google. Primeiro, clique no botão na página de configurações da agenda para acessar o URL do feed de eventos dela:

http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic

Usando a documentação do Google Agenda como referência, posso recuperar e mostrar eventos da agenda assim, em que PUBLIC_FEED_URL contém o URL do feed de eventos.

CalendarService myService = new CalendarService("exampleCo-fiddlerExample-1");
final String PUBLIC_FEED_URL = "http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic";
URL feedUrl = new URL(PUBLIC_FEED_URL);
CalendarEventFeed resultFeed = myService.getFeed(feedUrl, CalendarEventFeed.class);

System.out.println("All events on your calendar:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEventEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

Isso gera uma lista básica dos eventos na minha agenda:

All events on your calendar:
    MS150 Training ride
    Meeting with Nicole
    MS150 Information session

O snippet de código acima mostra os títulos dos eventos da agenda, mas e o restante dos dados que recebemos do servidor? A biblioteca de cliente Java não facilita a saída de um feed ou entrada como XML, e mesmo que facilitasse, o XML não é tudo. E os cabeçalhos HTTP que acompanham a solicitação? A consulta foi encaminhada por proxy ou redirecionada? Com operações mais complexas, essas perguntas se tornam cada vez mais importantes, principalmente quando algo dá errado e recebemos erros. Um software de rastreamento de pacotes pode responder a essas perguntas revelando o tráfego de rede.

tcpdump

O tcpdump é uma ferramenta de linha de comando que funciona em plataformas semelhantes ao Unix, mas também há uma porta do Windows chamada WinDump. Como a maioria dos sniffers de pacotes, o tcpdump coloca sua placa de rede no modo promíscuo, que exige privilégios de superusuário. Para usar o tcpdump, basta especificar a interface de rede a ser monitorada, e o tráfego de rede será enviado para stdout:

sudo tcpdump -i eth0

Se você executar esse comando, vai receber todo tipo de tráfego de rede, alguns dos quais você nem vai reconhecer. Você pode encaminhar a saída para um arquivo e grep depois, mas isso pode gerar arquivos muito grandes. A maioria dos softwares de captura de pacotes tem alguns mecanismos de filtragem integrados para que você capture apenas o que precisa.

O tcpdump oferece suporte a filtragem com base em várias características do tráfego de rede. Por exemplo, é possível instruir o tcpdump a capturar apenas o tráfego de ou para o servidor na porta 80 (mensagens HTTP) inserindo o nome do host do servidor na seguinte expressão:

dst or src host <hostname> and port 80

Para cada pacote que corresponde à expressão de filtro, o tcpdump mostra um carimbo de data/hora, a origem e o destino do pacote e várias flags TCP. Essas informações podem ser valiosas porque mostram a ordem em que os pacotes foram enviados e recebidos.

Também costuma ser útil ver o conteúdo dos pacotes. A flag "-A" instrui o tcpdump a imprimir cada pacote em ASCII, expondo os cabeçalhos HTTP e o corpo da mensagem. A flag "-s" é usada para especificar quantos bytes serão exibidos. "-s 0" significa não truncar o corpo da mensagem.

Juntando tudo, temos o seguinte comando:

sudo tcpdump -A -s 0 -i eth0 dst or src host <hostname> and port 80

Se você executar esse comando e o exemplo curto de .Java acima, verá toda a comunicação de rede envolvida nessa operação. Entre o tráfego, você vai encontrar a solicitação HTTP GET:

22:22:30.870771 IP dellalicious.mshome.net.4520 > po-in-f99.google.com.80: P 1:360(359) ack 1 win 65535
E.....@....\...eH..c...P.=.....zP......GET /calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic HTTP/1.1
User-Agent: exampleCo-fiddlerExample-1 GCalendar-Java/1.0.6 GData-Java/1.0.10(gzip)
Accept-Encoding: gzip
Cache-Control: no-cache
Pragma: no-cache
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

Você também vai encontrar a mensagem de resposta 200 OK que contém o feed de dados do Google. O feed é dividido em quatro pacotes:

22:22:31.148789 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1:1431(1430) ack 360 win 6432
E...1 ..2.I.H..c...e.P.....z.=.:P..M...HTTP/1.1 200 OK
Content-Type: application/atom+xml; charset=UTF-8
Cache-Control: max-age=0, must-revalidate, private
Last-Modified: Mon, 11 Jun 2007 15:11:40 GMT
Transfer-Encoding: chunked
Date: Sun, 24 Jun 2007 02:22:10 GMT
Server: GFE/1.3

13da
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:gCal='http://sc
hemas.google.com/gCal/2005' xmlns:gd='http://schemas.google.com/g/2005'><id>http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic</id><updated>2007-06-11T15:11:40.000Z</updated><category sc
heme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/g/2
005#event'></category><title type='text'>MS150 Training Schedule</title><subtitl
e type='text'>This calendar is public</subtitle><link rel='http://schemas.google
.com/g/2005#feed' type='application/atom+xml' href='http://www.google.com/calend
ar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic'></
link><link rel='self' type='application/atom+xml' href='http://www.google.com/ca
lendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic
?max-results=25'></link><author><name>Lane LiaBraaten</name><email>api.lliabraa@
gmail.com</email></author><generator version='1.0' uri='http://www.google.com/ca
lendar'>Google Calendar</generator><openSearch:totalRe


22:22:31.151501 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 1431:2861(1430) ack 360 win 6432
E...1!..2.I.H..c...e.P.......=.:P.. 2...sults>3</openSearch:totalResults><openSe
arch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch
:itemsPerPage><gd:where valueString=''></gd:where><gCal:timezone value='America/
Los_Angeles'></gCal:timezone><entry><id>http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744</id><published>2007-06-11T15:11:05.000Z</published><updated>2007-06-
11T15:11:05.000Z</updated><category scheme='http://schemas.google.com/g/2005#kin
d' term='http://schemas.google.com/g/2005#event'></category><title type='text'>M
S150 Training ride</title><summary type='html'>When: Sat Jun 9, 2007 7am to 10am

&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed</summary><conte
nt type='text'>When: Sat Jun 9, 2007 7am to 10am&amp;nbsp; PDT&lt;br&gt;   &lt;b
r&gt;Event Status:     confirmed</content><link rel='alternate' type='text/html'
 href='http://www.google.com/calendar/event?eid=ZGd0NDAwMjJjdWkyazNqNzQwaG5qNDY3
NDQgMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw' title='alternate'></link><link rel='
self' type='application/atom+xml' href='http://www.google.com/calendar/feeds/24v
j3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/dgt40022cui2k3j
740hnj46744'></link><author><name>MS150 Training Schedule</name></author><gCal:s
endEventNotifications value='false'></gCal:sendEventNotifications></entry><entry

><id>http://www.google.com/cal

22:22:31.153097 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: . 2861:4291(1430) ack 360 win 6432
E...1#..2.I.H..c...e.P.......=.:P.. ....endar/feeds/24vj3m5pl125bh2ijbbneh953s%4
0group.calendar.google.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8</id><publishe
d>2007-06-11T15:08:23.000Z</published><updated>2007-06-11T15:10:39.000Z</updated
><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.g
oogle.com/g/2005#event'></category><title type='text'>Meeting with Nicole</title

><summary type='html'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&gt;
  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed</summ
ary><content type='text'>When: Mon Jun 4, 2007 10am to 11am&amp;nbsp; PDT&lt;br&
gt;  &lt;br&gt;Where: Conference Room B &lt;br&gt;Event Status:     confirmed

&lt;br&gt;Event Description: Discuss building cycling team for MS150</content><l
ink rel='alternate' type='text/html' href='http://www.google.com/calendar/event?
eid=NTFkOGtoNHMzYnBscW5iZjFscDZwMGtqcDggMjR2ajNtNXBsMTI1YmgyaWpiYm5laDk1M3NAZw'
title='alternate'></link><link rel='self' type='application/atom+xml' href='http
://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.calendar.goo
gle.com/public/basic/51d8kh4s3bplqnbf1lp6p0kjp8'></link><author><name>MS150 Trai
ning Schedule</name></author><gCal:sendEventNotifications value='false'></gCal:s
endEventNotifications></entry><entry><id>http://www.google.com/calendar/feeds/24
vj3m5pl125bh2ijbbneh953s%40group.calendar.google.com/public/basic/va41amq3r08dhh
kpm3lc1abs2o</id><published>20


22:22:31.190244 IP po-in-f99.google.com.80 > dellalicious.mshome.net.4520: P 4291:5346(1055) ack 360 win 6432
E..G1$..2.K.H..c...e.P.....<.=.:P.. ....07-06-11T15:10:08.000Z</published><updat
ed>2007-06-11T15:10:08.000Z</updated><category scheme='http://schemas.google.com
/g/2005#kind' term='http://schemas.google.com/g/2005#event'></category><title ty
pe='text'>MS150 Information session</title><summary type='html'>When: Wed Jun 6,
 2007 4pm to Wed Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Statu
s:     confirmed</summary><content type='text'>When: Wed Jun 6, 2007 4pm to Wed
Jun 6, 2007 5pm&amp;nbsp; PDT&lt;br&gt;   &lt;br&gt;Event Status:     confirmed<

/content><link rel='alternate' type='text/html' href='http://www.google.com/cale
ndar/event?eid=dmE0MWFtcTNyMDhkaGhrcG0zbGMxYWJzMm8gMjR2ajNtNXBsMTI1YmgyaWpiYm5la
Dk1M3NAZw' title='alternate'></link><link rel='self' type='application/atom+xml'
 href='http://www.google.com/calendar/feeds/24vj3m5pl125bh2ijbbneh953s%40group.c
alendar.google.com/public/basic/va41amq3r08dhhkpm3lc1abs2o'></link><author><name
>MS150 Training Schedule</name></author><gCal:sendEventNotifications value='fals
e'></gCal:sendEventNotifications></entry></feed>

Essa saída inclui todos os cabeçalhos e o conteúdo HTTP, além de várias flags TCP criptografadas. Todos os dados estão aqui, mas é difícil ler e entender. Há várias ferramentas gráficas que facilitam a visualização desses dados.

WireShark (antigo Ethereal)

Captura de tela do Wireshark
O WireShark mostra o tráfego de rede de várias maneiras.

O WireShark é uma ferramenta gráfica criada com o libpcap, a mesma biblioteca em que o tcpdump é criado, e está disponível para Linux, Mac OS X e Windows. A GUI do WireShark permite várias novas maneiras de interpretar e interagir com dados de captura de pacotes. Por exemplo, à medida que os pacotes são capturados da sua interface de rede, eles são mostrados em cores diferentes com base no protocolo que estão usando. Também é possível classificar o tráfego por carimbo de data/hora, origem, destino e protocolo.

Se você selecionar uma linha na lista de pacotes, o Wireshark vai mostrar informações específicas de IP, TCP e outros protocolos nos cabeçalhos de pacote em uma árvore legível para humanos. Os dados também são mostrados em HEX e ASCII na parte de baixo da tela.

Embora a natureza visual do WireShark facilite a compreensão do tráfego de rede, ainda é recomendável filtrar o tráfego de rede na maioria dos casos. O WireShark tem recursos de filtragem robustos, incluindo suporte para centenas de protocolos.

DICA:para ver os protocolos disponíveis e criar filtros complexos, clique no botão na parte de cima da janela do WireShark.

Para recriar o filtro usado no exemplo de tcpdump acima, insira a seguinte expressão na caixa de filtro do WireShark:

ip.addr==<your IP address> && tcp.port==80

Ou aproveite o conhecimento do WireShark sobre HTTP:

ip.addr==<your IP address> && http

Isso vai filtrar os resultados da captura para apenas os pacotes envolvidos nessa interação com o servidor do Google Agenda. Clique em cada pacote para ver o conteúdo e montar a transação.

DICA:clique com o botão direito do mouse em um dos pacotes e escolha "Seguir fluxo TCP" para mostrar as solicitações e respostas sequencialmente em uma única janela.

O WireShark oferece várias maneiras de salvar as informações de captura. Você pode salvar um, alguns ou todos os pacotes. Se você estiver visualizando um fluxo TCP, basta clicar no botão "Salvar como" para salvar apenas os pacotes relevantes. Você também pode importar a saída de uma captura de tcpdump e visualizá-la no WireShark.

Um problema: SSL e criptografia

Uma deficiência comum das ferramentas de captura de pacotes é a incapacidade de visualizar dados criptografados em uma conexão SSL. O exemplo acima acessa um feed público, então o SSL não é necessário. No entanto, se o exemplo acessasse um feed particular, o cliente precisaria se autenticar com o serviço de autenticação do Google, que exige uma conexão SSL.

O snippet a seguir é semelhante ao exemplo anterior, mas aqui o CalendarService solicita o metafeed de calendário do usuário, que é um feed particular que exige autenticação. Para autenticar, basta chamar o método setUserCredentials. Esse método aciona uma solicitação HTTPS para o serviço ClientLogin e extrai o token de autenticação da resposta. O objeto CalendarService vai incluir o token de autenticação em todas as solicitações subsequentes.

CalendarService myService = new CalendarService("exampleCo-fiddlerSslExample-1");
myService.setUserCredentials(username, userPassword);
final String METAFEED_URL = "http://www.google.com/calendar/feeds/default";
URL feedUrl = new URL(METAFEED_URL);
CalendarFeed resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);

System.out.println("Your calendars:");
for (int i = 0; i < resultFeed.getEntries().size(); i++) {
  CalendarEntry entry = resultFeed.getEntries().get(i);
  System.out.println("\t" + entry.getTitle().getPlainText());
}
System.out.println();

Considere o tráfego de rede necessário para autenticar e acessar um feed particular da API Google Data:

  1. Enviar credenciais de usuário ao serviço ClientLogin
    • Envie um HTTP POST para https://www.google.com/accounts/ClientLogin com os seguintes parâmetros no corpo da mensagem:
      • E-mail: o endereço de e-mail do usuário.
      • Passwd: a senha do usuário.
      • source: identifica seu aplicativo cliente. Deve ter o formato companyName-applicationName-versionID. Os exemplos usam o nome ExampleCo-FiddlerSSLExample-1.
      • service: o nome do serviço do Google Agenda é "cl".
  2. Receber o token de autorização
    • Se a solicitação de autenticação falhar, você vai receber um código de status HTTP 403 Forbidden.
    • Se a solicitação for bem-sucedida, a resposta do serviço será um código de status HTTP 200 OK, além de três códigos alfanuméricos longos no corpo da resposta: SID, LSID e Auth. O valor Auth é o token de autorização.
  3. Solicitar um metafeed de agenda particular
    • Envie um HTTP GET para http://www.google.com/calendar/feeds/default com o seguinte cabeçalho:
    • Authorization: GoogleLogin auth=<yourAuthToken>
      

Tente executar este snippet e ver o tráfego de rede no WireShark (usando "http || ssl" como filtro). Você vai ver os pacotes SSL e TLS envolvidos na transação, mas os pacotes de solicitação e resposta do ClientLogin são criptografados nos pacotes de "Dados do aplicativo". Não se preocupe, em seguida vamos analisar uma ferramenta que pode revelar essas informações criptografadas.

Fiddler

O Fiddler é outra ferramenta gráfica de rastreamento de pacotes, mas se comporta de maneira bem diferente das ferramentas apresentadas até agora. O Fiddler atua como um proxy entre seu aplicativo e os serviços remotos com que você está interagindo, tornando-se efetivamente um man-in-the-middle. O Fiddler estabelece uma conexão SSL com seu aplicativo e com o serviço da Web remoto, descriptografando o tráfego de um endpoint, capturando o texto simples e criptografando novamente o tráfego antes de enviá-lo. Infelizmente, o Fiddler está disponível apenas para Windows. Pedimos desculpas aos usuários de Mac e Linux.

Observação:o suporte a SSL exige o Fiddler versão 2 e o .NET Framework versão 2.0.

A visualização do tráfego de rede no Fiddler é feita principalmente na guia "Session Inspector". As subguias mais úteis para depurar problemas com as APIs Google Data são:

  • Cabeçalhos: mostra os cabeçalhos HTTP em um formato de árvore recolhível.
  • Auth: mostra os cabeçalhos de autenticação.
  • Bruto: mostra o conteúdo dos pacotes de rede em texto ASCII.

DICA:clique no ícone no canto inferior esquerdo da janela do Fiddler para ativar e desativar a captura.

O Fiddler usa o .NET Framework para configurar conexões de rede e usar o Fiddler como um proxy. Isso significa que todas as conexões feitas com o Internet Explorer ou com o código .NET vão aparecer no Fiddler por padrão. No entanto, o tráfego do exemplo em Java acima não vai aparecer porque o Java tem uma maneira diferente de configurar proxies HTTP.

Em Java, é possível definir o proxy HTTP usando propriedades do sistema. O Fiddler é executado na porta 8888. Portanto, para uma instalação local, é possível fazer com que o código Java use o Fiddler como um proxy para HTTP e HTTPS adicionando estas linhas:

System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8888");
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8888");

Se você executar a amostra com essas linhas, vai receber um rastreamento de pilha desagradável do pacote de segurança Java:

[java] Caused by:
  sun.security.validator.ValidatorException: PKIX path building failed:
  sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Captura de tela do Fiddler
O Fiddler pode descriptografar e mostrar o tráfego SSL.

Esse erro ocorre quando não é possível verificar o certificado retornado do servidor em uma conexão SSL. Nesse caso, o certificado inválido vem do Fiddler, que atua como um interceptador. O Fiddler gera certificados dinamicamente, e como ele não é um emissor confiável, esses certificados fazem com que o Java falhe ao configurar a conexão SSL.

Observação:quando o Fiddler está em execução, qualquer conexão SSL feita no Internet Explorer aciona um "Alerta de segurança" perguntando se você quer continuar apesar do certificado suspeito. Clique em "Ver certificado" para conferir o certificado gerado pelo Fiddler.

Então, como contornar essa exceção de segurança? Basicamente, você precisa reconfigurar a estrutura de segurança do Java para confiar em todos os certificados. Felizmente, não é preciso reinventar a roda aqui. Confira a solução de Francis Labrie e adicione o método SSLUtilities.trustAllHttpsCertificates() ao exemplo acima.

Depois de configurar o Java para usar o Fiddler como um proxy e desativar a verificação de certificado padrão, você pode executar o exemplo e ver todo o tráfego enviado pela rede em texto simples. Não roube minha senha!

Lembre-se de que essa transação de autenticação é apenas um pequeno exemplo de tráfego SSL. Alguns aplicativos da Web usam conexões SSL exclusivamente. Portanto, a depuração do tráfego HTTP não é possível sem uma maneira de descriptografar os dados.

Conclusão

O tcpdump está disponível para Linux, Mac OS X e Windows e é uma ótima ferramenta quando você sabe o que está procurando e só precisa de uma captura rápida. No entanto, há algumas ferramentas gráficas que apresentam o tráfego de rede em formatos mais fáceis de entender. O tcpdump tem muito mais opções e recursos de filtragem do que os abordados aqui. Para uma descrição completa da funcionalidade do tcpdump, digite "man tcpdump" ou acesse a página do manual do tcpdump on-line.

O WireShark também está disponível para Linux, Mac OS X e Windows. O suporte integrado para centenas de protocolos torna o WireShark uma ferramenta útil para muitos aplicativos, não apenas para depuração HTTP. Esta introdução mal arranha a superfície dos muitos recursos do Wireshark. Para mais informações, digite "man wireshark" ou acesse o site do WireShark (em inglês).

O Fiddler também tem muitos recursos excelentes, mas o que o diferencia é a capacidade de descriptografar o tráfego SSL. Para mais informações, acesse o site do Fiddler2.

Esses aplicativos de rastreamento de pacotes são ótimas ferramentas para ter no seu arsenal, e os leitores atentos perceberam que todos eles são sem custo financeiro. Na próxima vez que você estiver trabalhando com as APIs do Google e notar algo suspeito, use um desses analisadores de rede e examine mais de perto o que está acontecendo. Se não encontrar o problema, poste uma pergunta no nosso grupo de discussão. Incluir as mensagens de rede relevantes vai ajudar outras pessoas a entender e diagnosticar seu problema específico.

Boa sorte e boa farejada!

Recursos