HTTP-verkeer debuggen met Fiddler

Door CodeCaster op vrijdag 23 maart 2012 12:30 - Reacties (9)
Categorie: Tech, Views: 6.872

Tijdens het ontwikkelen van software kom je op een zeker moment ongetwijfeld in aanraking met het HTTP-protocol. Het is voornamelijk bekend als drijvende kracht achter het www, maar ook webservices maken gebruik van dit protocol om data uit te wisselen.

Introductie HTTP

HTTP werkt volgens het request-responsemodel: de client vuurt een aanvraag af op een bepaalde resource op een server, waarna deze server het verzoek verwerkt en vervolgens een antwoord terugstuurt.

Althans, als alles goed gaat. Om goed uit te kunnen leggen wat er allemaal mis kan gaan bij een HTTP-verzoek, zodat je een idee hebt waar te kijken als het mis gaat, zal ik eerst de basisbegrippen pogen te verduidelijken.
URI's
Alle acties die middels het HTTP-protocol kunnen worden uitgevoerd, worden dat op een resource. Een resource wijs je aan middels een, de naam zegt het al, Uniform Resource Identifier (URI).
Verbs
De initile specificatie van HTTP beschrijft een aantal methodes die kunnen worden uitgevoerd door een client, zoals GET, HEAD, POST, PUT en DELETE. Deze methodes, ook wel verbs (werkwoorden) genoemd, bepalen wat de server met de opgegeven resource moet doen. Versie 1.1 voegt een aantal verbs toe aan deze lijst, waaronder OPTIONS. Verder is het toegestaan dat uitbreidingen op het HTTP-protocol hun eigen verbs introduceren. Kijk dus niet vreemd op als je ineens een PROPFIND-request voorbij ziet komen als je een kalenderclient hebt draaien.
Host
Als de user agent (dat is de client in HTTP-jargon, bijvoorbeeld een webbrowser) een verzoek naar een website gaat doen, wordt eerst het IP-adres van de webserver opgevraagd middels DNS. Zo kun je bijvoorbeeld de host tweakers.net 'resolven' naar het IP-adres 213.239.154.35.

Vervolgens bouwt de client een TCP-verbinding op richting de server, en op dat moment is (voor wat die verbinding betreft) alle domeininformatie verloren. Doordat DNS namelijk een aantal lagen hoger ligt dan TCP, weet de server op dat moment niet welke website je wil bezoeken. Dit was in eerste instantie geen probleem ten tijde van de ontwikkeling van HTTP 1.0, maar aangezien er anno nu soms wel honderden sites op n server (en dus meestal n IP-adres) worden gehost, moet de client aan de server vertellen welke website 'ie zoekt. Dat gebeurt dus door middel van de Host-header.
Overige headers
Behalve de host-header zijn er nog legio headers die een HTTP-client en -server kunnen uitwisselen. Veel hiervan hebben betrekking op de te verzenden inhoud, bijvoorbeeld het mime-type, de encoding en eventuele compressie.
Request
Als je bovenstaande zaken combineert, en nog even zo netjes bent te vermelden welke HTTP-versie je client ondersteunt, kun je een verzoek gaan opbouwen. Als je een lokale webserver draait, en met je browser de index-pagina daarop opvraagt, zou het verzoek er als volgt uit kunnen zien:
code:
1
2
GET /index.html HTTP/1.1
Host: localhost

Response
Na het verzenden van een verzoek blijft de client wachten op een antwoord van de server. Dit antwoord kan er in bovenstaand geval zo uit kunnen zien:
code:
1
2
3
4
HTTP/1.1 200 OK
Content-length: 5

Hello



Dat ziet er goed uit: de statuscode is er een uit de 200-serie, wat inhoudt dat het verzoek succesvol is verwerkt door de server. Vervolgens zie je een Content-length-header, die aangeeft hoeveel data de user agent in het antwoord kan verwachten, twee CRLF's (de scheiding tussen headers en payload) en uiteindelijk de payload: "Hello".
Minder goed nieuws
Het is minder fijn wanneer de server gn statuscode in de 200-reeks terugstuurt. De 100's en 300's zijn niet zo erg, dit is meestal een tussenstap richting een 200 (bijvoorbeeld 100 Continue of 301 Moved Permanently), maar 400 en 500 worden spannender.

De fouten uit de 400-reeks houden in dat het verzoek dat door de client is gestuurd, niet door de server verwerkt kan worden. Dit kan aan het verzoek zelf liggen (412 Precondition Failed), maar ook aan de opgevraagde resource (404 Not Found).

Daar tegenover staan verzoeken die de server om zeep helpen, wat wordt afgedekt door de 500-serie. Meestal krijg je letterlijk een 500 om je oren, "Internal Server Error", en in sommige gevallen een 501 Not Implemented, bijvoorbeeld bij het opvragen van een niet-ondersteunde verb.

Debuggen

Maar wanneer en hoe wil je dit nu kunnen debuggen? Een voordeel van HTTP is dat het behoorlijk human-readable is, maar daardoor direct ook ietwat verbose (al wordt daar nu aan gewerkt). Door het verkeer tussen client en server af te luisteren, kun je een hoop te weten komen over de opgevraagde data, de gebruikte server en client en de eventuele foutmeldingen.

Een, nee, d tool om dit verkeer af te vangen en uit te lezen is het gratis programma Fiddler (download). Fiddler installeert zichzelf na het starten als proxy, waarna alle uitgaande (!) HTTP-verzoeken en de antwoorden hierop geanalyseerd kunnen worden. Het maakt niet uit of je zelf al een proxyserver hebt ingesteld; Fiddler doet aan zogeheten chaining, waardoor ieder verzoek dat bij Fiddler binnenkomt weer wordt doorgestuurd naar de oorspronkelijke proxy.

Screenshot van Fiddler
Webdevelopment
Maar wat heb je hier nu aan tijdens het ontwikkelen? Je kunt bijvoorbeeld websites debuggen: kijken hoeveel requests worden afgevuurd, hoe lang deze duren, of ze lukken, hoe groot de uitgewisselde resources zijn en welke headers welke effecten sorteren.

De noodzaak van tools als Fiddler voor dit doeleinde vervalt enigszins, aangezien de meeste gangbare browsers vergelijkbare hulpmiddelen reeds aan boord hebben. Druk maar eens op F12 in Chrome, Firefox of IE.
Reverse Engineering
Ook bestaande applicaties, die HTTP-verkeer naar een (jou) onbekende server sturen, kunnen middels Fiddler worden bekeken, zolang ze de op het systeem ingestelde proxy maar respecteren zodat hun verkeer ook daadwerkelijk via Fiddler loopt. Degelijke applicaties doen dit.

Wanneer je je bezighoudt met het testen of analyseren van applicaties die het HTTP-protocol (of een afgeleide daarvan) implementeren, kun je Fiddler gebruiken om de door hen verzonden en ontvangen data in te zien en eventuele foutmeldingen op te sporen.
Services en sites debuggen
Services en sites die in IIS onder een bepaalde Application Pool draaien, draaien hoogstwaarschijnlijk onder een ander account dat het account dat Fiddler heeft opgestart. Hierdoor is het noodzakelijk om de proxy voor de betreffende site of service handmatig in te stellen. Dit kan middels het <defaultProxy>-element in de configuratie:

code:
1
2
3
4
5
6
7
8
9
10
11
<configuration>
  <system.net>
    <defaultProxy>
      <proxy
        usesystemdefault="false"
        proxyaddress="http://127.0.0.1:8888"
        bypassonlocal="false"
      />
    </defaultProxy>
  </system.net>
</configuration>


Zodoende zal een service of site die een HTTP-verzoek wil gaan doen, dit via Fiddler doen. Zo kun je bijvoorbeeld authenticatieproblemen achterhalen.

Dergelijke fouten kunnen ontstaan doordat een service, die bijvoorbeeld onder het account NetworkService draait, een andere service via het internet wil aanroepen. In bepaalde configuraties zal een bedrijfsproxy dit niet toestaan, omdat het account waarmee de NetworkService naar buiten gaat (domein\computernaam$) in de proxyserver niet bekend is.

Hierdoor zul je, zodra de service of site dit verzoek afvuurt, in Fiddler een 401 Unauthorized zien opduiken, al dan niet voorafgegaan door een 407 Proxy Authentication Required. Je weet dan dat je aan de proxybeheerder kunt vragen om de gevraagde URI te whitelisten, of dat je de gebruiker van de Application Pool moet aanpassen naar een die wel wordt herkend door de proxy. Als alternatief kun je zelf een klasse schrijven die als WebProxy dienst doet, zodat je service eerst aan jouw DLL vraagt om verbinding met de proxy te maken.
Inkomende verbindingen
Standaard werkt Fiddler alleen als proxy voor uitgaand verkeer, maar het is mogelijk om ook inkomend verkeer te onderscheppen. Om dit te doen moet je op het Connections-tabblad in Fiddler het item "Allow remote computers to connect" aanvinken, en moet je aan de verzendende kant het adres waarop Fiddler luistert instellen als proxy-adres.
HTTPS
Last but not least kun je met Fiddler ook HTTPS-verkeer bekijken. Ook dit is handig om bijvoorbeeld services van derde partijen te debuggen. Als het .NET-framework of een daarop gebouwde applicatie immers de HTTP-foutmelding (of bijvoorbeeld een serializatiefout) opeet, en de originele data niet inzichtelijk kan worden gemaakt, kun je zelf naar de headers en payload kijken. Om de connectie tussen deze gegevens en de uiteindelijke foutmelding te kunnen leggen, zul je behalve kennis van het gebruikte framework ook het een en ander van het HTTP-protocol moeten kennen, waarvoor ik hierboven heb gepoogd een aantal handvatten aan te reiken.

Toepassing

Stel, je hebt een webapplicatie die bij het opstarten even 'naar huis belt', of wil controleren of er een update is, maar na het neerzetten en uitvoeren van de applicatie krijg je enkel "Fout bij verbinden naar updateserver".

Dit kan aan bijzonder veel zaken liggen. Wellicht is de service down? Dit kun je uitsluiten door de endpoint-URL die in de web.config van de client staat in de browser te bezoeken. Ook configuratiefouten aan de servicekant kun je op die manier opsporen, doordat je een YSOD voorgeschoteld kunt krijgen waaruit je de bron van de fout kunt halen. Dat laatste geldt uiteraard alleen wanneer dit ook daadwerkelijk is ingeschakeld, een instelling die sterk wordt afgeraden voor productieomgevingen.

Mocht dit allemaal geen soelaas bieden, dan kun je met Fiddler aan de slag! Het probleem ligt dan namelijk hoogstwaarschijnlijk aan de clientkant. In de service uit dit voorbeeld heb ik Basic Authentication toegepast: dit is een onveilige manier van inloggen, doordat de credentials in plain text over de lijn worden gestuurd.

In Fiddler kun je dit vervolgens ook zien. Het eerste verzoek toont het opvragen van de webapplicatie zelf. Vervolgens poogt deze applicatie de service te bereiken zonder inloginformatie, waarna een '401 Unauthorized' wordt geretourneerd. Vervolgens wordt het verzoek herhaald, nu met een Authorization-header, waarin het gebruikersnaam:wachtwoord-paar in Base64 is gecodeerd. Hierop stuurt de server vervolgens nogmaals een 401 terug:
Fiddler 401

Wat blijkt hieruit: de client had de verkeerde credentials in de configuratie staan, waardoor de toegang tot de service werd geweigerd.

Conclusie

Fiddler kan vooral handig blijken als applicaties foutmeldingen die in de applicatielaag optreden simpelweg opeten en slechts melden dt er een fout is opgetreden, en niet (of niet inhoudelijk genoeg) melden welke fout dit was. Ik hoop dat deze blog iemand een aantal uurtjes debugwerk kan besparen.
Tips & Tricks
  • Door de werking van Windows (of specifieker: WinINet), worden verzoeken naar localhost, loopback, 127.0.0.1 en [::1] nooit via een proxyserver verstuurd. Hierdoor kun je met Fiddler (of Wireshark, of om het even welke sniffer) in de meeste gevallen geen verkeer afluisteren dat naar deze hosts wordt gestuurd. Om dit te omzeilen, gebruik je in plaats daarvan het IP-adres van een van de NIC's van de huidige computer, of diens machinenaam.
  • Doordat het rootcertificaat dat Fiddler gebruikt, DO_NOT_TRUST_FiddlerRoot, niet van een vertrouwde instantie afkomstig is, kan dit zorgen voor meldingen van de browser of voor services die weigeren te communiceren. Je kunt het certificaat laten importeren om dit alsnog werkend te krijgen. Hierdoor sta je alle certificaten die daaruit worden gegenereerd toe.
  • Het achterhalen van een IPv4-adres van een machine kan het gemakkelijkst door deze te pingen, met de optie -4 achter het commando: ping <machinenaam> -4.



http://codecaster.nl/got/rmb/star1.pnghttp://codecaster.nl/got/rmb/star2.pnghttp://codecaster.nl/got/rmb/star3.pnghttp://codecaster.nl/got/rmb/star4.pnghttp://codecaster.nl/got/rmb/star5.pnghttp://codecaster.nl/got/rmb/stats.gif

Volgende: Exit De Pers 03-'12 Exit De Pers
Volgende: Halbe Zijlstra en het onderwijs, deel twee 03-'12 Halbe Zijlstra en het onderwijs, deel twee

Reacties


Door Tweakers user naam, vrijdag 23 maart 2012 14:49

Interessant stukje om te lezen :) Misschien nog een linkje naar de download van Fiddler erbij zetten? http://www.fiddler2.com/fiddler2/version.asp

Door Tweakers user CodeCaster, vrijdag 23 maart 2012 14:50

Dank! :)

De link stond inderdaad niet zo duidelijk, heb de tekst wat aangepast.

[Reactie gewijzigd op vrijdag 23 maart 2012 14:53]


Door Tweakers user naam, vrijdag 23 maart 2012 14:51

Ah, ik zie het inderdaad.. Gemist, mijn fout :+

Door Tweakers user Don Kedero, vrijdag 23 maart 2012 15:33

Mooie & duidelijke tutorial! Fiddler is echt een zalige tool!

Door Tweakers user Mediarange, zaterdag 24 maart 2012 13:16

Kan je hiermee ook hacken?

Door Tweakers user CodeCaster, zaterdag 24 maart 2012 14:34

Je kunt verkeer dat een applicatie verstuurt en ontvangt analyseren, naspelen en bewerken, dus eventueel zou je op dat gebied kunnen hacken ja.

[Reactie gewijzigd op zaterdag 24 maart 2012 14:34]


Door Tweakers user Mediarange, zaterdag 24 maart 2012 15:03

Vet, dat ga ik doen!

Door Tweakers user [ti], zaterdag 24 maart 2012 16:40

Door de werking van Windows (of specifieker: WinINet), worden verzoeken naar localhost, loopback, 127.0.0.1 en [::1] nooit via een proxyserver verstuurd. Hierdoor kun je met Fiddler (of Wireshark, of om het even welke sniffer) in de meeste gevallen geen verkeer afluisteren dat naar deze hosts wordt gestuurd. Om dit te omzeilen, gebruik je in plaats daarvan het IP-adres van een van de NIC's van de huidige computer, of diens machinenaam.
Helaas werkt dit niet altijd, omdat sommige apps alleen aan 127.0.0.1 binden (bijvoorbeeld de debug webserver van visual studio), in dat geval kun je 127.0.0.1. (dus met extra punt erachter) gebruiken om het verkeer alsnog via de proxy te laten verlopen.

Door Tweakers user Korben, donderdag 29 maart 2012 16:08

[ti] schreef op zaterdag 24 maart 2012 @ 16:40:
[...]
Helaas werkt dit niet altijd, omdat sommige apps alleen aan 127.0.0.1 binden (bijvoorbeeld de debug webserver van visual studio), in dat geval kun je 127.0.0.1. (dus met extra punt erachter) gebruiken om het verkeer alsnog via de proxy te laten verlopen.
Of je kunt de hostname 'ipv4.fiddler' of 'ipv6.fiddler' gebruiken. Dan werkt het prima met applicaties die binden aan 127.0.0.1, maar loop je tegen problemen aan als je (bijvoorbeeld) webservers hebt die ook kijken naar de hostname (zoals IIS Express).

Reageren is niet meer mogelijk