package tls import ( "context" tls "github.com/refraction-networking/utls" "net" "time" "github.com/go-gost/core/dialer" "github.com/go-gost/core/logger" md "github.com/go-gost/core/metadata" "github.com/go-gost/x/registry" ) func init() { registry.DialerRegistry().Register("tls", NewDialer) } type tlsDialer struct { md metadata logger logger.Logger options dialer.Options } func NewDialer(opts ...dialer.Option) dialer.Dialer { options := dialer.Options{} for _, opt := range opts { opt(&options) } return &tlsDialer{ logger: options.Logger, options: options, } } func (d *tlsDialer) Init(md md.Metadata) (err error) { return d.parseMetadata(md) } func (d *tlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) { var options dialer.DialOptions for _, opt := range opts { opt(&options) } conn, err := options.Dialer.Dial(ctx, "tcp", addr) if err != nil { d.logger.Error(err) } return conn, err } // Handshake implements dialer.Handshaker func (d *tlsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) { if d.md.handshakeTimeout > 0 { conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout)) defer conn.SetDeadline(time.Time{}) } tlsConfig := d.options.TLSConfig utlsConf := &tls.Config{InsecureSkipVerify: tlsConfig.InsecureSkipVerify, ServerName: tlsConfig.ServerName, ClientAuth: tls.ClientAuthType(tlsConfig.ClientAuth), ClientCAs: tlsConfig.ClientCAs, RootCAs: tlsConfig.RootCAs} if len(tlsConfig.Certificates) > 0 { for _, certificate := range tlsConfig.Certificates { utlsConf.Certificates = append(utlsConf.Certificates, tls.Certificate{ Certificate: certificate.Certificate, PrivateKey: certificate.PrivateKey, OCSPStaple: certificate.OCSPStaple, SignedCertificateTimestamps: certificate.SignedCertificateTimestamps, Leaf: certificate.Leaf, }) } } tlsConn := tls.UClient(conn, utlsConf, tls.HelloChrome_Auto) if err := tlsConn.HandshakeContext(ctx); err != nil { conn.Close() return nil, err } return tlsConn, nil }