Clash.Meta/transport/sing-shadowtls/shadowtls.go

82 lines
2.2 KiB
Go
Raw Normal View History

package sing_shadowtls
import (
"context"
"crypto/tls"
"net"
2023-11-03 21:01:45 +08:00
"github.com/metacubex/mihomo/component/ca"
tlsC "github.com/metacubex/mihomo/component/tls"
"github.com/metacubex/mihomo/log"
"github.com/metacubex/sing-shadowtls"
utls "github.com/metacubex/utls"
)
const (
Mode string = "shadow-tls"
)
var (
DefaultALPN = []string{"h2", "http/1.1"}
)
type ShadowTLSOption struct {
Password string
Host string
Fingerprint string
ClientFingerprint string
SkipCertVerify bool
Version int
2025-04-22 20:49:54 +08:00
ALPN []string
}
func NewShadowTLS(ctx context.Context, conn net.Conn, option *ShadowTLSOption) (net.Conn, error) {
tlsConfig := &tls.Config{
2025-04-22 20:49:54 +08:00
NextProtos: option.ALPN,
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: option.SkipCertVerify,
ServerName: option.Host,
}
2025-04-22 20:09:24 +08:00
if option.Version == 1 {
tlsConfig.MaxVersion = tls.VersionTLS12 // ShadowTLS v1 only support TLS 1.2
}
var err error
2023-09-22 14:45:34 +08:00
tlsConfig, err = ca.GetSpecifiedFingerprintTLSConfig(tlsConfig, option.Fingerprint)
if err != nil {
return nil, err
}
tlsHandshake := uTLSHandshakeFunc(tlsConfig, option.ClientFingerprint)
client, err := shadowtls.NewClient(shadowtls.ClientConfig{
Version: option.Version,
Password: option.Password,
TLSHandshake: tlsHandshake,
Logger: log.SingLogger,
})
if err != nil {
return nil, err
}
return client.DialContextConn(ctx, conn)
}
func uTLSHandshakeFunc(config *tls.Config, clientFingerprint string) shadowtls.TLSHandshakeFunc {
return func(ctx context.Context, conn net.Conn, sessionIDGenerator shadowtls.TLSSessionIDGeneratorFunc) error {
2025-04-21 12:07:33 +08:00
tlsConfig := tlsC.UConfig(config)
tlsConfig.SessionIDGenerator = sessionIDGenerator
clientFingerprint := clientFingerprint
if tlsC.HaveGlobalFingerprint() && len(clientFingerprint) == 0 {
clientFingerprint = tlsC.GetGlobalFingerprint()
}
if len(clientFingerprint) != 0 {
if fingerprint, exists := tlsC.GetFingerprint(clientFingerprint); exists {
2025-04-21 12:07:33 +08:00
tlsConn := tlsC.UClient(conn, tlsConfig, fingerprint)
return tlsConn.HandshakeContext(ctx)
}
}
tlsConn := utls.Client(conn, tlsConfig)
return tlsConn.HandshakeContext(ctx)
}
}