Patch Proposal: TLS ServerName Callback

133 views
Skip to first unread message

Ben Burkert

unread,
Jan 27, 2012, 4:36:06 PM1/27/12
to golan...@googlegroups.com
The Server Name Indication (SNI) extension to TLS is supported by Go's crypto/tls package. It is implemented by adding the ServerName field to the tls.Config type. This only used by the client handshake to specify the hostname of the server it is attempting to connect with. The server handshake code ignores it completely.

OpenSSL first implemented the SNI extension in version 0.9.8f. This implementation included an optional callback that could change the SSL context (analogous to tls.Config) based on the hostname the client supplied during the ClientHello. If the callback returns null, the current SSL context is used to finish the handshake. If the callback returns a context, the current SSL object replaces the default context with the new context and proceeds to finish the handshake. This provides virtual host functionality: the server certificate provided to the client may change based on the host that the client is attempting to connect with.

I propose changing tls.Config to include a field for a function variable that may return a tls.Config or nil. During the server's handshake phase, after the ClientHello has been recieved, the callback function should be called with the server name. If this callback returns a *tls.Config, then the handshake proceeds with the alternate Config. This would provide the necessary functionality to implement TLS virtual hosting in Go. It is also the same common pattern implemented in other languages:


I also propose adding a ServerName field to tls.ConnectionState. Currently, there is no way for a server Conn to know the hostname that the client supplied. This information is useful, for example, when implementing an HTTP proxy server where it is important that the upstream server know that the client supports SNI (so that the response body can safely include URLs to resources hosted on SNI based webservers). The (c *Conn) ConnectionState() would need to lookup the value for ServerName from the config field.

I'm very interested in working on this patch because the concurrency primitives in Go make it well suited for implementing an SSL termination server with virtual host functionality. Please let me know if there is anything I can clarify or any issues/complications I may have overlooked.

Thanks,
-Ben

Brad Fitzpatrick

unread,
Jan 27, 2012, 5:29:30 PM1/27/12
to Ben Burkert, Adam Langley, golan...@googlegroups.com
[+agl]

I agree that SNI support for both client & server is very important, but I thought we already had it.  Perhaps I'm remembering something else.

Adam?

Adam Langley

unread,
Jan 27, 2012, 5:35:33 PM1/27/12
to Brad Fitzpatrick, Ben Burkert, golan...@googlegroups.com
On Fri, Jan 27, 2012 at 2:29 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
> [+agl]
>
> I agree that SNI support for both client & server is very important, but I
> thought we already had it.  Perhaps I'm remembering something else.

We don't actually do SNI certificate selection in the server because
it works so badly on the current Internet. (Due to a lack of client
support.) But we don't need any tls.Config changes. We already have
NameToCertificate and Certificates.

I don't object to adding ServerName to the ConnectionState.


Cheers

AGL

Brad Fitzpatrick

unread,
Jan 27, 2012, 5:44:35 PM1/27/12
to Adam Langley, Ben Burkert, golan...@googlegroups.com
On Fri, Jan 27, 2012 at 2:35 PM, Adam Langley <a...@golang.org> wrote:
On Fri, Jan 27, 2012 at 2:29 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
> [+agl]
>
> I agree that SNI support for both client & server is very important, but I
> thought we already had it.  Perhaps I'm remembering something else.

We don't actually do SNI certificate selection in the server because
it works so badly on the current Internet. (Due to a lack of client
support.) But we don't need any tls.Config changes. We already have
NameToCertificate and Certificates.

NameToCertificate was what I was remembering, but I don't think it could be used to e.g. look up a certificate in a database from a name (imagine some HTTP load balancer front-end terminating TLS for thousands of sites speaking plain HTTP inside the network).

Ben Burkert

unread,
Jan 27, 2012, 6:22:16 PM1/27/12
to golan...@googlegroups.com

On Friday, January 27, 2012 at 3:09 PM, Ben Burkert wrote:


On Friday, January 27, 2012 at 2:35 PM, Adam Langley wrote:


I don't object to adding ServerName to the ConnectionState.


Excellent! I'll start with this patch. (p.s. thanks for the heads up about the API freeze, I'll wait until post 1.0 before submitting it).


Actually, it looks like this has already been implemented. bonus!
 
Cheers,
-Ben

Ben Burkert

unread,
Jan 27, 2012, 6:09:40 PM1/27/12
to golan...@googlegroups.com

On Friday, January 27, 2012 at 2:35 PM, Adam Langley wrote:

On Fri, Jan 27, 2012 at 2:29 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
[+agl]

I agree that SNI support for both client & server is very important, but I
thought we already had it.  Perhaps I'm remembering something else.

We don't actually do SNI certificate selection in the server because
it works so badly on the current Internet. (Due to a lack of client
support.) But we don't need any tls.Config changes. We already have
NameToCertificate and Certificates.

Ah ha. I checked out the latest release of Go and missed the addition of NameToCertificate. That would indeed support "TLS vhost"ing, sorry for the misinformation. But it would not be possible to add a cert to the NameToCertificate between the time the server receives the ClientHello message and the call to getCertificateForName(). But I'm hoping to lookup the server cert & key from a datastore based on the server name supplied by the client. AFAIK, it's not currently possible to implement this server functionality. Unless it's possible to somehow overload/extend the map type and build a Config with a NameToCertificate of that type?
 

I don't object to adding ServerName to the ConnectionState.


Excellent! I'll start with this patch. (p.s. thanks for the heads up about the API freeze, I'll wait until post 1.0 before submitting it).


Cheers

AGL

Adam Langley

unread,
Jan 27, 2012, 9:45:25 PM1/27/12
to Brad Fitzpatrick, Ben Burkert, golan...@googlegroups.com
On Fri, Jan 27, 2012 at 2:44 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
> NameToCertificate was what I was remembering, but I don't think it could be
> used to e.g. look up a certificate in a database from a name (imagine some
> HTTP load balancer front-end terminating TLS for thousands of sites speaking
> plain HTTP inside the network).

That's true, but it doesn't mean that we should handle that case on
the off-chance that someone needs to do it. If we were playing `what
if' games then there's far lower-hanging fruit (like supporting
session tickets).


Cheers

AGL

Reply all
Reply to author
Forward
0 new messages