github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/v4/transport_internet.go (about)

     1  package v4
     2  
     3  import (
     4  	"encoding/json"
     5  	"strings"
     6  
     7  	"github.com/golang/protobuf/proto"
     8  
     9  	"github.com/v2fly/v2ray-core/v5/common/protocol"
    10  	"github.com/v2fly/v2ray-core/v5/common/serial"
    11  	"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon"
    12  	"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/loader"
    13  	"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/socketcfg"
    14  	"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon/tlscfg"
    15  	"github.com/v2fly/v2ray-core/v5/transport/internet"
    16  	"github.com/v2fly/v2ray-core/v5/transport/internet/domainsocket"
    17  	httpheader "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
    18  	"github.com/v2fly/v2ray-core/v5/transport/internet/http"
    19  	"github.com/v2fly/v2ray-core/v5/transport/internet/kcp"
    20  	"github.com/v2fly/v2ray-core/v5/transport/internet/quic"
    21  	"github.com/v2fly/v2ray-core/v5/transport/internet/tcp"
    22  	"github.com/v2fly/v2ray-core/v5/transport/internet/websocket"
    23  )
    24  
    25  var (
    26  	kcpHeaderLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{
    27  		"none":         func() interface{} { return new(NoOpAuthenticator) },
    28  		"srtp":         func() interface{} { return new(SRTPAuthenticator) },
    29  		"utp":          func() interface{} { return new(UTPAuthenticator) },
    30  		"wechat-video": func() interface{} { return new(WechatVideoAuthenticator) },
    31  		"dtls":         func() interface{} { return new(DTLSAuthenticator) },
    32  		"wireguard":    func() interface{} { return new(WireguardAuthenticator) },
    33  	}, "type", "")
    34  
    35  	tcpHeaderLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{
    36  		"none": func() interface{} { return new(NoOpConnectionAuthenticator) },
    37  		"http": func() interface{} { return new(Authenticator) },
    38  	}, "type", "")
    39  )
    40  
    41  type KCPConfig struct {
    42  	Mtu             *uint32         `json:"mtu"`
    43  	Tti             *uint32         `json:"tti"`
    44  	UpCap           *uint32         `json:"uplinkCapacity"`
    45  	DownCap         *uint32         `json:"downlinkCapacity"`
    46  	Congestion      *bool           `json:"congestion"`
    47  	ReadBufferSize  *uint32         `json:"readBufferSize"`
    48  	WriteBufferSize *uint32         `json:"writeBufferSize"`
    49  	HeaderConfig    json.RawMessage `json:"header"`
    50  	Seed            *string         `json:"seed"`
    51  }
    52  
    53  // Build implements Buildable.
    54  func (c *KCPConfig) Build() (proto.Message, error) {
    55  	config := new(kcp.Config)
    56  
    57  	if c.Mtu != nil {
    58  		mtu := *c.Mtu
    59  		if mtu < 576 || mtu > 1460 {
    60  			return nil, newError("invalid mKCP MTU size: ", mtu).AtError()
    61  		}
    62  		config.Mtu = &kcp.MTU{Value: mtu}
    63  	}
    64  	if c.Tti != nil {
    65  		tti := *c.Tti
    66  		if tti < 10 || tti > 100 {
    67  			return nil, newError("invalid mKCP TTI: ", tti).AtError()
    68  		}
    69  		config.Tti = &kcp.TTI{Value: tti}
    70  	}
    71  	if c.UpCap != nil {
    72  		config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap}
    73  	}
    74  	if c.DownCap != nil {
    75  		config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap}
    76  	}
    77  	if c.Congestion != nil {
    78  		config.Congestion = *c.Congestion
    79  	}
    80  	if c.ReadBufferSize != nil {
    81  		size := *c.ReadBufferSize
    82  		if size > 0 {
    83  			config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024}
    84  		} else {
    85  			config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024}
    86  		}
    87  	}
    88  	if c.WriteBufferSize != nil {
    89  		size := *c.WriteBufferSize
    90  		if size > 0 {
    91  			config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024}
    92  		} else {
    93  			config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024}
    94  		}
    95  	}
    96  	if len(c.HeaderConfig) > 0 {
    97  		headerConfig, _, err := kcpHeaderLoader.Load(c.HeaderConfig)
    98  		if err != nil {
    99  			return nil, newError("invalid mKCP header config.").Base(err).AtError()
   100  		}
   101  		ts, err := headerConfig.(cfgcommon.Buildable).Build()
   102  		if err != nil {
   103  			return nil, newError("invalid mKCP header config").Base(err).AtError()
   104  		}
   105  		config.HeaderConfig = serial.ToTypedMessage(ts)
   106  	}
   107  
   108  	if c.Seed != nil {
   109  		config.Seed = &kcp.EncryptionSeed{Seed: *c.Seed}
   110  	}
   111  
   112  	return config, nil
   113  }
   114  
   115  type TCPConfig struct {
   116  	HeaderConfig        json.RawMessage `json:"header"`
   117  	AcceptProxyProtocol bool            `json:"acceptProxyProtocol"`
   118  }
   119  
   120  // Build implements Buildable.
   121  func (c *TCPConfig) Build() (proto.Message, error) {
   122  	config := new(tcp.Config)
   123  	if len(c.HeaderConfig) > 0 {
   124  		headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)
   125  		if err != nil {
   126  			return nil, newError("invalid TCP header config").Base(err).AtError()
   127  		}
   128  		ts, err := headerConfig.(cfgcommon.Buildable).Build()
   129  		if err != nil {
   130  			return nil, newError("invalid TCP header config").Base(err).AtError()
   131  		}
   132  		config.HeaderSettings = serial.ToTypedMessage(ts)
   133  	}
   134  	if c.AcceptProxyProtocol {
   135  		config.AcceptProxyProtocol = c.AcceptProxyProtocol
   136  	}
   137  	return config, nil
   138  }
   139  
   140  type WebSocketConfig struct {
   141  	Path                 string            `json:"path"`
   142  	Headers              map[string]string `json:"headers"`
   143  	AcceptProxyProtocol  bool              `json:"acceptProxyProtocol"`
   144  	MaxEarlyData         int32             `json:"maxEarlyData"`
   145  	UseBrowserForwarding bool              `json:"useBrowserForwarding"`
   146  	EarlyDataHeaderName  string            `json:"earlyDataHeaderName"`
   147  }
   148  
   149  // Build implements Buildable.
   150  func (c *WebSocketConfig) Build() (proto.Message, error) {
   151  	path := c.Path
   152  	header := make([]*websocket.Header, 0, 32)
   153  	for key, value := range c.Headers {
   154  		header = append(header, &websocket.Header{
   155  			Key:   key,
   156  			Value: value,
   157  		})
   158  	}
   159  	config := &websocket.Config{
   160  		Path:                 path,
   161  		Header:               header,
   162  		MaxEarlyData:         c.MaxEarlyData,
   163  		UseBrowserForwarding: c.UseBrowserForwarding,
   164  		EarlyDataHeaderName:  c.EarlyDataHeaderName,
   165  	}
   166  	if c.AcceptProxyProtocol {
   167  		config.AcceptProxyProtocol = c.AcceptProxyProtocol
   168  	}
   169  	return config, nil
   170  }
   171  
   172  type HTTPConfig struct {
   173  	Host    *cfgcommon.StringList            `json:"host"`
   174  	Path    string                           `json:"path"`
   175  	Method  string                           `json:"method"`
   176  	Headers map[string]*cfgcommon.StringList `json:"headers"`
   177  }
   178  
   179  // Build implements Buildable.
   180  func (c *HTTPConfig) Build() (proto.Message, error) {
   181  	config := &http.Config{
   182  		Path: c.Path,
   183  	}
   184  	if c.Host != nil {
   185  		config.Host = []string(*c.Host)
   186  	}
   187  	if c.Method != "" {
   188  		config.Method = c.Method
   189  	}
   190  	if len(c.Headers) > 0 {
   191  		config.Header = make([]*httpheader.Header, 0, len(c.Headers))
   192  		headerNames := sortMapKeys(c.Headers)
   193  		for _, key := range headerNames {
   194  			value := c.Headers[key]
   195  			if value == nil {
   196  				return nil, newError("empty HTTP header value: " + key).AtError()
   197  			}
   198  			config.Header = append(config.Header, &httpheader.Header{
   199  				Name:  key,
   200  				Value: append([]string(nil), (*value)...),
   201  			})
   202  		}
   203  	}
   204  	return config, nil
   205  }
   206  
   207  type QUICConfig struct {
   208  	Header   json.RawMessage `json:"header"`
   209  	Security string          `json:"security"`
   210  	Key      string          `json:"key"`
   211  }
   212  
   213  // Build implements Buildable.
   214  func (c *QUICConfig) Build() (proto.Message, error) {
   215  	config := &quic.Config{
   216  		Key: c.Key,
   217  	}
   218  
   219  	if len(c.Header) > 0 {
   220  		headerConfig, _, err := kcpHeaderLoader.Load(c.Header)
   221  		if err != nil {
   222  			return nil, newError("invalid QUIC header config.").Base(err).AtError()
   223  		}
   224  		ts, err := headerConfig.(cfgcommon.Buildable).Build()
   225  		if err != nil {
   226  			return nil, newError("invalid QUIC header config").Base(err).AtError()
   227  		}
   228  		config.Header = serial.ToTypedMessage(ts)
   229  	}
   230  
   231  	var st protocol.SecurityType
   232  	switch strings.ToLower(c.Security) {
   233  	case "aes-128-gcm":
   234  		st = protocol.SecurityType_AES128_GCM
   235  	case "chacha20-poly1305":
   236  		st = protocol.SecurityType_CHACHA20_POLY1305
   237  	default:
   238  		st = protocol.SecurityType_NONE
   239  	}
   240  
   241  	config.Security = &protocol.SecurityConfig{
   242  		Type: st,
   243  	}
   244  
   245  	return config, nil
   246  }
   247  
   248  type DomainSocketConfig struct {
   249  	Path     string `json:"path"`
   250  	Abstract bool   `json:"abstract"`
   251  	Padding  bool   `json:"padding"`
   252  }
   253  
   254  // Build implements Buildable.
   255  func (c *DomainSocketConfig) Build() (proto.Message, error) {
   256  	return &domainsocket.Config{
   257  		Path:     c.Path,
   258  		Abstract: c.Abstract,
   259  		Padding:  c.Padding,
   260  	}, nil
   261  }
   262  
   263  type TransportProtocol string
   264  
   265  // Build implements Buildable.
   266  func (p TransportProtocol) Build() (string, error) {
   267  	switch strings.ToLower(string(p)) {
   268  	case "tcp":
   269  		return "tcp", nil
   270  	case "kcp", "mkcp":
   271  		return "mkcp", nil
   272  	case "ws", "websocket":
   273  		return "websocket", nil
   274  	case "h2", "http":
   275  		return "http", nil
   276  	case "ds", "domainsocket":
   277  		return "domainsocket", nil
   278  	case "quic":
   279  		return "quic", nil
   280  	case "gun", "grpc":
   281  		return "gun", nil
   282  	default:
   283  		return "", newError("Config: unknown transport protocol: ", p)
   284  	}
   285  }
   286  
   287  type StreamConfig struct {
   288  	Network        *TransportProtocol      `json:"network"`
   289  	Security       string                  `json:"security"`
   290  	TLSSettings    *tlscfg.TLSConfig       `json:"tlsSettings"`
   291  	TCPSettings    *TCPConfig              `json:"tcpSettings"`
   292  	KCPSettings    *KCPConfig              `json:"kcpSettings"`
   293  	WSSettings     *WebSocketConfig        `json:"wsSettings"`
   294  	HTTPSettings   *HTTPConfig             `json:"httpSettings"`
   295  	DSSettings     *DomainSocketConfig     `json:"dsSettings"`
   296  	QUICSettings   *QUICConfig             `json:"quicSettings"`
   297  	GunSettings    *GunConfig              `json:"gunSettings"`
   298  	GRPCSettings   *GunConfig              `json:"grpcSettings"`
   299  	SocketSettings *socketcfg.SocketConfig `json:"sockopt"`
   300  }
   301  
   302  // Build implements Buildable.
   303  func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
   304  	config := &internet.StreamConfig{
   305  		ProtocolName: "tcp",
   306  	}
   307  	if c.Network != nil {
   308  		protocol, err := c.Network.Build()
   309  		if err != nil {
   310  			return nil, err
   311  		}
   312  		config.ProtocolName = protocol
   313  	}
   314  	if strings.EqualFold(c.Security, "tls") {
   315  		tlsSettings := c.TLSSettings
   316  		if tlsSettings == nil {
   317  			tlsSettings = &tlscfg.TLSConfig{}
   318  		}
   319  		ts, err := tlsSettings.Build()
   320  		if err != nil {
   321  			return nil, newError("Failed to build TLS config.").Base(err)
   322  		}
   323  		tm := serial.ToTypedMessage(ts)
   324  		config.SecuritySettings = append(config.SecuritySettings, tm)
   325  		config.SecurityType = serial.V2Type(tm)
   326  	}
   327  	if c.TCPSettings != nil {
   328  		ts, err := c.TCPSettings.Build()
   329  		if err != nil {
   330  			return nil, newError("Failed to build TCP config.").Base(err)
   331  		}
   332  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   333  			ProtocolName: "tcp",
   334  			Settings:     serial.ToTypedMessage(ts),
   335  		})
   336  	}
   337  	if c.KCPSettings != nil {
   338  		ts, err := c.KCPSettings.Build()
   339  		if err != nil {
   340  			return nil, newError("Failed to build mKCP config.").Base(err)
   341  		}
   342  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   343  			ProtocolName: "mkcp",
   344  			Settings:     serial.ToTypedMessage(ts),
   345  		})
   346  	}
   347  	if c.WSSettings != nil {
   348  		ts, err := c.WSSettings.Build()
   349  		if err != nil {
   350  			return nil, newError("Failed to build WebSocket config.").Base(err)
   351  		}
   352  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   353  			ProtocolName: "websocket",
   354  			Settings:     serial.ToTypedMessage(ts),
   355  		})
   356  	}
   357  	if c.HTTPSettings != nil {
   358  		ts, err := c.HTTPSettings.Build()
   359  		if err != nil {
   360  			return nil, newError("Failed to build HTTP config.").Base(err)
   361  		}
   362  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   363  			ProtocolName: "http",
   364  			Settings:     serial.ToTypedMessage(ts),
   365  		})
   366  	}
   367  	if c.DSSettings != nil {
   368  		ds, err := c.DSSettings.Build()
   369  		if err != nil {
   370  			return nil, newError("Failed to build DomainSocket config.").Base(err)
   371  		}
   372  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   373  			ProtocolName: "domainsocket",
   374  			Settings:     serial.ToTypedMessage(ds),
   375  		})
   376  	}
   377  	if c.QUICSettings != nil {
   378  		qs, err := c.QUICSettings.Build()
   379  		if err != nil {
   380  			return nil, newError("Failed to build QUIC config.").Base(err)
   381  		}
   382  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   383  			ProtocolName: "quic",
   384  			Settings:     serial.ToTypedMessage(qs),
   385  		})
   386  	}
   387  	if c.GunSettings == nil {
   388  		c.GunSettings = c.GRPCSettings
   389  	}
   390  	if c.GunSettings != nil {
   391  		gs, err := c.GunSettings.Build()
   392  		if err != nil {
   393  			return nil, newError("Failed to build Gun config.").Base(err)
   394  		}
   395  		config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
   396  			ProtocolName: "gun",
   397  			Settings:     serial.ToTypedMessage(gs),
   398  		})
   399  	}
   400  	if c.SocketSettings != nil {
   401  		ss, err := c.SocketSettings.Build()
   402  		if err != nil {
   403  			return nil, newError("Failed to build sockopt.").Base(err)
   404  		}
   405  		config.SocketSettings = ss
   406  	}
   407  	return config, nil
   408  }