I’m attempting to implement a paper’s technique which requires matching a HTTP request to its underlying TLS connection, specifically the ClientHelloInfo used in the handshake.
I am wondering if anyone has a good solution for getting the underlying TLS connection (not just the connection state) from an http.Request, or if maybe there’s some way (a custom listener?) to expose the ClientHelloInfo to HTTP handlers…
Ah! That’s so elegant! How did I miss this?? I think my Go foo must be weak since I’ve been doing too much JS and Python lately.
… maybe it’s because I have already “used” the GetCertificate callback in my code and I just glossed over the fact that it gives access to the ClientHelloInfo and its type can also be used as a Handler. See, that’s nice. That’s real nice.
I’ll have to take care with thread safety but, yeah… Thank you! That should do the trick.
Haha to be honest, I’ve never worked with anything related to what you were asking so I just used my best skill of messing around with stuff to work it out in conjunction with my second best skill of googling what the stuff was that you were asking about
It’s probably because I haven’t worked with it before that I came up with a solution that would be simple for you because I wouldn’t overlook things by accident lol!
I see the elegance of the solution (hats off!), but I don’t get it completely.
The code creates a tls.Config with nothing but the GetCertifcate func set and all other fields left at their zero value. Is this really sufficient for handling TLS or did you just leave out all the other stuff for brevity?
Personally I left out the other stuff because I haven’t worked with that stuff before, but realized that the function could be used just for setting the value.
With that being said, I knew that someone like @matt would be able to work out the middle parts even if I had no idea what needs to normally be there!
Sometimes I’m not bad at coming up with ideas, but I don’t always understand the details surrounding them all lol!
This is indeed the right way to go about it (in general), however I’m still stuck at trying to associate an http.Request with its ClientHelloInfo. The current method as-is will overwrite the ClientHelloInfo at each handshake… Go 1.8 exposes the underlying net.Conn in the ClientHelloInfo so I feel like we must be close! I just don’t know how to map that to the proper request in the handler… is there a way to access the net.Conn from an HTTP request without hijacking it? If so, I think this is a solved problem then, because I can create a map of net.Conn to their ClientHelloInfo.
ptrVal := reflect.ValueOf(w)
val := reflect.Indirect(ptrVal)
// w is a "http.response" struct from which we get the 'conn' field
valconn := val.FieldByName("conn")
val1 := reflect.Indirect(valconn)
// which is a http.conn from which we get the 'rwc' field
ptrRwc := val1.FieldByName("rwc").Elem()
rwc := reflect.Indirect(ptrRwc)
but… of course, I don’t want to do this if I don’t have to…
Nevermind! Kale Blankenship gave me a tip in the Gopher slack: we can use the RemoteAddr of the net.Conn as a map key. This will match the RemoteAddr field of the request.