Saturday, May 21, 2011

SPDY Requests in Detail

‹prev | My Chain | next›

Today, I am going to examine a SPDY session in excruciating detail. Specifically, I am going to go through the request packets for the following page (from the node-spdy example server):



The entire conversation from Wireshark looks like:
request »»»
55 6.993317 127.0.0.1 127.0.0.1 TLSv1 Client Hello

««« response
57 6.993692 127.0.0.1 127.0.0.1 TLSv1 Server Hello, Certificate, Server Hello Done

request »»»
59 6.995636 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
60 7.000103 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
62 7.038667 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP trafficContinuation or non-HTTP traffic

request »»»
64 7.074843 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
65 7.078185 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
67 7.108609 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic

request »»»
69 7.120765 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

request »»»
70 7.122965 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
72 7.123613 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

request »»»
73 7.131861 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
74 7.131888 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic

««« response
75 7.139855 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic

««« response
77 7.142581 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
78 7.142701 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
79 7.147850 127.0.0.1 127.0.0.1 TLSv1 Application Data

««« response
81 7.150942 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic

««« response
83 7.154903 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
85 7.188625 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

request »»»
87 7.293050 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
88 7.295411 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
90 7.296229 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic

««« response
92 7.296729 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
There are seven requests in all. The first is:
request »»»
55 6.993317 127.0.0.1 127.0.0.1 TLSv1 Client Hello
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E.
0010 00 e9 f3 35 40 00 40 06 48 d7 7f 00 00 01 7f 00 ...5@.@.H.......
0020 00 01 b1 a2 1f 91 72 7d 25 0e 72 b9 33 3f 80 18 ......r}%.r.3?..
0030 01 01 fe dd 00 00 01 01 08 0a 01 52 d6 3e 01 52 ...........R.>.R
0040 d6 3e 16 03 01 00 b0 01 00 00 ac 03 01 4d d7 2c .>...........M.,
0050 98 2f 60 55 4a 0c 0e ef c4 ad 10 b6 42 82 d9 53 ./`UJ.......B..S
0060 84 34 e2 2f 4a 79 11 4e 27 a7 2e eb 71 00 00 48 .4./Jy.N'...q..H
0070 c0 0a c0 14 00 88 00 87 00 39 00 38 c0 0f c0 05 .........9.8....
0080 00 84 00 35 c0 07 c0 09 c0 11 c0 13 00 45 00 44 ...5.........E.D
0090 00 66 00 33 00 32 c0 0c c0 0e c0 02 c0 04 00 96 .f.3.2..........
00a0 00 41 00 04 00 05 00 2f c0 08 c0 12 00 16 00 13 .A...../........
00b0 c0 0d c0 03 fe ff 00 0a 02 01 00 00 3a 00 00 00 ............:...
00c0 0e 00 0c 00 00 09 6c 6f 63 61 6c 68 6f 73 74 ff ......localhost.
00d0 01 00 01 00 00 0a 00 08 00 06 00 17 00 18 00 19 ................
00e0 00 0b 00 02 01 00 00 23 00 00 33 74 00 00 00 05 .......#..3t....
00f0 00 05 01 00 00 00 00 .......
That is just a normal SSL request. Nothing SPDY-like in there. The second request:
request »»»
59 6.995636 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 43 00 00 20 06 73 70 64 79 2f 32 18 00 00 00 00 C.. .spd y/2.....
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 14 00 00 0c 50 e0 b6 d9 32 f5 aa eb ........ P...2...
0030 2d 4d 31 68 -M1h
==
0000 80 02 00 01 01 00 01 41 00 00 00 01 00 00 00 00 .......A ........
0010 00 00 38 ea df a2 51 b2 62 e0 65 60 83 a4 17 06 ..8...Q. b.e`....
0020 7b b8 0b 75 30 2c d6 ae 40 17 cd cd b1 2e b4 35 {..u0,.. @......5
0030 d0 b3 d4 d1 d2 d7 02 b3 2c 18 f8 50 73 2c 83 9c ........ ,..Ps,..
0040 67 b0 3f d4 3d 3a 60 07 81 d5 99 eb 40 d4 1b 33 g.?.=:`. ....@..3
0050 f0 a3 e5 69 06 41 90 8b 75 a0 4e d6 29 4e 49 ce ...i.A.. u.N.)NI.
0060 80 ab 81 25 03 06 be d4 3c dd d0 60 9d d4 3c a8 ...%.... <..`..<.
0070 a5 bc 28 89 8d 81 23 2f 5f 17 2c c2 c0 06 89 53 ..(...#/ _.,....S
0080 06 19 60 89 92 ad 57 9c 5a 0c f2 b2 ad 93 63 86 ..`...W. Z.....c.
0090 b9 a3 a3 aa b1 0b 08 19 38 32 b0 80 8a 08 06 3e ........ 82.....>
00a0 50 3a ca 01 31 ad 2c 0c 2c 0c 19 d8 72 81 45 53 P:..1.,. ,...r.ES
00b0 7e 0a 03 b3 bb 6b 08 03 40 6c 05 45 89 e9 b9 89 ~....k.. @l.E....
00c0 c8 46 17 03 c9 dc 54 06 d6 8c 92 92 82 62 06 66 .F....T. .....b.f
00d0 50 40 32 ea 33 70 21 72 3f 43 9a 6f 7e 55 66 4e P@2.3p!r ?C.o~UfN
00e0 4e a2 be a9 9e 81 82 46 84 a1 a1 b5 82 4f 66 5e N......F .....Of^
00f0 69 85 42 85 85 59 bc 99 89 a6 82 23 30 30 53 c3 i.B..Y.. ...#00S.
0100 53 93 bc 33 4b f4 4d 8d 4d f4 8c cd 14 34 bc 3d S..3K.M. M....4.=
0110 42 7c 7d 74 14 72 32 b3 53 15 dc 53 93 b3 f3 35 B|}t.r2. S..S...5
0120 15 9c 33 80 c5 58 aa be a1 b1 1e 30 e4 cc cc f5 ..3..X.. ...0....
0130 0c 15 82 13 d3 12 8b 32 a1 7a 18 d8 a1 71 c9 c0 .......2 .z...q..
0140 01 8b 62 00 00 00 00 ff ff ..b..... .
There are two compressed frames in there (note-to-self: are these two different packets assembled into one by Wireshark?). The first packet is confirmation to the server of a SPDY session. The second packet is a SYN_STREAM frame (fourth octet is 0x01). The first line of that packet is SYN_STREAM overhead: control bit, SPDY version, the SYN_STREAM type, the packet length, etc. The rest of the packet is name-value (NV) data. I know how to decompress NV data!

I drop into the node REPL to see the decompressed contents of the NV frame (with setup from the other day):
> var context = new ZLibContext(flatDict);
> var d1 = new Buffer([0x38, 0xea, 0xdf, 0xa2, 0x51, 0xb2, 0x62, 0xe0, 0x65, 0x60, 0x83, 0xa4, 0x17, 0x06, 0x7b, 0xb8, 0x0b, 0x75, 0x30, 0x2c, 0xd6, 0xae, 0x40, 0x17, 0xcd, 0xcd, 0xb1, 0x2e, 0xb4, 0x35, 0xd0, 0xb3, 0xd4, 0xd1, 0xd2, 0xd7, 0x02, 0xb3, 0x2c, 0x18, 0xf8, 0x50, 0x73, 0x2c, 0x83, 0x9c, 0x67, 0xb0, 0x3f, 0xd4, 0x3d, 0x3a, 0x60, 0x07, 0x81, 0xd5, 0x99, 0xeb, 0x40, 0xd4, 0x1b, 0x33, 0xf0, 0xa3, 0xe5, 0x69, 0x06, 0x41, 0x90, 0x8b, 0x75, 0xa0, 0x4e, 0xd6, 0x29, 0x4e, 0x49, 0xce, 0x80, 0xab, 0x81, 0x25, 0x03, 0x06, 0xbe, 0xd4, 0x3c, 0xdd, 0xd0, 0x60, 0x9d, 0xd4, 0x3c, 0xa8, 0xa5, 0xbc, 0x28, 0x89, 0x8d, 0x81, 0x23, 0x2f, 0x5f, 0x17, 0x2c, 0xc2, 0xc0, 0x06, 0x89, 0x53, 0x06, 0x19, 0x60, 0x89, 0x92, 0xad, 0x57, 0x9c, 0x5a, 0x0c, 0xf2, 0xb2, 0xad, 0x93, 0x63, 0x86, 0xb9, 0xa3, 0xa3, 0xaa, 0xb1, 0x0b, 0x08, 0x19, 0x38, 0x32, 0xb0, 0x80, 0x8a, 0x08, 0x06, 0x3e, 0x50, 0x3a, 0xca, 0x01, 0x31, 0xad, 0x2c, 0x0c, 0x2c, 0x0c, 0x19, 0xd8, 0x72, 0x81, 0x45, 0x53, 0x7e, 0x0a, 0x03, 0xb3, 0xbb, 0x6b, 0x08, 0x03, 0x40, 0x6c, 0x05, 0x45, 0x89, 0xe9, 0xb9, 0x89, 0xc8, 0x46, 0x17, 0x03, 0xc9, 0xdc, 0x54, 0x06, 0xd6, 0x8c, 0x92, 0x92, 0x82, 0x62, 0x06, 0x66, 0x50, 0x40, 0x32, 0xea, 0x33, 0x70, 0x21, 0x72, 0x3f, 0x43, 0x9a, 0x6f, 0x7e, 0x55, 0x66, 0x4e, 0x4e, 0xa2, 0xbe, 0xa9, 0x9e, 0x81, 0x82, 0x46, 0x84, 0xa1, 0xa1, 0xb5, 0x82, 0x4f, 0x66, 0x5e, 0x69, 0x85, 0x42, 0x85, 0x85, 0x59, 0xbc, 0x99, 0x89, 0xa6, 0x82, 0x23, 0x30, 0x30, 0x53, 0xc3, 0x53, 0x93, 0xbc, 0x33, 0x4b, 0xf4, 0x4d, 0x8d, 0x4d, 0xf4, 0x8c, 0xcd, 0x14, 0x34, 0xbc, 0x3d, 0x42, 0x7c, 0x7d, 0x74, 0x14, 0x72, 0x32, 0xb3, 0x53, 0x15, 0xdc, 0x53, 0x93, 0xb3, 0xf3, 0x35, 0x15, 0x9c, 0x33, 0x80, 0xc5, 0x58, 0xaa, 0xbe, 0xa1, 0xb1, 0x1e, 0x30, 0xe4, 0xcc, 0xcc, 0xf5, 0x0c, 0x15, 0x82, 0x13, 0xd3, 0x12, 0x8b, 0x32, 0xa1, 0x7a, 0x18, 0xd8, 0xa1, 0x71, 0xc9, 0xc0, 0x01, 0x8b, 0x62, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]);
> var u1 = context.inflate(d1);
> u1.toString();
'\u0000\r\u0000\u0006accept\u0000?text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\u0000\u000eaccept-charset\u0000\u001eISO-8859-1,utf-8;q=0.7,*;q=0.3\u0000\u000faccept-encoding\u0000\u0011gzip,deflate,sdch\u0000\u000faccept-language\u0000\u000een-US,en;q=0.8\u0000\rcache-control\u0000\bno-cache\u0000\u0006cookie\u0000\u001crack.session=BAh7AA%3D%3D%0A\u0000\u0004host\u0000\u000elocalhost:8081\u0000\u0006method\u0000\u0003GET\u0000\u0006pragma\u0000\bno-cache\u0000\u0006scheme\u0000\u0005https\u0000\u0003url\u0000\u0001/\u0000\nuser-agent\u0000fMozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.36 (KHTML, like Gecko) Chrome/13.0.767.1 Safari/534.36\u0000\u0007version\u0000\bHTTP/1.1'
Not surprisingly, that is a request for the homepage.

The next packet is:
request »»»
64 7.074843 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 01 01 00 00 40 00 00 00 03 00 00 00 00 .......@ ........
0010 40 00 62 e0 83 c7 a8 10 38 46 93 8b 8b e1 91 64 @.b..... 8F.....d
0020 38 72 22 89 1d 5a 28 33 88 83 63 c9 4a 5f 1f 55 8r"..Z(3 ..c.J_.U
0030 bf 3e d6 68 e4 d2 2f 2e a9 cc 49 d5 03 06 da 20 .>.h../. ..I....
0040 89 4f 00 00 00 00 ff ff .O......
Running that through the node REPL decompressor (re-using the same context, of course), I find:
 > var d2 = new Buffer([0x62, 0xe0, 0x83, 0xc7, 0xa8, 0x10, 0x38, 0x46, 0x93, 0x8b, 0x8b, 0xe1, 0x91, 0x64, 0x38, 0x72, 0x22, 0x89, 0x1d, 0x5a, 0x28, 0x33, 0x88, 0x83, 0x63, 0xc9, 0x4a, 0x5f, 0x1f, 0x55, 0xbf, 0x3e, 0xd6, 0x68, 0xe4, 0xd2, 0x2f, 0x2e, 0xa9, 0xcc, 0x49, 0xd5, 0x03, 0x06, 0xda, 0x20, 0x89, 0x4f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff]);
> var u2 = context.inflate(d2);
> u2.toString();
'\u0000\u000e\u0000\u0006accept\u0000\u0012text/css,*/*;q=0.1\u0000\u000eaccept-charset\u0000\u001eISO-8859-1,utf-8;q=0.7,*;q=0.3\u0000\u000faccept-encoding\u0000\u0011gzip,deflate,sdch\u0000\u000faccept-language\u0000\u000een-US,en;q=0.8\u0000\rcache-control\u0000\bno-cache\u0000\u0006cookie\u0000\u001crack.session=BAh7AA%3D%3D%0A\u0000\u0004host\u0000\u000elocalhost:8081\u0000\u0006method\u0000\u0003GET\u0000\u0006pragma\u0000\bno-cache\u0000\u0007referer\u0000\u0017https://localhost:8081/\u0000\u0006scheme\u0000\u0005https\u0000\u0003url\u0000\n/style.css\u0000\nuser-agent\u0000fMozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.36 (KHTML, like Gecko) Chrome/13.0.767.1 Safari/534.36\u0000\u0007version\u0000\bHTTP/1.1'
That is a request for the style.css file.

Next up is:
request »»»
69 7.120765 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 01 00 00 00 46 00 00 00 05 00 00 00 00 .......F ........
0010 80 00 62 10 84 c7 27 33 30 1a 07 59 04 f2 a1 96 ..b...'3 0..Y....
0020 cb 0c 4c 86 16 0c 3c c8 a5 2e d0 6c d4 62 83 2a ..L...<. ...l.b.*
0030 71 ce 12 e0 1f 0c 8c f4 fc a2 cc f4 cc 3c 06 31 q....... .....<.1
0040 ec 31 4c b5 44 31 68 f2 36 00 00 00 ff ff .1L.D1h. 6.....
This decompresses to:
'\u0000\u0011\u0000\u0006accept\u0000\u0003*/*\u0000\u000eaccept-charset\u0000\u001eISO-8859-1,utf-8;q=0.7,*;q=0.3\u0000\u000faccept-encoding\u0000\u0011gzip,deflate,sdch\u0000\u000faccept-language\u0000\u000een-US,en;q=0.8\u0000\rcache-control\u0000\bno-cache\u0000\u000econtent-length\u0000\u000218\u0000\fcontent-type\u0000\u000fapplication/xml\u0000\u0006cookie\u0000\u001crack.session=BAh7AA%3D%3D%0A\u0000\u0004host\u0000\u000elocalhost:8081\u0000\u0006method\u0000\u0004POST\u0000\u0006origin\u0000\u0016https://localhost:8081\u0000\u0006pragma\u0000\bno-cache\u0000\u0007referer\u0000\u0017https://localhost:8081/\u0000\u0006scheme\u0000\u0005https\u0000\u0003url\u0000\u0001/\u0000\nuser-agent\u0000fMozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.36 (KHTML, like Gecko) Chrome/13.0.767.1 Safari/534.36\u0000\u0007version\u0000\bHTTP/1.1'
Weird that looks to be a second request for the top-level home page.

The next request packet is similar strange:
request »»»
70 7.122965 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 00 00 00 05 01 00 00 12 68 65 6c 6c 6f 20 66 72 ........ hello fr
0010 6f 6d 20 73 65 72 76 65 72 21 om serve r!
Bizarre! That is just a plain-text, not-even-SPDY response. That certainly warrants some investigation at some point.

Next up, we return to SPDY request land:
request »»»
73 7.131861 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 01 01 00 00 26 00 00 00 07 00 00 00 00 .......& ........
0010 80 00 42 ca db 83 30 2d 0c ba cc cc a9 5f 5c 90 ..B...0- ....._\.
0020 52 a9 97 55 90 3e 48 e2 0f 00 00 00 ff ff R..U.>H. ......
This decompresses to:
'\u0000\u000e\u0000\u0006accept\u0000\u0003*/*\u0000\u000eaccept-charset\u0000\u001eISO-8859-1,utf-8;q=0.7,*;q=0.3\u0000\u000faccept-encoding\u0000\u0011gzip,deflate,sdch\u0000\u000faccept-language\u0000\u000een-US,en;q=0.8\u0000\rcache-control\u0000\bno-cache\u0000\u0006cookie\u0000\u001crack.session=BAh7AA%3D%3D%0A\u0000\u0004host\u0000\u000elocalhost:8081\u0000\u0006method\u0000\u0003GET\u0000\u0006pragma\u0000\bno-cache\u0000\u0007referer\u0000\u0017https://localhost:8081/\u0000\u0006scheme\u0000\u0005https\u0000\u0003url\u0000\t/spdy.jpg\u0000\nuser-agent\u0000fMozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.36 (KHTML, like Gecko) Chrome/13.0.767.1 Safari/534.36\u0000\u0007version\u0000\bHTTP/1.1'
This is a request for a JPEG image.

The last request is:
request »»»
87 7.293050 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 01 01 00 00 29 00 00 00 09 00 00 00 00 .......) ........
0010 80 00 62 e0 1e 04 f1 47 bd 68 c2 12 e4 3c fa 69 ..b....G .h...<.i
0020 89 65 99 c0 b4 a1 57 90 37 58 42 1d 00 00 00 ff .e....W. 7XB.....
0030 ff .
Which decompresses to:
'\u0000\u000b\u0000\u0006accept\u0000\u0003*/*\u0000\u000eaccept-charset\u0000\u001eISO-8859-1,utf-8;q=0.7,*;q=0.3\u0000\u000faccept-encoding\u0000\u0011gzip,deflate,sdch\u0000\u000faccept-language\u0000\u000een-US,en;q=0.8\u0000\u0006cookie\u0000\u001crack.session=BAh7AA%3D%3D%0A\u0000\u0004host\u0000\u000elocalhost:8081\u0000\u0006method\u0000\u0003GET\u0000\u0006scheme\u0000\u0005https\u0000\u0003url\u0000\f/favicon.png\u0000\nuser-agent\u0000fMozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.36 (KHTML, like Gecko) Chrome/13.0.767.1 Safari/534.36\u0000\u0007version\u0000\bHTTP/1.1'
A favicon. Of course there had to be a favicon in there somewhere.

That about does it for tracing through the SPDY request side of things. There were a couple of unexpected things in there, but for the most part, normal HTTP requests over SPDY. I will investigate the unexpected another day. Tomorrow I will have a look-see at the response side.


Day #26

No comments:

Post a Comment