莫粒 的多维空间


关于 | GitHub | Twitter

golang读取ssl的ClientHello

问题:作为一个反向代理,如何从ssl中读取到host?

经过半天的看golang的源码……其实代码只有几行,但是特么缺看源码的时间,整理思路 到 尝试。。缺花了很长时间。。

终于把问题解决了,然后写篇博客吧……反而写博客的心里更放松…

需求是这样的:

大家知道nginx的https,配置时可以给每一个server配置ssl。

所以有一个有一个类似的需求:

需要根据不同的域名,加载不同的ssl证书。

但是一般我们不会像nginx,从tcp层读取并解析ssl协议中的 client hello请求。

所以,我就想,既然golang的源码(tls包)已有了,为啥不能直接拿过来用。

so,源码如下:

ln, err := net.Listen("tcp", ":443")  // 监听tcp
if err != nil {
    return
}
for {
    conn, err := ln.Accept()
    if err != nil {
        continue
    }
    tlsconn = tls.Server(conn, &tls.Config{})   // 初始化一个tls *tls.Conn
    tlsconn.Handshake()                         // 读取tls的握手(Client Hello)
    state := tlsconn.ConnectionState()          // 完成 ConnectionState returns basic TLS details about the connection.
    this.log.Info("server name ", state.ServerName)  // Client hello中的扩展字段会带上server name,这里会输出host
}

完毕。

================

上面的不是很合理,后来发现tls.Config中有一个 GetCertificate 回调方法。。。完美解决。。。

tlsCfg := &tls.Config{
    GetCertificate: func(info *tls.ClientHelloInfo) (cert *tls.Certificate, err error) {

    },
}