You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In some situations, ConnectionState.ServerName is not enough and the access to the certificate used to negociate the connection is needed.
This issue targets any stateless protocol that can use SNI and an field (inside the protocol) to identify a virtual host.
In Case of HTTP with TLS , SNI ServerName and the Host header provide valid strings that may differ.
Solution
Adding a ServerCertificate *x509.Certificate attribute to tls.ConnectionState struct
tls.Conn has access to tls.Config so ServerCertificate can be set when (*tls.Conn)ConnectionState() is called.
Illustrations of the problem
the context is a HTTPS offloader/reverse-proxy that have 2 differents certificates each for a different *.FQDN in CommonName ; precisely, cert-1 has *.FQDN-1 CommonName and cert-2 has *.FQDN-2 CommonName
Good case (easily produced with any browser)
client connects to the server with a SNI header to foo.FQDN-1 and a Host: foo.FQDN-1
server sets request.TLS.ServerName and call ServeHTTP foo.FQDN-1
inside ServeHTTP, request.TLS.ServerName and req.Host have the same value
ServeHTTP answers a redirection to bar.FQDN-1
client reuses the same connection & Session Ticket because the Certificate's CommonName allow it
inside ServerHTTP , request.TLS.ServerName and req.Host have different values because req.TLS.ServerName was set in the first connection
a call to req.TLS.ServerCertificate.VerifyHostname(req.Host) will return nil to confirm that bar.FQDN-1 can be served on the same connection.
Bad case
client connects to the server with a SNI header to foo.FQDN-1 and a Host: foo.FQDN-1
server sets request.TLS.ServerName and call ServeHTTP foo.FQDN-1
client crafts a HTTP request to foo.FQDN-2 and reuse the previous connection
inside ServerHTTP , request.TLS.ServerName and req.Host have different values
Here, a call to req.TLS.ServerCertificate.VerifyHostname(req.Host) will return an error. this call provide an elegant way to mitigate the situation.
There are others way to mitigate this situation but are also more complicated.
The text was updated successfully, but these errors were encountered:
ianlancetaylor
changed the title
Missing attribute in tls.ConnectionState struct
crypto/tls: Missing attribute in tls.ConnectionState struct
Jul 27, 2015
Why's it a problem if the the ServerName doesn't match the Host header? If the client wants to reuse the connection, presumably it did so because it saw the cert from the first connection and knew that the server did FQDN-2 as well. Doesn't HTTP/2 actually encourage that behavior?
Hi,
Summary
In some situations,
ConnectionState.ServerName
is not enough and the access to the certificate used to negociate the connection is needed.This issue targets any stateless protocol that can use SNI and an field (inside the protocol) to identify a virtual host.
In Case of HTTP with TLS , SNI ServerName and the Host header provide valid strings that may differ.
Solution
Adding a
ServerCertificate *x509.Certificate
attribute totls.ConnectionState
structtls.Conn
has access totls.Config
soServerCertificate
can be set when(*tls.Conn)ConnectionState()
is called.Illustrations of the problem
the context is a HTTPS offloader/reverse-proxy that have 2 differents certificates each for a different *.FQDN in CommonName ; precisely, cert-1 has *.FQDN-1 CommonName and cert-2 has *.FQDN-2 CommonName
Good case (easily produced with any browser)
foo.FQDN-1
and a Host:foo.FQDN-1
request.TLS.ServerName
and call ServeHTTPfoo.FQDN-1
request.TLS.ServerName
andreq.Host
have the same valuebar.FQDN-1
CommonName
allow itrequest.TLS.ServerName
andreq.Host
have different values becausereq.TLS.ServerName
was set in the first connectiona call to
req.TLS.ServerCertificate.VerifyHostname(req.Host)
will returnnil
to confirm thatbar.FQDN-1
can be served on the same connection.Bad case
foo.FQDN-1
and a Host:foo.FQDN-1
request.TLS.ServerName
and call ServeHTTPfoo.FQDN-1
foo.FQDN-2
and reuse the previous connectionrequest.TLS.ServerName
andreq.Host
have different valuesHere, a call to
req.TLS.ServerCertificate.VerifyHostname(req.Host)
will return an error. this call provide an elegant way to mitigate the situation.There are others way to mitigate this situation but are also more complicated.
The text was updated successfully, but these errors were encountered: