Add sockstls:// (#1090)

Closes #1087.

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
Neil 2023-11-04 17:57:15 +00:00 committed by GitHub
parent ddb75700a0
commit 93a5adfd18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 18 deletions

View File

@ -179,6 +179,22 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
} }
options.password = []byte(p) options.password = []byte(p)
} }
// 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 {
options.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 options.tlsSNI == "" {
if host, _, err := net.SplitHostPort(u.Host); err == nil && net.ParseIP(host) == nil {
options.tlsSNI = host
}
}
// If we think we're already connected to this peer, load up // If we think we're already connected to this peer, load up
// the existing peer state. Try to kick the peer if possible, // the existing peer state. Try to kick the peer if possible,
@ -497,24 +513,8 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
case "tcp": case "tcp":
dialer = l.tcp dialer = l.tcp
case "tls": case "tls":
// 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 {
options.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 options.tlsSNI == "" {
if host, _, err := net.SplitHostPort(u.Host); err == nil && net.ParseIP(host) == nil {
options.tlsSNI = host
}
}
dialer = l.tls dialer = l.tls
case "socks": case "socks", "sockstls":
dialer = l.socks dialer = l.socks
case "unix": case "unix":
dialer = l.unix dialer = l.unix

View File

@ -2,6 +2,7 @@ package core
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"net" "net"
"net/url" "net/url"
@ -34,7 +35,16 @@ func (l *linkSOCKS) dial(_ context.Context, url *url.URL, info linkInfo, options
return nil, fmt.Errorf("failed to configure proxy") return nil, fmt.Errorf("failed to configure proxy")
} }
pathtokens := strings.Split(strings.Trim(url.Path, "/"), "/") pathtokens := strings.Split(strings.Trim(url.Path, "/"), "/")
return dialer.Dial("tcp", pathtokens[0]) conn, err := dialer.Dial("tcp", pathtokens[0])
if err != nil {
return nil, fmt.Errorf("failed to dial: %w", err)
}
if url.Scheme == "sockstls" {
tlsconfig := l.tls.config.Clone()
tlsconfig.ServerName = options.tlsSNI
conn = tls.Client(conn, tlsconfig)
}
return conn, nil
} }
func (l *linkSOCKS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) { func (l *linkSOCKS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {