From 87322c335e952a13a04272a088587fae75761f5a Mon Sep 17 00:00:00 2001 From: arraykeys Date: Sat, 19 Jan 2019 18:54:42 +0800 Subject: [PATCH] a --- CHANGELOG | 2 ++ config.go | 1 + sdk/android-ios/sdk.go | 1 + services/sps/sps.go | 26 ++++++++++++++++++------ utils/functions.go | 45 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 68 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d79a617..0c5f576 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ proxy更新日志 + v6.9 1.修复了sps的start潜在的crash问题. +2.sps代理增加了--parent-tls-single参数用来支持单向tls上级。 v6.8 1.HTTP(S)\SOCKS5代理,API认证功能,发送给认证接口的参数增加了本地IP,local_ip字段, diff --git a/config.go b/config.go index 403d39e..7210fd0 100755 --- a/config.go +++ b/config.go @@ -303,6 +303,7 @@ func initConfig() (err error) { spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool() spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String() spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String() + spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool() spsArgs.Debug = isDebug //########dns######### diff --git a/sdk/android-ios/sdk.go b/sdk/android-ios/sdk.go index 54cbb22..c1ac81f 100644 --- a/sdk/android-ios/sdk.go +++ b/sdk/android-ios/sdk.go @@ -326,6 +326,7 @@ func StartWithLog(serviceID, serviceArgsStr string, loggerCallback LogCallback) spsArgs.LoadBalanceOnlyHA = sps.Flag("lb-onlyha", "use only `high availability mode` to choose parent for LB").Default("false").Bool() spsArgs.RateLimit = sps.Flag("rate-limit", "rate limit (bytes/second) of each connection, such as: 100K 1.5M . 0 means no limitation").Short('l').Default("0").String() spsArgs.Jumper = sps.Flag("jumper", "https or socks5 proxies used when connecting to parent, only worked of -T is tls or tcp, format is https://username:password@host:port https://host:port or socks5://username:password@host:port socks5://host:port").Default("").String() + spsArgs.ParentTLSSingle = sps.Flag("parent-tls-single", "conntect to parent insecure skip verify").Default("false").Bool() spsArgs.Debug = debug //########dns######### diff --git a/services/sps/sps.go b/services/sps/sps.go index b5c68d0..6547f1f 100644 --- a/services/sps/sps.go +++ b/services/sps/sps.go @@ -71,6 +71,7 @@ type SPSArgs struct { LoadBalanceRetryTime *int LoadBalanceHashTarget *bool LoadBalanceOnlyHA *bool + ParentTLSSingle *bool RateLimit *string RateLimitBytes float64 @@ -121,9 +122,11 @@ func (s *SPS) CheckArgs() (err error) { return } if *s.cfg.ParentType == "tls" || *s.cfg.LocalType == "tls" { - s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) - if err != nil { - return + if !*s.cfg.ParentTLSSingle { + s.cfg.CertBytes, s.cfg.KeyBytes, err = utils.TlsBytes(*s.cfg.CertFile, *s.cfg.KeyFile) + if err != nil { + return + } } if *s.cfg.CaCertFile != "" { s.cfg.CaCertBytes, err = ioutil.ReadFile(*s.cfg.CaCertFile) @@ -657,12 +660,21 @@ func (s *SPS) GetParentConn(address string) (conn net.Conn, err error) { if *s.cfg.ParentType == "tls" { if s.jumper == nil { var _conn tls.Conn - _conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes) + if *s.cfg.ParentTLSSingle { + _conn, err = utils.SingleTlsConnectHost(address, *s.cfg.Timeout, s.cfg.CaCertBytes) + } else { + _conn, err = utils.TlsConnectHost(address, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes) + } if err == nil { conn = net.Conn(&_conn) } } else { - conf, err := utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes) + var conf *tls.Config + if *s.cfg.ParentTLSSingle { + conf, err = utils.SingleTlsConfig(s.cfg.CaCertBytes) + } else { + conf, err = utils.TlsConfig(s.cfg.CertBytes, s.cfg.KeyBytes, s.cfg.CaCertBytes) + } if err != nil { return nil, err } @@ -720,7 +732,9 @@ func (s *SPS) ParentUDPKey() (key []byte) { return []byte(v)[:24] } case "tls": - return s.cfg.KeyBytes[:24] + if s.cfg.KeyBytes != nil { + return s.cfg.KeyBytes[:24] + } case "kcp": v := fmt.Sprintf("%x", md5.Sum([]byte(*s.cfg.KCP.Key))) return []byte(v)[:24] diff --git a/utils/functions.go b/utils/functions.go index 58ba7da..8afbd2a 100755 --- a/utils/functions.go +++ b/utils/functions.go @@ -122,12 +122,55 @@ func ioCopy(dst io.ReadWriter, src io.ReadWriter) (err error) { } } } +func SingleTlsConnectHost(host string, timeout int, caCertBytes []byte) (conn tls.Conn, err error) { + h := strings.Split(host, ":") + port, _ := strconv.Atoi(h[1]) + return SingleTlsConnect(h[0], port, timeout, caCertBytes) +} +func SingleTlsConnect(host string, port, timeout int, caCertBytes []byte) (conn tls.Conn, err error) { + conf, err := getRequestSingleTlsConfig(caCertBytes) + if err != nil { + return + } + _conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond) + if err != nil { + return + } + return *tls.Client(_conn, conf), err +} +func SingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) { + return getRequestSingleTlsConfig(caCertBytes) +} +func getRequestSingleTlsConfig(caCertBytes []byte) (conf *tls.Config, err error) { + conf = &tls.Config{InsecureSkipVerify: true} + serverCertPool := x509.NewCertPool() + if caCertBytes != nil { + ok := serverCertPool.AppendCertsFromPEM(caCertBytes) + if !ok { + err = errors.New("failed to parse root certificate") + } + conf.RootCAs = serverCertPool + conf.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + opts := x509.VerifyOptions{ + Roots: serverCertPool, + } + for _, rawCert := range rawCerts { + cert, _ := x509.ParseCertificate(rawCert) + _, err := cert.Verify(opts) + if err != nil { + return err + } + } + return nil + } + } + return +} func TlsConnectHost(host string, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) { h := strings.Split(host, ":") port, _ := strconv.Atoi(h[1]) return TlsConnect(h[0], port, timeout, certBytes, keyBytes, caCertBytes) } - func TlsConnect(host string, port, timeout int, certBytes, keyBytes, caCertBytes []byte) (conn tls.Conn, err error) { conf, err := getRequestTlsConfig(certBytes, keyBytes, caCertBytes) if err != nil {