tls.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package tlscfg
  2. import (
  3. "encoding/base64"
  4. "strings"
  5. "github.com/golang/protobuf/proto"
  6. "github.com/v2fly/v2ray-core/v4/common/platform/filesystem"
  7. "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon"
  8. "github.com/v2fly/v2ray-core/v4/transport/internet/tls"
  9. )
  10. //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
  11. type TLSConfig struct {
  12. Insecure bool `json:"allowInsecure"`
  13. Certs []*TLSCertConfig `json:"certificates"`
  14. ServerName string `json:"serverName"`
  15. ALPN *cfgcommon.StringList `json:"alpn"`
  16. EnableSessionResumption bool `json:"enableSessionResumption"`
  17. DisableSystemRoot bool `json:"disableSystemRoot"`
  18. PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
  19. VerifyClientCertificate bool `json:"verifyClientCertificate"`
  20. }
  21. // Build implements Buildable.
  22. func (c *TLSConfig) Build() (proto.Message, error) {
  23. config := new(tls.Config)
  24. config.Certificate = make([]*tls.Certificate, len(c.Certs))
  25. for idx, certConf := range c.Certs {
  26. cert, err := certConf.Build()
  27. if err != nil {
  28. return nil, err
  29. }
  30. config.Certificate[idx] = cert
  31. }
  32. serverName := c.ServerName
  33. config.AllowInsecure = c.Insecure
  34. config.VerifyClientCertificate = c.VerifyClientCertificate
  35. if len(c.ServerName) > 0 {
  36. config.ServerName = serverName
  37. }
  38. if c.ALPN != nil && len(*c.ALPN) > 0 {
  39. config.NextProtocol = []string(*c.ALPN)
  40. }
  41. config.EnableSessionResumption = c.EnableSessionResumption
  42. config.DisableSystemRoot = c.DisableSystemRoot
  43. if c.PinnedPeerCertificateChainSha256 != nil {
  44. config.PinnedPeerCertificateChainSha256 = [][]byte{}
  45. for _, v := range *c.PinnedPeerCertificateChainSha256 {
  46. hashValue, err := base64.StdEncoding.DecodeString(v)
  47. if err != nil {
  48. return nil, err
  49. }
  50. config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue)
  51. }
  52. }
  53. return config, nil
  54. }
  55. type TLSCertConfig struct {
  56. CertFile string `json:"certificateFile"`
  57. CertStr []string `json:"certificate"`
  58. KeyFile string `json:"keyFile"`
  59. KeyStr []string `json:"key"`
  60. Usage string `json:"usage"`
  61. }
  62. // Build implements Buildable.
  63. func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
  64. certificate := new(tls.Certificate)
  65. cert, err := readFileOrString(c.CertFile, c.CertStr)
  66. if err != nil {
  67. return nil, newError("failed to parse certificate").Base(err)
  68. }
  69. certificate.Certificate = cert
  70. if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
  71. key, err := readFileOrString(c.KeyFile, c.KeyStr)
  72. if err != nil {
  73. return nil, newError("failed to parse key").Base(err)
  74. }
  75. certificate.Key = key
  76. }
  77. switch strings.ToLower(c.Usage) {
  78. case "encipherment":
  79. certificate.Usage = tls.Certificate_ENCIPHERMENT
  80. case "verify":
  81. certificate.Usage = tls.Certificate_AUTHORITY_VERIFY
  82. case "verifyclient":
  83. certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT
  84. case "issue":
  85. certificate.Usage = tls.Certificate_AUTHORITY_ISSUE
  86. default:
  87. certificate.Usage = tls.Certificate_ENCIPHERMENT
  88. }
  89. return certificate, nil
  90. }
  91. func readFileOrString(f string, s []string) ([]byte, error) {
  92. if len(f) > 0 {
  93. return filesystem.ReadFile(f)
  94. }
  95. if len(s) > 0 {
  96. return []byte(strings.Join(s, "\n")), nil
  97. }
  98. return nil, newError("both file and bytes are empty.")
  99. }