github.com/sagernet/sing-box@v1.2.7/common/tls/std_client.go (about) 1 package tls 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "net" 7 "net/netip" 8 "os" 9 10 "github.com/sagernet/sing-box/adapter" 11 "github.com/sagernet/sing-box/option" 12 E "github.com/sagernet/sing/common/exceptions" 13 ) 14 15 type STDClientConfig struct { 16 config *tls.Config 17 } 18 19 func (s *STDClientConfig) ServerName() string { 20 return s.config.ServerName 21 } 22 23 func (s *STDClientConfig) SetServerName(serverName string) { 24 s.config.ServerName = serverName 25 } 26 27 func (s *STDClientConfig) NextProtos() []string { 28 return s.config.NextProtos 29 } 30 31 func (s *STDClientConfig) SetNextProtos(nextProto []string) { 32 s.config.NextProtos = nextProto 33 } 34 35 func (s *STDClientConfig) Config() (*STDConfig, error) { 36 return s.config, nil 37 } 38 39 func (s *STDClientConfig) Client(conn net.Conn) (Conn, error) { 40 return tls.Client(conn, s.config), nil 41 } 42 43 func (s *STDClientConfig) Clone() Config { 44 return &STDClientConfig{s.config.Clone()} 45 } 46 47 func NewSTDClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) { 48 var serverName string 49 if options.ServerName != "" { 50 serverName = options.ServerName 51 } else if serverAddress != "" { 52 if _, err := netip.ParseAddr(serverName); err != nil { 53 serverName = serverAddress 54 } 55 } 56 if serverName == "" && !options.Insecure { 57 return nil, E.New("missing server_name or insecure=true") 58 } 59 60 var tlsConfig tls.Config 61 tlsConfig.Time = router.TimeFunc() 62 if options.DisableSNI { 63 tlsConfig.ServerName = "127.0.0.1" 64 } else { 65 tlsConfig.ServerName = serverName 66 } 67 if options.Insecure { 68 tlsConfig.InsecureSkipVerify = options.Insecure 69 } else if options.DisableSNI { 70 tlsConfig.InsecureSkipVerify = true 71 tlsConfig.VerifyConnection = func(state tls.ConnectionState) error { 72 verifyOptions := x509.VerifyOptions{ 73 DNSName: serverName, 74 Intermediates: x509.NewCertPool(), 75 } 76 for _, cert := range state.PeerCertificates[1:] { 77 verifyOptions.Intermediates.AddCert(cert) 78 } 79 _, err := state.PeerCertificates[0].Verify(verifyOptions) 80 return err 81 } 82 } 83 if len(options.ALPN) > 0 { 84 tlsConfig.NextProtos = options.ALPN 85 } 86 if options.MinVersion != "" { 87 minVersion, err := ParseTLSVersion(options.MinVersion) 88 if err != nil { 89 return nil, E.Cause(err, "parse min_version") 90 } 91 tlsConfig.MinVersion = minVersion 92 } 93 if options.MaxVersion != "" { 94 maxVersion, err := ParseTLSVersion(options.MaxVersion) 95 if err != nil { 96 return nil, E.Cause(err, "parse max_version") 97 } 98 tlsConfig.MaxVersion = maxVersion 99 } 100 if options.CipherSuites != nil { 101 find: 102 for _, cipherSuite := range options.CipherSuites { 103 for _, tlsCipherSuite := range tls.CipherSuites() { 104 if cipherSuite == tlsCipherSuite.Name { 105 tlsConfig.CipherSuites = append(tlsConfig.CipherSuites, tlsCipherSuite.ID) 106 continue find 107 } 108 } 109 return nil, E.New("unknown cipher_suite: ", cipherSuite) 110 } 111 } 112 var certificate []byte 113 if options.Certificate != "" { 114 certificate = []byte(options.Certificate) 115 } else if options.CertificatePath != "" { 116 content, err := os.ReadFile(options.CertificatePath) 117 if err != nil { 118 return nil, E.Cause(err, "read certificate") 119 } 120 certificate = content 121 } 122 if len(certificate) > 0 { 123 certPool := x509.NewCertPool() 124 if !certPool.AppendCertsFromPEM(certificate) { 125 return nil, E.New("failed to parse certificate:\n\n", certificate) 126 } 127 tlsConfig.RootCAs = certPool 128 } 129 return &STDClientConfig{&tlsConfig}, nil 130 }