From df9624a9656deb39a7b8f129d4b8c9bcae1c7576 Mon Sep 17 00:00:00 2001 From: Shelikhoo Date: Sat, 4 Sep 2021 12:48:23 +0100 Subject: [PATCH] isolate tls settings --- .../conf/cfgcommon/tlscfg/errors.generated.go | 9 ++ infra/conf/cfgcommon/tlscfg/tls.go | 112 ++++++++++++++++++ infra/conf/v4/transport_internet.go | 108 +---------------- 3 files changed, 124 insertions(+), 105 deletions(-) create mode 100644 infra/conf/cfgcommon/tlscfg/errors.generated.go create mode 100644 infra/conf/cfgcommon/tlscfg/tls.go diff --git a/infra/conf/cfgcommon/tlscfg/errors.generated.go b/infra/conf/cfgcommon/tlscfg/errors.generated.go new file mode 100644 index 000000000..57791cb84 --- /dev/null +++ b/infra/conf/cfgcommon/tlscfg/errors.generated.go @@ -0,0 +1,9 @@ +package tlscfg + +import "github.com/v2fly/v2ray-core/v4/common/errors" + +type errPathObjHolder struct{} + +func newError(values ...interface{}) *errors.Error { + return errors.New(values...).WithPathObj(errPathObjHolder{}) +} diff --git a/infra/conf/cfgcommon/tlscfg/tls.go b/infra/conf/cfgcommon/tlscfg/tls.go new file mode 100644 index 000000000..1280d7d1d --- /dev/null +++ b/infra/conf/cfgcommon/tlscfg/tls.go @@ -0,0 +1,112 @@ +package tlscfg + +import ( + "encoding/base64" + "github.com/golang/protobuf/proto" + "github.com/v2fly/v2ray-core/v4/common/platform/filesystem" + "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon" + "github.com/v2fly/v2ray-core/v4/transport/internet/tls" + "strings" +) + +//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen + +type TLSConfig struct { + Insecure bool `json:"allowInsecure"` + Certs []*TLSCertConfig `json:"certificates"` + ServerName string `json:"serverName"` + ALPN *cfgcommon.StringList `json:"alpn"` + EnableSessionResumption bool `json:"enableSessionResumption"` + DisableSystemRoot bool `json:"disableSystemRoot"` + PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` + VerifyClientCertificate bool `json:"verifyClientCertificate"` +} + +// Build implements Buildable. +func (c *TLSConfig) Build() (proto.Message, error) { + config := new(tls.Config) + config.Certificate = make([]*tls.Certificate, len(c.Certs)) + for idx, certConf := range c.Certs { + cert, err := certConf.Build() + if err != nil { + return nil, err + } + config.Certificate[idx] = cert + } + serverName := c.ServerName + config.AllowInsecure = c.Insecure + config.VerifyClientCertificate = c.VerifyClientCertificate + if len(c.ServerName) > 0 { + config.ServerName = serverName + } + if c.ALPN != nil && len(*c.ALPN) > 0 { + config.NextProtocol = []string(*c.ALPN) + } + config.EnableSessionResumption = c.EnableSessionResumption + config.DisableSystemRoot = c.DisableSystemRoot + + if c.PinnedPeerCertificateChainSha256 != nil { + config.PinnedPeerCertificateChainSha256 = [][]byte{} + for _, v := range *c.PinnedPeerCertificateChainSha256 { + hashValue, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return nil, err + } + config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) + } + } + + return config, nil +} + +type TLSCertConfig struct { + CertFile string `json:"certificateFile"` + CertStr []string `json:"certificate"` + KeyFile string `json:"keyFile"` + KeyStr []string `json:"key"` + Usage string `json:"usage"` +} + +// Build implements Buildable. +func (c *TLSCertConfig) Build() (*tls.Certificate, error) { + certificate := new(tls.Certificate) + + cert, err := readFileOrString(c.CertFile, c.CertStr) + if err != nil { + return nil, newError("failed to parse certificate").Base(err) + } + certificate.Certificate = cert + + if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { + key, err := readFileOrString(c.KeyFile, c.KeyStr) + if err != nil { + return nil, newError("failed to parse key").Base(err) + } + certificate.Key = key + } + + switch strings.ToLower(c.Usage) { + case "encipherment": + certificate.Usage = tls.Certificate_ENCIPHERMENT + case "verify": + certificate.Usage = tls.Certificate_AUTHORITY_VERIFY + case "verifyclient": + certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT + case "issue": + certificate.Usage = tls.Certificate_AUTHORITY_ISSUE + default: + certificate.Usage = tls.Certificate_ENCIPHERMENT + } + + return certificate, nil +} + +func readFileOrString(f string, s []string) ([]byte, error) { + if len(f) > 0 { + return filesystem.ReadFile(f) + } + if len(s) > 0 { + return []byte(strings.Join(s, "\n")), nil + } + return nil, newError("both file and bytes are empty.") +} diff --git a/infra/conf/v4/transport_internet.go b/infra/conf/v4/transport_internet.go index 27644ab5c..b0224e123 100644 --- a/infra/conf/v4/transport_internet.go +++ b/infra/conf/v4/transport_internet.go @@ -1,14 +1,13 @@ package v4 import ( - "encoding/base64" "encoding/json" "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon/loader" + "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon/tlscfg" "strings" "github.com/golang/protobuf/proto" - "github.com/v2fly/v2ray-core/v4/common/platform/filesystem" "github.com/v2fly/v2ray-core/v4/common/protocol" "github.com/v2fly/v2ray-core/v4/common/serial" "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon" @@ -19,7 +18,6 @@ import ( "github.com/v2fly/v2ray-core/v4/transport/internet/kcp" "github.com/v2fly/v2ray-core/v4/transport/internet/quic" "github.com/v2fly/v2ray-core/v4/transport/internet/tcp" - "github.com/v2fly/v2ray-core/v4/transport/internet/tls" "github.com/v2fly/v2ray-core/v4/transport/internet/websocket" ) @@ -261,106 +259,6 @@ func (c *DomainSocketConfig) Build() (proto.Message, error) { }, nil } -func readFileOrString(f string, s []string) ([]byte, error) { - if len(f) > 0 { - return filesystem.ReadFile(f) - } - if len(s) > 0 { - return []byte(strings.Join(s, "\n")), nil - } - return nil, newError("both file and bytes are empty.") -} - -type TLSCertConfig struct { - CertFile string `json:"certificateFile"` - CertStr []string `json:"certificate"` - KeyFile string `json:"keyFile"` - KeyStr []string `json:"key"` - Usage string `json:"usage"` -} - -// Build implements Buildable. -func (c *TLSCertConfig) Build() (*tls.Certificate, error) { - certificate := new(tls.Certificate) - - cert, err := readFileOrString(c.CertFile, c.CertStr) - if err != nil { - return nil, newError("failed to parse certificate").Base(err) - } - certificate.Certificate = cert - - if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { - key, err := readFileOrString(c.KeyFile, c.KeyStr) - if err != nil { - return nil, newError("failed to parse key").Base(err) - } - certificate.Key = key - } - - switch strings.ToLower(c.Usage) { - case "encipherment": - certificate.Usage = tls.Certificate_ENCIPHERMENT - case "verify": - certificate.Usage = tls.Certificate_AUTHORITY_VERIFY - case "verifyclient": - certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT - case "issue": - certificate.Usage = tls.Certificate_AUTHORITY_ISSUE - default: - certificate.Usage = tls.Certificate_ENCIPHERMENT - } - - return certificate, nil -} - -type TLSConfig struct { - Insecure bool `json:"allowInsecure"` - Certs []*TLSCertConfig `json:"certificates"` - ServerName string `json:"serverName"` - ALPN *cfgcommon.StringList `json:"alpn"` - EnableSessionResumption bool `json:"enableSessionResumption"` - DisableSystemRoot bool `json:"disableSystemRoot"` - PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` - VerifyClientCertificate bool `json:"verifyClientCertificate"` -} - -// Build implements Buildable. -func (c *TLSConfig) Build() (proto.Message, error) { - config := new(tls.Config) - config.Certificate = make([]*tls.Certificate, len(c.Certs)) - for idx, certConf := range c.Certs { - cert, err := certConf.Build() - if err != nil { - return nil, err - } - config.Certificate[idx] = cert - } - serverName := c.ServerName - config.AllowInsecure = c.Insecure - config.VerifyClientCertificate = c.VerifyClientCertificate - if len(c.ServerName) > 0 { - config.ServerName = serverName - } - if c.ALPN != nil && len(*c.ALPN) > 0 { - config.NextProtocol = []string(*c.ALPN) - } - config.EnableSessionResumption = c.EnableSessionResumption - config.DisableSystemRoot = c.DisableSystemRoot - - if c.PinnedPeerCertificateChainSha256 != nil { - config.PinnedPeerCertificateChainSha256 = [][]byte{} - for _, v := range *c.PinnedPeerCertificateChainSha256 { - hashValue, err := base64.StdEncoding.DecodeString(v) - if err != nil { - return nil, err - } - config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) - } - } - - return config, nil -} - type TransportProtocol string // Build implements Buildable. @@ -425,7 +323,7 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { type StreamConfig struct { Network *TransportProtocol `json:"network"` Security string `json:"security"` - TLSSettings *TLSConfig `json:"tlsSettings"` + TLSSettings *tlscfg.TLSConfig `json:"tlsSettings"` TCPSettings *TCPConfig `json:"tcpSettings"` KCPSettings *KCPConfig `json:"kcpSettings"` WSSettings *WebSocketConfig `json:"wsSettings"` @@ -452,7 +350,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) { if strings.EqualFold(c.Security, "tls") { tlsSettings := c.TLSSettings if tlsSettings == nil { - tlsSettings = &TLSConfig{} + tlsSettings = &tlscfg.TLSConfig{} } ts, err := tlsSettings.Build() if err != nil {