github.com/kelleygo/clashcore@v1.0.2/transport/vmess/tls.go (about) 1 package vmess 2 3 import ( 4 "context" 5 "crypto/tls" 6 "errors" 7 "net" 8 9 "github.com/kelleygo/clashcore/component/ca" 10 tlsC "github.com/kelleygo/clashcore/component/tls" 11 ) 12 13 type TLSConfig struct { 14 Host string 15 SkipCertVerify bool 16 FingerPrint string 17 ClientFingerprint string 18 NextProtos []string 19 Reality *tlsC.RealityConfig 20 } 21 22 func StreamTLSConn(ctx context.Context, conn net.Conn, cfg *TLSConfig) (net.Conn, error) { 23 tlsConfig := &tls.Config{ 24 ServerName: cfg.Host, 25 InsecureSkipVerify: cfg.SkipCertVerify, 26 NextProtos: cfg.NextProtos, 27 } 28 29 var err error 30 tlsConfig, err = ca.GetSpecifiedFingerprintTLSConfig(tlsConfig, cfg.FingerPrint) 31 if err != nil { 32 return nil, err 33 } 34 35 if len(cfg.ClientFingerprint) != 0 { 36 if cfg.Reality == nil { 37 utlsConn, valid := GetUTLSConn(conn, cfg.ClientFingerprint, tlsConfig) 38 if valid { 39 err := utlsConn.(*tlsC.UConn).HandshakeContext(ctx) 40 return utlsConn, err 41 } 42 } else { 43 return tlsC.GetRealityConn(ctx, conn, cfg.ClientFingerprint, tlsConfig, cfg.Reality) 44 } 45 } 46 if cfg.Reality != nil { 47 return nil, errors.New("REALITY is based on uTLS, please set a client-fingerprint") 48 } 49 50 tlsConn := tls.Client(conn, tlsConfig) 51 52 err = tlsConn.HandshakeContext(ctx) 53 return tlsConn, err 54 } 55 56 func GetUTLSConn(conn net.Conn, ClientFingerprint string, tlsConfig *tls.Config) (net.Conn, bool) { 57 58 if fingerprint, exists := tlsC.GetFingerprint(ClientFingerprint); exists { 59 utlsConn := tlsC.UClient(conn, tlsConfig, fingerprint) 60 61 return utlsConn, true 62 } 63 64 return nil, false 65 }