github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/conf/transport_internet.go (about)

     1  package conf
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  
     7  	"github.com/golang/protobuf/proto"
     8  	"v2ray.com/core/common/platform/filesystem"
     9  	"v2ray.com/core/common/protocol"
    10  	"v2ray.com/core/common/serial"
    11  	"v2ray.com/core/transport/internet"
    12  	"v2ray.com/core/transport/internet/domainsocket"
    13  	"v2ray.com/core/transport/internet/http"
    14  	"v2ray.com/core/transport/internet/kcp"
    15  	"v2ray.com/core/transport/internet/quic"
    16  	"v2ray.com/core/transport/internet/tcp"
    17  	"v2ray.com/core/transport/internet/tls"
    18  	"v2ray.com/core/transport/internet/websocket"
    19  	"v2ray.com/core/transport/internet/xtls"
    20  )
    21  
    22  var (
    23  	kcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
    24  		"none":         func() interface{} { return new(NoOpAuthenticator) },
    25  		"srtp":         func() interface{} { return new(SRTPAuthenticator) },
    26  		"utp":          func() interface{} { return new(UTPAuthenticator) },
    27  		"wechat-video": func() interface{} { return new(WechatVideoAuthenticator) },
    28  		"dtls":         func() interface{} { return new(DTLSAuthenticator) },
    29  		"wireguard":    func() interface{} { return new(WireguardAuthenticator) },
    30  	}, "type", "")
    31  
    32  	tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
    33  		"none": func() interface{} { return new(NoOpConnectionAuthenticator) },
    34  		"http": func() interface{} { return new(HTTPAuthenticator) },
    35  	}, "type", "")
    36  )
    37  
    38  type KCPConfig struct {
    39  	Mtu             *uint32         `json:"mtu"`
    40  	Tti             *uint32         `json:"tti"`
    41  	UpCap           *uint32         `json:"uplinkCapacity"`
    42  	DownCap         *uint32         `json:"downlinkCapacity"`
    43  	Congestion      *bool           `json:"congestion"`
    44  	ReadBufferSize  *uint32         `json:"readBufferSize"`
    45  	WriteBufferSize *uint32         `json:"writeBufferSize"`
    46  	HeaderConfig    json.RawMessage `json:"header"`
    47  	Seed            *string         `json:"seed"`
    48  }
    49  
    50  // Build implements Buildable.
    51  func (c *KCPConfig) Build() (proto.Message, error) {
    52  	config := new(kcp.Config)
    53  
    54  	if c.Mtu != nil {
    55  		mtu := *c.Mtu
    56  		if mtu < 576 || mtu > 1460 {
    57  			return nil, newError("invalid mKCP MTU size: ", mtu).AtError()
    58  		}
    59  		config.Mtu = &kcp.MTU{Value: mtu}
    60  	}
    61  	if c.Tti != nil {
    62  		tti := *c.Tti
    63  		if tti < 10 || tti > 100 {
    64  			return nil, newError("invalid mKCP TTI: ", tti).AtError()
    65  		}
    66  		config.Tti = &kcp.TTI{Value: tti}
    67  	}
    68  	if c.UpCap != nil {
    69  		config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap}
    70  	}
    71  	if c.DownCap != nil {
    72  		config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap}
    73  	}
    74  	if c.Congestion != nil {
    75  		config.Congestion = *c.Congestion
    76  	}
    77  	if c.ReadBufferSize != nil {
    78  		size := *c.ReadBufferSize
    79  		if size > 0 {
    80  			config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024}
    81  		} else {
    82  			config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024}
    83  		}
    84  	}
    85  	if c.WriteBufferSize != nil {
    86  		size := *c.WriteBufferSize
    87  		if size > 0 {
    88  			config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024}
    89  		} else {
    90  			config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024}
    91  		}
    92  	}
    93  	if len(c.HeaderConfig) > 0 {
    94  		headerConfig, _, err := kcpHeaderLoader.Load(c.HeaderConfig)
    95  		if err != nil {
    96  			return nil, newError("invalid mKCP header config.").Base(err).AtError()
    97  		}
    98  		ts, err := headerConfig.(Buildable).Build()
    99  		if err != nil {
   100  			return nil, newError("invalid mKCP header config").Base(err).AtError()
   101  		}
   102  		config.HeaderConfig = serial.ToTypedMessage(ts)
   103  	}
   104  
   105  	if c.Seed != nil {
   106  		config.Seed = &kcp.EncryptionSeed{Seed: *c.Seed}
   107  	}
   108  
   109  	return config, nil
   110  }
   111  
   112  type TCPConfig struct {
   113  	HeaderConfig        json.RawMessage `json:"header"`
   114  	AcceptProxyProtocol bool            `json:"acceptProxyProtocol"`
   115  }
   116  
   117  // Build implements Buildable.
   118  func (c *TCPConfig) Build() (proto.Message, error) {
   119  	config := new(tcp.Config)
   120  	if len(c.HeaderConfig) > 0 {
   121  		headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)
   122  		if err != nil {
   123  			return nil, newError("invalid TCP header config").Base(err).AtError()
   124  		}
   125  		ts, err := headerConfig.(Buildable).Build()
   126  		if err != nil {
   127  			return nil, newError("invalid TCP header config").Base(err).AtError()
   128  		}
   129  		config.HeaderSettings = serial.ToTypedMessage(ts)
   130  	}
   131  	if c.AcceptProxyProtocol {
   132  		config.AcceptProxyProtocol = c.AcceptProxyProtocol
   133  	}
   134  	return config, nil
   135  }
   136  
   137  type WebSocketConfig struct {
   138  	Path                string            `json:"path"`
   139  	Path2               string            `json:"Path"` // The key was misspelled. For backward compatibility, we have to keep track the old key.
   140  	Headers             map[string]string `json:"headers"`
   141  	AcceptProxyProtocol bool              `json:"acceptProxyProtocol"`
   142  }
   143  
   144  // Build implements Buildable.
   145  func (c *WebSocketConfig) Build() (proto.Message, error) {
   146  	path := c.Path
   147  	if path == "" && c.Path2 != "" {
   148  		path = c.Path2
   149  	}
   150  	header := make([]*websocket.Header, 0, 32)
   151  	for key, value := range c.Headers {
   152  		header = append(header, &websocket.Header{
   153  			Key:   key,
   154  			Value: value,
   155  		})
   156  	}
   157  	config := &websocket.Config{
   158  		Path:   path,
   159  		Header: header,
   160  	}
   161  	if c.AcceptProxyProtocol {
   162  		config.AcceptProxyProtocol = c.AcceptProxyProtocol
   163  	}
   164  	return config, nil
   165  }
   166  
   167  type HTTPConfig struct {
   168  	Host *StringList `json:"host"`
   169  	Path string      `json:"path"`
   170  }
   171  
   172  // Build implements Buildable.
   173  func (c *HTTPConfig) Build() (proto.Message, error) {
   174  	config := &http.Config{
   175  		Path: c.Path,
   176  	}
   177  	if c.Host != nil {
   178  		config.Host = []string(*c.Host)
   179  	}
   180  	return config, nil
   181  }
   182  
   183  type QUICConfig struct {
   184  	Header   json.RawMessage `json:"header"`
   185  	Security string          `json:"security"`
   186  	Key      string          `json:"key"`
   187  }
   188  
   189  // Build implements Buildable.
   190  func (c *QUICConfig) Build() (proto.Message, error) {
   191  	config := &quic.Config{
   192  		Key: c.Key,
   193  	}
   194  
   195  	if len(c.Header) > 0 {
   196  		headerConfig, _, err := kcpHeaderLoader.Load(c.Header)
   197  		if err != nil {
   198  			return nil, newError("invalid QUIC header config.").Base(err).AtError()
   199  		}
   200  		ts, err := headerConfig.(Buildable).Build()
   201  		if err != nil {
   202  			return nil, newError("invalid QUIC header config").Base(err).AtError()
   203  		}
   204  		config.Header = serial.ToTypedMessage(ts)
   205  	}
   206  
   207  	var st protocol.SecurityType
   208  	switch strings.ToLower(c.Security) {
   209  	case "aes-128-gcm":
   210  		st = protocol.SecurityType_AES128_GCM
   211  	case "chacha20-poly1305":
   212  		st = protocol.SecurityType_CHACHA20_POLY1305
   213  	default:
   214  		st = protocol.SecurityType_NONE
   215  	}
   216  
   217  	config.Security = &protocol.SecurityConfig{
   218  		Type: st,
   219  	}
   220  
   221  	return config, nil
   222  }
   223  
   224  type DomainSocketConfig struct {
   225  	Path                string `json:"path"`
   226  	Abstract            bool   `json:"abstract"`
   227  	Padding             bool   `json:"padding"`
   228  	AcceptProxyProtocol bool   `json:"acceptProxyProtocol"`
   229  }
   230  
   231  // Build implements Buildable.
   232  func (c *DomainSocketConfig) Build() (proto.Message, error) {
   233  	return &domainsocket.Config{
   234  		Path:                c.Path,
   235  		Abstract:            c.Abstract,
   236  		Padding:             c.Padding,
   237  		AcceptProxyProtocol: c.AcceptProxyProtocol,
   238  	}, nil
   239  }
   240  
   241  func readFileOrString(f string, s []string) ([]byte, error) {
   242  	if len(f) > 0 {
   243  		return filesystem.ReadFile(f)
   244  	}
   245  	if len(s) > 0 {
   246  		return []byte(strings.Join(s, "\n")), nil
   247  	}
   248  	return nil, newError("both file and bytes are empty.")
   249  }
   250  
   251  type TLSCertConfig struct {
   252  	CertFile string   `json:"certificateFile"`
   253  	CertStr  []string `json:"certificate"`
   254  	KeyFile  string   `json:"keyFile"`
   255  	KeyStr   []string `json:"key"`
   256  	Usage    string   `json:"usage"`
   257  }
   258  
   259  // Build implements Buildable.
   260  func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
   261  	certificate := new(tls.Certificate)
   262  
   263  	cert, err := readFileOrString(c.CertFile, c.CertStr)
   264  	if err != nil {
   265  		return nil, newError("failed to parse certificate").Base(err)
   266  	}
   267  	certificate.Certificate = cert
   268  
   269  	if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
   270  		key, err := readFileOrString(c.KeyFile, c.KeyStr)
   271  		if err != nil {
   272  			return nil, newError("failed to parse key").Base(err)
   273  		}
   274  		certificate.Key = key
   275  	}
   276  
   277  	switch strings.ToLower(c.Usage) {
   278  	case "encipherment":
   279  		certificate.Usage = tls.Certificate_ENCIPHERMENT
   280  	case "verify":
   281  		certificate.Usage = tls.Certificate_AUTHORITY_VERIFY
   282  	case "issue":
   283  		certificate.Usage = tls.Certificate_AUTHORITY_ISSUE
   284  	default:
   285  		certificate.Usage = tls.Certificate_ENCIPHERMENT
   286  	}
   287  
   288  	return certificate, nil
   289  }
   290  
   291  type TLSConfig struct {
   292  	Insecure                 bool             `json:"allowInsecure"`
   293  	InsecureCiphers          bool             `json:"allowInsecureCiphers"`
   294  	Certs                    []*TLSCertConfig `json:"certificates"`
   295  	ServerName               string           `json:"serverName"`
   296  	ALPN                     *StringList      `json:"alpn"`
   297  	DisableSessionResumption bool             `json:"disableSessionResumption"`
   298  	DisableSystemRoot        bool             `json:"disableSystemRoot"`
   299  }
   300  
   301  // Build implements Buildable.
   302  func (c *TLSConfig) Build() (proto.Message, error) {
   303  	config := new(tls.Config)
   304  	config.Certificate = make([]*tls.Certificate, len(c.Certs))
   305  	for idx, certConf := range c.Certs {
   306  		cert, err := certConf.Build()
   307  		if err != nil {
   308  			return nil, err
   309  		}
   310  		config.Certificate[idx] = cert
   311  	}
   312  	serverName := c.ServerName
   313  	config.AllowInsecure = c.Insecure
   314  	config.AllowInsecureCiphers = c.InsecureCiphers
   315  	if len(c.ServerName) > 0 {
   316  		config.ServerName = serverName
   317  	}
   318  	if c.ALPN != nil && len(*c.ALPN) > 0 {
   319  		config.NextProtocol = []string(*c.ALPN)
   320  	}
   321  	config.DisableSessionResumption = c.DisableSessionResumption
   322  	config.DisableSystemRoot = c.DisableSystemRoot
   323  	return config, nil
   324  }
   325  
   326  type XTLSCertConfig struct {
   327  	CertFile string   `json:"certificateFile"`
   328  	CertStr  []string `json:"certificate"`
   329  	KeyFile  string   `json:"keyFile"`
   330  	KeyStr   []string `json:"key"`
   331  	Usage    string   `json:"usage"`
   332  }
   333  
   334  // Build implements Buildable.
   335  func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
   336  	certificate := new(xtls.Certificate)
   337  
   338  	cert, err := readFileOrString(c.CertFile, c.CertStr)
   339  	if err != nil {
   340  		return nil, newError("failed to parse certificate").Base(err)
   341  	}
   342  	certificate.Certificate = cert
   343  
   344  	if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
   345  		key, err := readFileOrString(c.KeyFile, c.KeyStr)
   346  		if err != nil {
   347  			return nil, newError("failed to parse key").Base(err)
   348  		}
   349  		certificate.Key = key
   350  	}
   351  
   352  	switch strings.ToLower(c.Usage) {
   353  	case "encipherment":
   354  		certificate.Usage = xtls.Certificate_ENCIPHERMENT
   355  	case "verify":
   356  		certificate.Usage = xtls.Certificate_AUTHORITY_VERIFY
   357  	case "issue":
   358  		certificate.Usage = xtls.Certificate_AUTHORITY_ISSUE
   359  	default:
   360  		certificate.Usage = xtls.Certificate_ENCIPHERMENT
   361  	}
   362  
   363  	return certificate, nil
   364  }
   365  
   366  type XTLSConfig struct {
   367  	Insecure                 bool              `json:"allowInsecure"`
   368  	InsecureCiphers          bool              `json:"allowInsecureCiphers"`
   369  	Certs                    []*XTLSCertConfig `json:"certificates"`
   370  	ServerName               string            `json:"serverName"`
   371  	ALPN                     *StringList       `json:"alpn"`
   372  	DisableSessionResumption bool              `json:"disableSessionResumption"`
   373  	DisableSystemRoot        bool              `json:"disableSystemRoot"`
   374  }
   375  
   376  // Build implements Buildable.
   377  func (c *XTLSConfig) Build() (proto.Message, error) {
   378  	config := new(xtls.Config)
   379  	config.Certificate = make([]*xtls.Certificate, len(c.Certs))
   380  	for idx, certConf := range c.Certs {
   381  		cert, err := certConf.Build()
   382  		if err != nil {
   383  			return nil, err
   384  		}
   385  		config.Certificate[idx] = cert
   386  	}
   387  	serverName := c.ServerName
   388  	config.AllowInsecure = c.Insecure
   389  	config.AllowInsecureCiphers = c.InsecureCiphers
   390  	if len(c.ServerName) > 0 {
   391  		config.ServerName = serverName
   392  	}
   393  	if c.ALPN != nil && len(*c.ALPN) > 0 {
   394  		config.NextProtocol = []string(*c.ALPN)
   395  	}
   396  	config.DisableSessionResumption = c.DisableSessionResumption
   397  	config.DisableSystemRoot = c.DisableSystemRoot
   398  	return config, nil
   399  }
   400  
   401  type TransportProtocol string
   402  
   403  // Build implements Buildable.
   404  func (p TransportProtocol) Build() (string, error) {
   405  	switch strings.ToLower(string(p)) {
   406  	case "tcp":
   407  		return "tcp", nil
   408  	case "kcp", "mkcp":
   409  		return "mkcp", nil
   410  	case "ws", "websocket":
   411  		return "websocket", nil
   412  	case "h2", "http":
   413  		return "http", nil
   414  	case "ds", "domainsocket":
   415  		return "domainsocket", nil
   416  	case "quic":
   417  		return "quic", nil
   418  	default:
   419  		return "", newError("Config: unknown transport protocol: ", p)
   420  	}
   421  }
   422  
   423  type SocketConfig struct {
   424  	Mark   int32  `json:"mark"`
   425  	TFO    *bool  `json:"tcpFastOpen"`
   426  	TProxy string `json:"tproxy"`
   427  }
   428  
   429  // Build implements Buildable.
   430  func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
   431  	var tfoSettings internet.SocketConfig_TCPFastOpenState
   432  	if c.TFO != nil {
   433  		if *c.TFO {
   434  			tfoSettings = internet.SocketConfig_Enable
   435  		} else {
   436  			tfoSettings = internet.SocketConfig_Disable
   437  		}
   438  	}
   439  	var tproxy internet.SocketConfig_TProxyMode
   440  	switch strings.ToLower(c.TProxy) {
   441  	case "tproxy":
   442  		tproxy = internet.SocketConfig_TProxy
   443  	case "redirect":
   444  		tproxy = internet.SocketConfig_Redirect
   445  	default:
   446  		tproxy = internet.SocketConfig_Off
   447  	}
   448  
   449  	return &internet.SocketConfig{
   450  		Mark:   c.Mark,
   451  		Tfo:    tfoSettings,
   452  		Tproxy: tproxy,
   453  	}, nil
   454  }
   455  
   456  type StreamConfig struct {
   457  	Network        *TransportProtocol  `json:"network"`
   458  	Security       string              `json:"security"`
   459  	TLSSettings    *TLSConfig          `json:"tlsSettings"`
   460  	XTLSSettings   *XTLSConfig         `json:"xtlsSettings"`
   461  	TCPSettings    *TCPConfig          `json:"tcpSettings"`
   462  	KCPSettings    *KCPConfig          `json:"kcpSettings"`
   463  	WSSettings     *WebSocketConfig    `json:"wsSettings"`
   464  	HTTPSettings   *HTTPConfig         `json:"httpSettings"`
   465  	DSSettings     *DomainSocketConfig `json:"dsSettings"`
   466  	QUICSettings   *QUICConfig         `json:"quicSettings"`
   467  	SocketSettings *SocketConfig       `json:"sockopt"`
   468  }
   469  
   470  // Build implements Buildable.
   471  func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
   472  	config := &internet.StreamConfig{
   473  		ProtocolName: "tcp",
   474  	}
   475  	if c.Network != nil {
   476  		protocol, err := (*c.Network).Build()
   477  		if err != nil {
   478  			return nil, err
   479  		}
   480  		config.ProtocolName = protocol
   481  	}
   482  	if strings.EqualFold(c.Security, "tls") {
   483  		tlsSettings := c.TLSSettings
   484  		if tlsSettings == nil {
   485  			if c.XTLSSettings != nil {
   486  				return nil, newError(`TLS: Please use "tlsSettings" instead of "xtlsSettings".`)
   487  			}
   488  			tlsSettings = &TLSConfig{}
   489  		}
   490  		ts, err := tlsSettings.Build()
   491  		if err != nil {
   492  			return nil, newError("Failed to build TLS config.").Base(err)
   493  		}
   494  		tm := serial.ToTypedMessage(ts)
   495  		config.SecuritySettings = append(config.SecuritySettings, tm)
   496  		config.SecurityType = tm.Type
   497  	}
   498  	if strings.EqualFold(c.Security, "xtls") {
   499  		if config.ProtocolName != "tcp" && config.ProtocolName != "mkcp" && config.ProtocolName != "domainsocket" {
   500  			return nil, newError("XTLS only supports TCP, mKCP and DomainSocket for now.")
   501  		}
   502  		xtlsSettings := c.XTLSSettings
   503  		if xtlsSettings == nil {
   504  			if c.TLSSettings != nil {
   505  				return nil, newError(`XTLS: Please use "xtlsSettings" instead of "tlsSettings".`)
   506  			}
   507  			xtlsSettings = &XTLSConfig{}
   508  		}
   509  		ts, err := xtlsSettings.Build()
   510  		if err != nil {
   511  			return nil, newError("Failed to build XTLS config.").Base(err)
   512  		}
   513  		tm := serial.ToTypedMessage(ts)
   514  		config.SecuritySettings = append(config.SecuritySettings, tm)
   515  		config.SecurityType = tm.Type
   516  	}
   517  	if c.TCPSettings != nil {
   518  		ts, err := c.TCPSettings.Build()
   519  		if err != nil {
   520  			return nil, newError("Failed to build TCP config.").Base(err)
   521  		}
   522  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   523  			ProtocolName: "tcp",
   524  			Settings:     serial.ToTypedMessage(ts),
   525  		})
   526  	}
   527  	if c.KCPSettings != nil {
   528  		ts, err := c.KCPSettings.Build()
   529  		if err != nil {
   530  			return nil, newError("Failed to build mKCP config.").Base(err)
   531  		}
   532  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   533  			ProtocolName: "mkcp",
   534  			Settings:     serial.ToTypedMessage(ts),
   535  		})
   536  	}
   537  	if c.WSSettings != nil {
   538  		ts, err := c.WSSettings.Build()
   539  		if err != nil {
   540  			return nil, newError("Failed to build WebSocket config.").Base(err)
   541  		}
   542  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   543  			ProtocolName: "websocket",
   544  			Settings:     serial.ToTypedMessage(ts),
   545  		})
   546  	}
   547  	if c.HTTPSettings != nil {
   548  		ts, err := c.HTTPSettings.Build()
   549  		if err != nil {
   550  			return nil, newError("Failed to build HTTP config.").Base(err)
   551  		}
   552  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   553  			ProtocolName: "http",
   554  			Settings:     serial.ToTypedMessage(ts),
   555  		})
   556  	}
   557  	if c.DSSettings != nil {
   558  		ds, err := c.DSSettings.Build()
   559  		if err != nil {
   560  			return nil, newError("Failed to build DomainSocket config.").Base(err)
   561  		}
   562  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   563  			ProtocolName: "domainsocket",
   564  			Settings:     serial.ToTypedMessage(ds),
   565  		})
   566  	}
   567  	if c.QUICSettings != nil {
   568  		qs, err := c.QUICSettings.Build()
   569  		if err != nil {
   570  			return nil, newError("Failed to build QUIC config").Base(err)
   571  		}
   572  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   573  			ProtocolName: "quic",
   574  			Settings:     serial.ToTypedMessage(qs),
   575  		})
   576  	}
   577  	if c.SocketSettings != nil {
   578  		ss, err := c.SocketSettings.Build()
   579  		if err != nil {
   580  			return nil, newError("Failed to build sockopt").Base(err)
   581  		}
   582  		config.SocketSettings = ss
   583  	}
   584  	return config, nil
   585  }
   586  
   587  type ProxyConfig struct {
   588  	Tag string `json:"tag"`
   589  }
   590  
   591  // Build implements Buildable.
   592  func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) {
   593  	if v.Tag == "" {
   594  		return nil, newError("Proxy tag is not set.")
   595  	}
   596  	return &internet.ProxyConfig{
   597  		Tag: v.Tag,
   598  	}, nil
   599  }