Up today, I would like to mess about with SPDY over SSL. Last night, I was able to play around a bit with the eventmachine example implementation in the SPDY gem. I even got to inspect SPDY packets with
tcpdump
. The only thing lacking from last night's experiment was SSL—a necessary component of SPDY. Tonight I hope to repeat that success with
ssldump
.First, I re-enable the
start_tls
line in the example eventmachine code. I then open the application which now resides at: https://localhost:10000/.I get a warning that the certificate is not trusted, but proceed anyway only to get... nothing. The browser never receives a result, though the event machine server kindly reports:
[:SPDY, :connection_closed]This message indicates that the browser has unbound the connection:
def unbindHrm...
p [:SPDY, :connection_closed]
end
Next up, I actually follow the instructions in the example server and start Chrome with the
--use-spdy=ssl
. According to the SPDY debugging page, this option "forces Chrome to always use SPDY, even if not negotiated over SSL". That actually does the trick:Interesting. So if the debugging page is correct, then the reason this works is that, otherwise the connection is made while negotiating over plain text. That is something to investigate another day.
For today, if I am going to sniff SSL packets, I am going to need a server certificate. The whole point of SSL, of course, is to make packet sniffing impossible (or at least prohibitively difficult). It is possible, however, if you have the server's private key. To make one, I use
openssl
:➜ spdy git:(master) openssl genrsa -out key.pem 1024To use that in eventmachine, I change the
Generating RSA private key, 1024 bit long modulus
.........................................................++++++
.........................++++++
e is 65537 (0x10001)
➜ spdy git:(master) ✗ openssl req -new -key key.pem -out request.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Maryland
Locality Name (eg, city) []:Baltimore
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Chris Strom
Email Address []:chris@eeecomputes.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:password
An optional company name []:
➜ spdy git:(master) ✗ openssl x509 -req -days 30 -in request.pem -signkey key.pem -out cert.pem
Signature ok
subject=/C=US/ST=Maryland/L=Baltimore/O=Internet Widgits Pty Ltd/CN=Chris Strom/emailAddress=chris@eeecomputes.com
Getting Private key
start_tls
:def post_initAfter restarting the server, I verify that I can still access the example SPDY site. Once I am confident that everything still works with the new certificate, I am ready to try out
@parser = SPDY::Parser.new
@parser.on_headers_complete do |stream_id, associated_stream, priority, headers|
# ...
end
#start_tls
start_tls(:private_key_file => 'key.pem', :cert_chain_file => 'cert.pem', :verify_peer => false)
end
ssldump
:sudo ssldump -k key.pem -i lo -dXThe
-k
option uses the same private key file that I just generated and that eventmachine is now using. The example server is listening on localhost, so I need to sniff the packets on the loopback interface, lo
. The -dX
option tells ssldump
to dump the packet contents in hex—ideally this is exactly what I did last night using tcpdump, but now I will be able to see an (almost) real SPDY conversation take place.And, sure enough, that does the trick:
➜ examples git:(master) ✗ sudo ssldump -k key.pem -i lo -dXThe fourth byte in bold indicates that this is a SYN_STREAM just like I saw last night.
New TCP connection #1: localhost.localdomain(35098) <-> localhost.localdomain(10000)
New TCP connection #2: localhost.localdomain(35099) <-> localhost.localdomain(10000)
1 1 0.0071 (0.0071) C>S Handshake
ClientHello
Version 3.1
...
3 7 0.0040 (0.0000) C>S Handshake3 8 0.0040 (0.0000) C>S application_data
---------------------------------------------------------------
00 2c 01 d3 fe 80 02 00 01 01 00 01 24 00 00 00
01 00 00 00 00 00 00 38 ea df a2 51 b2 62 e0 61
60 83 a4 17 06 7b b8 0b 75 30 2c d6 ae 40 17 cd
cd b1 2e b4 35 d0 b3 d4 d1 d2 d7 02 b3 2c 18 f8
50 73 2c 83 9c 67 b0 3f d4 3d 3a 60 07 81 d5 99
eb 40 d4 1b 33 f0 a3 e5 69 06 41 90 8b 75 a0 4e
d6 29 4e 49 ce 80 ab 81 25 03 06 be d4 3c dd d0
60 9d d4 3c a8 a5 bc 28 89 8d 81 23 2f 5f 17 2c
c2 c0 02 ca fc 0c fc a0 14 92 03 62 5a 01 73 a4
81 01 03 5b 2e b0 d4 c9 4f 61 60 76 77 0d 61 60
2b 28 4a 4c cf 4d 44 d2 c5 56 0c 24 73 53 19 58
33 4a 4a 0a 8a 19 98 41 61 c4 a8 cf 00 10 17 22
63 33 a4 fb e6 57 65 e6 e4 24 ea 9b ea 19 28 68
44 18 1a 5a 2b f8 64 e6 95 56 28 54 58 98 c5 9b
99 68 2a 38 02 c3 29 35 3c 35 c9 3b b3 44 df d4
d8 44 cf 18 a8 cc db 23 c4 d7 47 47 21 27 33 3b
55 c1 3d 35 39 3b 5f 53 c1 39 03 58 42 a5 ea 1b
1a e9 01 03 c5 c4 48 cf d0 48 21 38 31 2d b1 28
13 aa 89 81 1d 1a 4f 0c 1c b0 e8 03 00 00 00 ff
ff 00 00 00 ff ff
---------------------------------------------------------------
...
That is a good place to stop for the night. Hopefully I will not have to rely on this technique much while working with SPDY, but it is good to know that it is available if needed.
SPDY protocol (draft 2)
Day #6
No comments:
Post a Comment