github.com/v2fly/v2ray-core/v4@v4.45.2/infra/conf/transport_internet.go (about) 1 package conf 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "strings" 7 8 "github.com/golang/protobuf/proto" 9 10 "github.com/v2fly/v2ray-core/v4/common/platform/filesystem" 11 "github.com/v2fly/v2ray-core/v4/common/protocol" 12 "github.com/v2fly/v2ray-core/v4/common/serial" 13 "github.com/v2fly/v2ray-core/v4/infra/conf/cfgcommon" 14 "github.com/v2fly/v2ray-core/v4/transport/internet" 15 "github.com/v2fly/v2ray-core/v4/transport/internet/domainsocket" 16 httpheader "github.com/v2fly/v2ray-core/v4/transport/internet/headers/http" 17 "github.com/v2fly/v2ray-core/v4/transport/internet/http" 18 "github.com/v2fly/v2ray-core/v4/transport/internet/kcp" 19 "github.com/v2fly/v2ray-core/v4/transport/internet/quic" 20 "github.com/v2fly/v2ray-core/v4/transport/internet/tcp" 21 "github.com/v2fly/v2ray-core/v4/transport/internet/tls" 22 "github.com/v2fly/v2ray-core/v4/transport/internet/websocket" 23 ) 24 25 var ( 26 kcpHeaderLoader = NewJSONConfigLoader(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 = NewJSONConfigLoader(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.(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.(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.(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 func readFileOrString(f string, s []string) ([]byte, error) { 264 if len(f) > 0 { 265 return filesystem.ReadFile(f) 266 } 267 if len(s) > 0 { 268 return []byte(strings.Join(s, "\n")), nil 269 } 270 return nil, newError("both file and bytes are empty.") 271 } 272 273 type TLSCertConfig struct { 274 CertFile string `json:"certificateFile"` 275 CertStr []string `json:"certificate"` 276 KeyFile string `json:"keyFile"` 277 KeyStr []string `json:"key"` 278 Usage string `json:"usage"` 279 } 280 281 // Build implements Buildable. 282 func (c *TLSCertConfig) Build() (*tls.Certificate, error) { 283 certificate := new(tls.Certificate) 284 285 cert, err := readFileOrString(c.CertFile, c.CertStr) 286 if err != nil { 287 return nil, newError("failed to parse certificate").Base(err) 288 } 289 certificate.Certificate = cert 290 291 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 292 key, err := readFileOrString(c.KeyFile, c.KeyStr) 293 if err != nil { 294 return nil, newError("failed to parse key").Base(err) 295 } 296 certificate.Key = key 297 } 298 299 switch strings.ToLower(c.Usage) { 300 case "encipherment": 301 certificate.Usage = tls.Certificate_ENCIPHERMENT 302 case "verify": 303 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY 304 case "verifyclient": 305 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY_CLIENT 306 case "issue": 307 certificate.Usage = tls.Certificate_AUTHORITY_ISSUE 308 default: 309 certificate.Usage = tls.Certificate_ENCIPHERMENT 310 } 311 312 return certificate, nil 313 } 314 315 type TLSConfig struct { 316 Insecure bool `json:"allowInsecure"` 317 Certs []*TLSCertConfig `json:"certificates"` 318 ServerName string `json:"serverName"` 319 ALPN *cfgcommon.StringList `json:"alpn"` 320 EnableSessionResumption bool `json:"enableSessionResumption"` 321 DisableSystemRoot bool `json:"disableSystemRoot"` 322 PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` 323 VerifyClientCertificate bool `json:"verifyClientCertificate"` 324 } 325 326 // Build implements Buildable. 327 func (c *TLSConfig) Build() (proto.Message, error) { 328 config := new(tls.Config) 329 config.Certificate = make([]*tls.Certificate, len(c.Certs)) 330 for idx, certConf := range c.Certs { 331 cert, err := certConf.Build() 332 if err != nil { 333 return nil, err 334 } 335 config.Certificate[idx] = cert 336 } 337 serverName := c.ServerName 338 config.AllowInsecure = c.Insecure 339 config.VerifyClientCertificate = c.VerifyClientCertificate 340 if len(c.ServerName) > 0 { 341 config.ServerName = serverName 342 } 343 if c.ALPN != nil && len(*c.ALPN) > 0 { 344 config.NextProtocol = []string(*c.ALPN) 345 } 346 config.EnableSessionResumption = c.EnableSessionResumption 347 config.DisableSystemRoot = c.DisableSystemRoot 348 349 if c.PinnedPeerCertificateChainSha256 != nil { 350 config.PinnedPeerCertificateChainSha256 = [][]byte{} 351 for _, v := range *c.PinnedPeerCertificateChainSha256 { 352 hashValue, err := base64.StdEncoding.DecodeString(v) 353 if err != nil { 354 return nil, err 355 } 356 config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) 357 } 358 } 359 360 return config, nil 361 } 362 363 type TransportProtocol string 364 365 // Build implements Buildable. 366 func (p TransportProtocol) Build() (string, error) { 367 switch strings.ToLower(string(p)) { 368 case "tcp": 369 return "tcp", nil 370 case "kcp", "mkcp": 371 return "mkcp", nil 372 case "ws", "websocket": 373 return "websocket", nil 374 case "h2", "http": 375 return "http", nil 376 case "ds", "domainsocket": 377 return "domainsocket", nil 378 case "quic": 379 return "quic", nil 380 case "gun", "grpc": 381 return "gun", nil 382 default: 383 return "", newError("Config: unknown transport protocol: ", p) 384 } 385 } 386 387 type SocketConfig struct { 388 Mark uint32 `json:"mark"` 389 TFO *bool `json:"tcpFastOpen"` 390 TFOQueueLength uint32 `json:"tcpFastOpenQueueLength"` 391 TProxy string `json:"tproxy"` 392 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 393 TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"` 394 TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"` 395 } 396 397 // Build implements Buildable. 398 func (c *SocketConfig) Build() (*internet.SocketConfig, error) { 399 var tfoSettings internet.SocketConfig_TCPFastOpenState 400 if c.TFO != nil { 401 if *c.TFO { 402 tfoSettings = internet.SocketConfig_Enable 403 } else { 404 tfoSettings = internet.SocketConfig_Disable 405 } 406 } 407 408 tfoQueueLength := c.TFOQueueLength 409 if tfoQueueLength == 0 { 410 tfoQueueLength = 4096 411 } 412 413 var tproxy internet.SocketConfig_TProxyMode 414 switch strings.ToLower(c.TProxy) { 415 case "tproxy": 416 tproxy = internet.SocketConfig_TProxy 417 case "redirect": 418 tproxy = internet.SocketConfig_Redirect 419 default: 420 tproxy = internet.SocketConfig_Off 421 } 422 423 return &internet.SocketConfig{ 424 Mark: c.Mark, 425 Tfo: tfoSettings, 426 TfoQueueLength: tfoQueueLength, 427 Tproxy: tproxy, 428 AcceptProxyProtocol: c.AcceptProxyProtocol, 429 TcpKeepAliveInterval: c.TCPKeepAliveInterval, 430 TcpKeepAliveIdle: c.TCPKeepAliveIdle, 431 }, nil 432 } 433 434 type StreamConfig struct { 435 Network *TransportProtocol `json:"network"` 436 Security string `json:"security"` 437 TLSSettings *TLSConfig `json:"tlsSettings"` 438 TCPSettings *TCPConfig `json:"tcpSettings"` 439 KCPSettings *KCPConfig `json:"kcpSettings"` 440 WSSettings *WebSocketConfig `json:"wsSettings"` 441 HTTPSettings *HTTPConfig `json:"httpSettings"` 442 DSSettings *DomainSocketConfig `json:"dsSettings"` 443 QUICSettings *QUICConfig `json:"quicSettings"` 444 GunSettings *GunConfig `json:"gunSettings"` 445 GRPCSettings *GunConfig `json:"grpcSettings"` 446 SocketSettings *SocketConfig `json:"sockopt"` 447 } 448 449 // Build implements Buildable. 450 func (c *StreamConfig) Build() (*internet.StreamConfig, error) { 451 config := &internet.StreamConfig{ 452 ProtocolName: "tcp", 453 } 454 if c.Network != nil { 455 protocol, err := c.Network.Build() 456 if err != nil { 457 return nil, err 458 } 459 config.ProtocolName = protocol 460 } 461 if strings.EqualFold(c.Security, "tls") { 462 tlsSettings := c.TLSSettings 463 if tlsSettings == nil { 464 tlsSettings = &TLSConfig{} 465 } 466 ts, err := tlsSettings.Build() 467 if err != nil { 468 return nil, newError("Failed to build TLS config.").Base(err) 469 } 470 tm := serial.ToTypedMessage(ts) 471 config.SecuritySettings = append(config.SecuritySettings, tm) 472 config.SecurityType = tm.Type 473 } 474 if c.TCPSettings != nil { 475 ts, err := c.TCPSettings.Build() 476 if err != nil { 477 return nil, newError("Failed to build TCP config.").Base(err) 478 } 479 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 480 ProtocolName: "tcp", 481 Settings: serial.ToTypedMessage(ts), 482 }) 483 } 484 if c.KCPSettings != nil { 485 ts, err := c.KCPSettings.Build() 486 if err != nil { 487 return nil, newError("Failed to build mKCP config.").Base(err) 488 } 489 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 490 ProtocolName: "mkcp", 491 Settings: serial.ToTypedMessage(ts), 492 }) 493 } 494 if c.WSSettings != nil { 495 ts, err := c.WSSettings.Build() 496 if err != nil { 497 return nil, newError("Failed to build WebSocket config.").Base(err) 498 } 499 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 500 ProtocolName: "websocket", 501 Settings: serial.ToTypedMessage(ts), 502 }) 503 } 504 if c.HTTPSettings != nil { 505 ts, err := c.HTTPSettings.Build() 506 if err != nil { 507 return nil, newError("Failed to build HTTP config.").Base(err) 508 } 509 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 510 ProtocolName: "http", 511 Settings: serial.ToTypedMessage(ts), 512 }) 513 } 514 if c.DSSettings != nil { 515 ds, err := c.DSSettings.Build() 516 if err != nil { 517 return nil, newError("Failed to build DomainSocket config.").Base(err) 518 } 519 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 520 ProtocolName: "domainsocket", 521 Settings: serial.ToTypedMessage(ds), 522 }) 523 } 524 if c.QUICSettings != nil { 525 qs, err := c.QUICSettings.Build() 526 if err != nil { 527 return nil, newError("Failed to build QUIC config.").Base(err) 528 } 529 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 530 ProtocolName: "quic", 531 Settings: serial.ToTypedMessage(qs), 532 }) 533 } 534 if c.GunSettings == nil { 535 c.GunSettings = c.GRPCSettings 536 } 537 if c.GunSettings != nil { 538 gs, err := c.GunSettings.Build() 539 if err != nil { 540 return nil, newError("Failed to build Gun config.").Base(err) 541 } 542 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 543 ProtocolName: "gun", 544 Settings: serial.ToTypedMessage(gs), 545 }) 546 } 547 if c.SocketSettings != nil { 548 ss, err := c.SocketSettings.Build() 549 if err != nil { 550 return nil, newError("Failed to build sockopt.").Base(err) 551 } 552 config.SocketSettings = ss 553 } 554 return config, nil 555 } 556 557 type ProxyConfig struct { 558 Tag string `json:"tag"` 559 TransportLayerProxy bool `json:"transportLayer"` 560 } 561 562 // Build implements Buildable. 563 func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) { 564 if v.Tag == "" { 565 return nil, newError("Proxy tag is not set.") 566 } 567 return &internet.ProxyConfig{ 568 Tag: v.Tag, 569 TransportLayerProxy: v.TransportLayerProxy, 570 }, nil 571 }