diff --git a/src/core/link.go b/src/core/link.go index ccab9219..8797b886 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -98,6 +98,22 @@ func (l *links) call(u *url.URL, sintf string) error { l.tcp.call(pathtokens[0], tcpOpts, sintf) case "tls": tcpOpts.upgrade = l.tcp.tls.forDialer + // SNI headers must contain hostnames and not IP addresses, so we must make sure + // that we do not populate the SNI with an IP literal. We do this by splitting + // the host-port combo from the query option and then seeing if it parses to an + // IP address successfully or not. + if sni := u.Query().Get("sni"); sni != "" { + if net.ParseIP(sni) == nil { + tcpOpts.tlsSNI = sni + } + } + // If the SNI is not configured still because the above failed then we'll try + // again but this time we'll use the host part of the peering URI instead. + if tcpOpts.tlsSNI == "" { + if host, _, err := net.SplitHostPort(u.Host); err == nil && net.ParseIP(host) == nil { + tcpOpts.tlsSNI = host + } + } l.tcp.call(u.Host, tcpOpts, sintf) default: return errors.New("unknown call scheme: " + u.Scheme) diff --git a/src/core/tcp.go b/src/core/tcp.go index 572fd652..7b1773b8 100644 --- a/src/core/tcp.go +++ b/src/core/tcp.go @@ -64,6 +64,7 @@ type tcpOptions struct { socksProxyAddr string socksProxyAuth *proxy.Auth socksPeerAddr string + tlsSNI string } func (l *TcpListener) Stop() { diff --git a/src/core/tls.go b/src/core/tls.go index 4c25225b..9e340ac4 100644 --- a/src/core/tls.go +++ b/src/core/tls.go @@ -78,7 +78,7 @@ func (t *tcptls) init(tcp *tcp) { } func (t *tcptls) configForOptions(options *tcpOptions) *tls.Config { - config := *t.config + config := t.config.Clone() config.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { if len(rawCerts) != 1 { return errors.New("tls not exactly 1 cert") @@ -103,7 +103,7 @@ func (t *tcptls) configForOptions(options *tcpOptions) *tls.Config { } return nil } - return &config + return config } func (t *tcptls) upgradeListener(c net.Conn, options *tcpOptions) (net.Conn, error) { @@ -117,6 +117,7 @@ func (t *tcptls) upgradeListener(c net.Conn, options *tcpOptions) (net.Conn, err func (t *tcptls) upgradeDialer(c net.Conn, options *tcpOptions) (net.Conn, error) { config := t.configForOptions(options) + config.ServerName = options.tlsSNI conn := tls.Client(c, config) if err := conn.Handshake(); err != nil { return c, err