diff --git a/proxy/base.go b/proxy/base.go index 5d05d12..787d2a9 100644 --- a/proxy/base.go +++ b/proxy/base.go @@ -375,14 +375,15 @@ func (b *Base) InitAdvLayer() { KeyFile: dc.TLSKey, } } - minVer := tlsLayer.GetMinVerFromExtra(dc.Extra) tConf = tlsLayer.GetTlsConfig(false, tlsLayer.Conf{ - Insecure: dc.Insecure, - AlpnList: dc.Alpn, - Host: dc.Host, - CertConf: certConf, - Minver: minVer, + Insecure: dc.Insecure, + AlpnList: dc.Alpn, + Host: dc.Host, + CertConf: certConf, + Minver: getTlsMinVerFromExtra(dc.Extra), + Maxver: getTlsMaxVerFromExtra(dc.Extra), + CipherSuites: getTlsCipherSuitesFromExtra(dc.Extra), }) } @@ -434,8 +435,6 @@ func (b *Base) InitAdvLayer() { if creator.IsSuper() { - minVer := tlsLayer.GetMinVerFromExtra(lc.Extra) - aConf.TlsConf = tlsLayer.GetTlsConfig(true, tlsLayer.Conf{ Insecure: lc.Insecure, AlpnList: lc.Alpn, @@ -443,7 +442,9 @@ func (b *Base) InitAdvLayer() { CertConf: &tlsLayer.CertConf{ CertFile: lc.TLSCert, KeyFile: lc.TLSKey, CA: lc.CA, }, - Minver: minVer, + Minver: getTlsMinVerFromExtra(lc.Extra), + Maxver: getTlsMaxVerFromExtra(lc.Extra), + CipherSuites: getTlsCipherSuitesFromExtra(lc.Extra), }) } diff --git a/proxy/tlsConfig.go b/proxy/tlsConfig.go index dd4e2a0..6372081 100644 --- a/proxy/tlsConfig.go +++ b/proxy/tlsConfig.go @@ -1,8 +1,11 @@ package proxy import ( + "crypto/tls" + "github.com/e1732a364fed/v2ray_simple/advLayer" "github.com/e1732a364fed/v2ray_simple/tlsLayer" + "github.com/e1732a364fed/v2ray_simple/utils" ) func updateAlpnListByAdvLayer(com BaseInterface, alpnList []string) (result []string) { @@ -59,15 +62,16 @@ func prepareTLS_forClient(com BaseInterface, dc *DialConf) error { KeyFile: dc.TLSKey, } } - var minVer uint16 = tlsLayer.GetMinVerFromExtra(dc.Extra) clic.Tls_c = tlsLayer.NewClient(tlsLayer.Conf{ - Host: dc.Host, - Insecure: dc.Insecure, - Use_uTls: dc.Utls, - AlpnList: alpnList, - CertConf: certConf, - Minver: minVer, + Host: dc.Host, + Insecure: dc.Insecure, + Use_uTls: dc.Utls, + AlpnList: alpnList, + CertConf: certConf, + Minver: getTlsMinVerFromExtra(dc.Extra), + Maxver: getTlsMaxVerFromExtra(dc.Extra), + CipherSuites: getTlsCipherSuitesFromExtra(dc.Extra), }) return nil } @@ -87,10 +91,13 @@ func prepareTLS_forServer(com BaseInterface, lc *ListenConf) error { CertConf: &tlsLayer.CertConf{ CertFile: lc.TLSCert, KeyFile: lc.TLSKey, CA: lc.CA, }, - Insecure: lc.Insecure, - AlpnList: alpnList, - Minver: tlsLayer.GetMinVerFromExtra(lc.Extra), - RejectUnknownSni: tlsLayer.GetRejectUnknownSniFromExtra(lc.Extra), + Insecure: lc.Insecure, + AlpnList: alpnList, + Minver: getTlsMinVerFromExtra(lc.Extra), + Maxver: getTlsMaxVerFromExtra(lc.Extra), + + RejectUnknownSni: getTlsRejectUnknownSniFromExtra(lc.Extra), + CipherSuites: getTlsCipherSuitesFromExtra(lc.Extra), }) if err == nil { @@ -100,3 +107,69 @@ func prepareTLS_forServer(com BaseInterface, lc *ListenConf) error { } return nil } + +func getTlsMinVerFromExtra(extra map[string]any) uint16 { + if len(extra) > 0 { + if thing := extra["tls_minVersion"]; thing != nil { + if str, ok := (thing).(string); ok && len(str) > 0 { + switch str { + case "1.2": + return tls.VersionTLS12 + } + } + } + } + + return tls.VersionTLS13 +} + +func getTlsMaxVerFromExtra(extra map[string]any) uint16 { + if len(extra) > 0 { + if thing := extra["tls_maxVersion"]; thing != nil { + if str, ok := (thing).(string); ok && len(str) > 0 { + switch str { + case "1.2": + return tls.VersionTLS12 + } + } + } + } + + return tls.VersionTLS13 +} + +func getTlsRejectUnknownSniFromExtra(extra map[string]any) bool { + if len(extra) > 0 { + if thing := extra["tls_rejectUnknownSni"]; thing != nil { + if is, ok := utils.AnyToBool(thing); ok && is { + return true + } + } + } + + return false +} + +func getTlsCipherSuitesFromExtra(extra map[string]any) []uint16 { + if len(extra) > 0 { + if thing := extra["tls_cipherSuites"]; thing != nil { + if is, ok := utils.AnyToUInt16Array(thing); ok && len(is) > 0 { + return is + } + if strs, ok := thing.([]string); ok { + var v []uint16 + for _, s := range strs { + cs := tlsLayer.StrToCipherSuite(s) + if cs > 0 { + v = append(v, cs) + } + } + if len(v) > 0 { + return v + } + } + } + } + + return nil +} diff --git a/tlsLayer/cert.go b/tlsLayer/cert.go index 84f45dc..5e242a7 100644 --- a/tlsLayer/cert.go +++ b/tlsLayer/cert.go @@ -2,7 +2,6 @@ package tlsLayer import ( "errors" - "io/ioutil" mathrand "math/rand" "crypto/ecdsa" @@ -34,7 +33,7 @@ func LoadCA(caFile string) (cp *x509.CertPool, err error) { return } cp = x509.NewCertPool() - data, err := ioutil.ReadFile(caFile) + data, err := os.ReadFile(caFile) if err != nil { return nil, err } @@ -44,7 +43,7 @@ func LoadCA(caFile string) (cp *x509.CertPool, err error) { return } -//使用 ecc p256 方式生成证书 +// 使用 ecc p256 方式生成证书 func GenerateRandomeCert_Key() (certPEM []byte, keyPEM []byte) { //可参考 https://blog.ideawand.com/2017/11/22/build-certificate-that-support-Subject-Alternative-Name-SAN/ @@ -143,7 +142,7 @@ func GenerateRandomCertKeyFiles(cfn, kfn string) error { return nil } -//若 certFile, keyFile 有一项没给出,则会自动生成随机证书 +// 若 certFile, keyFile 有一项没给出,则会自动生成随机证书 func GetCertArrayFromFile(certFile, keyFile string) (certArray []tls.Certificate, err error) { if certFile != "" && keyFile != "" { cert, err := tls.LoadX509KeyPair(utils.GetFilePath(certFile), utils.GetFilePath(keyFile)) diff --git a/tlsLayer/tlsLayer.go b/tlsLayer/tlsLayer.go index aea4575..5bfd15e 100644 --- a/tlsLayer/tlsLayer.go +++ b/tlsLayer/tlsLayer.go @@ -19,38 +19,13 @@ type Conf struct { Host string Insecure bool Minver uint16 + Maxver uint16 AlpnList []string CertConf *CertConf Use_uTls bool //only client RejectUnknownSni bool //only server -} - -func GetMinVerFromExtra(extra map[string]any) uint16 { - if len(extra) > 0 { - if thing := extra["tls_minVersion"]; thing != nil { - if str, ok := (thing).(string); ok && len(str) > 0 { - switch str { - case "1.2": - return tls.VersionTLS12 - } - } - } - } - - return tls.VersionTLS13 -} - -func GetRejectUnknownSniFromExtra(extra map[string]any) bool { - if len(extra) > 0 { - if thing := extra["rejectUnknownSni"]; thing != nil { - if is, ok := utils.AnyToBool(thing); ok && is { - return true - } - } - } - - return false + CipherSuites []uint16 } func rejectUnknownGetCertificateFunc(certs []*tls.Certificate) func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { @@ -110,6 +85,8 @@ func GetTlsConfig(mustHasCert bool, conf Conf) *tls.Config { ServerName: conf.Host, Certificates: certArray, MinVersion: conf.Minver, + MaxVersion: conf.Maxver, + CipherSuites: conf.CipherSuites, } if conf.CertConf != nil && conf.CertConf.CA != "" { certPool, err := LoadCA(conf.CertConf.CA) @@ -156,6 +133,8 @@ func GetUTlsConfig(conf Conf) utls.Config { ServerName: conf.Host, Certificates: certArray, MinVersion: conf.Minver, + MaxVersion: conf.Maxver, + CipherSuites: conf.CipherSuites, } if conf.CertConf != nil && conf.CertConf.CA != "" { certPool, err := LoadCA(conf.CertConf.CA) diff --git a/tlsLayer/utils.go b/tlsLayer/utils.go new file mode 100644 index 0000000..397157d --- /dev/null +++ b/tlsLayer/utils.go @@ -0,0 +1,69 @@ +package tlsLayer + +import ( + "crypto/tls" + "strings" +) + +// 0 means illegal string +func StrToCipherSuite(str string) uint16 { + str = strings.ToUpper(str) + + //tls1.2 + switch str { + case "TLS_RSA_WITH_RC4_128_SHA": + return tls.TLS_RSA_WITH_RC4_128_SHA + case "TLS_RSA_WITH_3DES_EDE_CBC_SHA": + return tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA + case "TLS_RSA_WITH_AES_128_CBC_SHA": + return tls.TLS_RSA_WITH_AES_128_CBC_SHA + case "TLS_RSA_WITH_AES_256_CBC_SHA": + return tls.TLS_RSA_WITH_AES_256_CBC_SHA + case "TLS_RSA_WITH_AES_128_CBC_SHA256": + return tls.TLS_RSA_WITH_AES_128_CBC_SHA256 + case "TLS_RSA_WITH_AES_128_GCM_SHA256": + return tls.TLS_RSA_WITH_AES_128_GCM_SHA256 + case "TLS_RSA_WITH_AES_256_GCM_SHA384": + return tls.TLS_RSA_WITH_AES_256_GCM_SHA384 + case "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA": + return tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA": + return tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + case "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA": + return tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + case "TLS_ECDHE_RSA_WITH_RC4_128_SHA": + return tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA + case "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA": + return tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA": + return tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + case "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA": + return tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + case "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256": + return tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + case "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": + return tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + case "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256": + return tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + case "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256": + return tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + case "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384": + return tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + case "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384": + return tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + case "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": + return tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + case "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256": + return tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + + //tls1.3 + case "TLS_AES_128_GCM_SHA256": + return tls.TLS_AES_128_GCM_SHA256 + case "TLS_AES_256_GCM_SHA384": + return tls.TLS_AES_256_GCM_SHA384 + case "TLS_CHACHA20_POLY1305_SHA256": + return tls.TLS_CHACHA20_POLY1305_SHA256 + + } + return 0 +} diff --git a/utils/cast.go b/utils/cast.go index 67a14ff..699a2b4 100644 --- a/utils/cast.go +++ b/utils/cast.go @@ -136,3 +136,66 @@ func AnyToFloat64(a any) (float64, bool) { } return 0, false } + +func AnyToUInt16Array(a any) ([]uint16, bool) { + switch value := a.(type) { + + case []uint16: + return value, true + case []uint32: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []uint64: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []uint8: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []uint: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []int: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []int8: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []int16: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []int32: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + case []int64: + var vv []uint16 + for _, v := range value { + vv = append(vv, uint16(v)) + } + return vv, true + } + return nil, false +}