github.com/xraypb/xray-core@v1.6.6/infra/conf/transport_internet.go (about) 1 package conf 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "math" 7 "net/url" 8 "strconv" 9 "strings" 10 11 "github.com/golang/protobuf/proto" 12 "github.com/xraypb/xray-core/common/platform/filesystem" 13 "github.com/xraypb/xray-core/common/protocol" 14 "github.com/xraypb/xray-core/common/serial" 15 "github.com/xraypb/xray-core/transport/internet" 16 "github.com/xraypb/xray-core/transport/internet/domainsocket" 17 httpheader "github.com/xraypb/xray-core/transport/internet/headers/http" 18 "github.com/xraypb/xray-core/transport/internet/http" 19 "github.com/xraypb/xray-core/transport/internet/kcp" 20 "github.com/xraypb/xray-core/transport/internet/quic" 21 "github.com/xraypb/xray-core/transport/internet/tcp" 22 "github.com/xraypb/xray-core/transport/internet/tls" 23 "github.com/xraypb/xray-core/transport/internet/websocket" 24 "github.com/xraypb/xray-core/transport/internet/xtls" 25 ) 26 27 var ( 28 kcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{ 29 "none": func() interface{} { return new(NoOpAuthenticator) }, 30 "srtp": func() interface{} { return new(SRTPAuthenticator) }, 31 "utp": func() interface{} { return new(UTPAuthenticator) }, 32 "wechat-video": func() interface{} { return new(WechatVideoAuthenticator) }, 33 "dtls": func() interface{} { return new(DTLSAuthenticator) }, 34 "wireguard": func() interface{} { return new(WireguardAuthenticator) }, 35 }, "type", "") 36 37 tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{ 38 "none": func() interface{} { return new(NoOpConnectionAuthenticator) }, 39 "http": func() interface{} { return new(Authenticator) }, 40 }, "type", "") 41 ) 42 43 type KCPConfig struct { 44 Mtu *uint32 `json:"mtu"` 45 Tti *uint32 `json:"tti"` 46 UpCap *uint32 `json:"uplinkCapacity"` 47 DownCap *uint32 `json:"downlinkCapacity"` 48 Congestion *bool `json:"congestion"` 49 ReadBufferSize *uint32 `json:"readBufferSize"` 50 WriteBufferSize *uint32 `json:"writeBufferSize"` 51 HeaderConfig json.RawMessage `json:"header"` 52 Seed *string `json:"seed"` 53 } 54 55 // Build implements Buildable. 56 func (c *KCPConfig) Build() (proto.Message, error) { 57 config := new(kcp.Config) 58 59 if c.Mtu != nil { 60 mtu := *c.Mtu 61 if mtu < 576 || mtu > 1460 { 62 return nil, newError("invalid mKCP MTU size: ", mtu).AtError() 63 } 64 config.Mtu = &kcp.MTU{Value: mtu} 65 } 66 if c.Tti != nil { 67 tti := *c.Tti 68 if tti < 10 || tti > 100 { 69 return nil, newError("invalid mKCP TTI: ", tti).AtError() 70 } 71 config.Tti = &kcp.TTI{Value: tti} 72 } 73 if c.UpCap != nil { 74 config.UplinkCapacity = &kcp.UplinkCapacity{Value: *c.UpCap} 75 } 76 if c.DownCap != nil { 77 config.DownlinkCapacity = &kcp.DownlinkCapacity{Value: *c.DownCap} 78 } 79 if c.Congestion != nil { 80 config.Congestion = *c.Congestion 81 } 82 if c.ReadBufferSize != nil { 83 size := *c.ReadBufferSize 84 if size > 0 { 85 config.ReadBuffer = &kcp.ReadBuffer{Size: size * 1024 * 1024} 86 } else { 87 config.ReadBuffer = &kcp.ReadBuffer{Size: 512 * 1024} 88 } 89 } 90 if c.WriteBufferSize != nil { 91 size := *c.WriteBufferSize 92 if size > 0 { 93 config.WriteBuffer = &kcp.WriteBuffer{Size: size * 1024 * 1024} 94 } else { 95 config.WriteBuffer = &kcp.WriteBuffer{Size: 512 * 1024} 96 } 97 } 98 if len(c.HeaderConfig) > 0 { 99 headerConfig, _, err := kcpHeaderLoader.Load(c.HeaderConfig) 100 if err != nil { 101 return nil, newError("invalid mKCP header config.").Base(err).AtError() 102 } 103 ts, err := headerConfig.(Buildable).Build() 104 if err != nil { 105 return nil, newError("invalid mKCP header config").Base(err).AtError() 106 } 107 config.HeaderConfig = serial.ToTypedMessage(ts) 108 } 109 110 if c.Seed != nil { 111 config.Seed = &kcp.EncryptionSeed{Seed: *c.Seed} 112 } 113 114 return config, nil 115 } 116 117 type TCPConfig struct { 118 HeaderConfig json.RawMessage `json:"header"` 119 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 120 } 121 122 // Build implements Buildable. 123 func (c *TCPConfig) Build() (proto.Message, error) { 124 config := new(tcp.Config) 125 if len(c.HeaderConfig) > 0 { 126 headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig) 127 if err != nil { 128 return nil, newError("invalid TCP header config").Base(err).AtError() 129 } 130 ts, err := headerConfig.(Buildable).Build() 131 if err != nil { 132 return nil, newError("invalid TCP header config").Base(err).AtError() 133 } 134 config.HeaderSettings = serial.ToTypedMessage(ts) 135 } 136 if c.AcceptProxyProtocol { 137 config.AcceptProxyProtocol = c.AcceptProxyProtocol 138 } 139 return config, nil 140 } 141 142 type WebSocketConfig struct { 143 Path string `json:"path"` 144 Headers map[string]string `json:"headers"` 145 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 146 } 147 148 // Build implements Buildable. 149 func (c *WebSocketConfig) Build() (proto.Message, error) { 150 path := c.Path 151 header := make([]*websocket.Header, 0, 32) 152 for key, value := range c.Headers { 153 header = append(header, &websocket.Header{ 154 Key: key, 155 Value: value, 156 }) 157 } 158 var ed uint32 159 if u, err := url.Parse(path); err == nil { 160 if q := u.Query(); q.Get("ed") != "" { 161 Ed, _ := strconv.Atoi(q.Get("ed")) 162 ed = uint32(Ed) 163 q.Del("ed") 164 u.RawQuery = q.Encode() 165 path = u.String() 166 } 167 } 168 config := &websocket.Config{ 169 Path: path, 170 Header: header, 171 Ed: ed, 172 } 173 if c.AcceptProxyProtocol { 174 config.AcceptProxyProtocol = c.AcceptProxyProtocol 175 } 176 return config, nil 177 } 178 179 type HTTPConfig struct { 180 Host *StringList `json:"host"` 181 Path string `json:"path"` 182 ReadIdleTimeout int32 `json:"read_idle_timeout"` 183 HealthCheckTimeout int32 `json:"health_check_timeout"` 184 Method string `json:"method"` 185 Headers map[string]*StringList `json:"headers"` 186 } 187 188 // Build implements Buildable. 189 func (c *HTTPConfig) Build() (proto.Message, error) { 190 if c.ReadIdleTimeout <= 0 { 191 c.ReadIdleTimeout = 0 192 } 193 if c.HealthCheckTimeout <= 0 { 194 c.HealthCheckTimeout = 0 195 } 196 config := &http.Config{ 197 Path: c.Path, 198 IdleTimeout: c.ReadIdleTimeout, 199 HealthCheckTimeout: c.HealthCheckTimeout, 200 } 201 if c.Host != nil { 202 config.Host = []string(*c.Host) 203 } 204 if c.Method != "" { 205 config.Method = c.Method 206 } 207 if len(c.Headers) > 0 { 208 config.Header = make([]*httpheader.Header, 0, len(c.Headers)) 209 headerNames := sortMapKeys(c.Headers) 210 for _, key := range headerNames { 211 value := c.Headers[key] 212 if value == nil { 213 return nil, newError("empty HTTP header value: " + key).AtError() 214 } 215 config.Header = append(config.Header, &httpheader.Header{ 216 Name: key, 217 Value: append([]string(nil), (*value)...), 218 }) 219 } 220 } 221 return config, nil 222 } 223 224 type QUICConfig struct { 225 Header json.RawMessage `json:"header"` 226 Security string `json:"security"` 227 Key string `json:"key"` 228 } 229 230 // Build implements Buildable. 231 func (c *QUICConfig) Build() (proto.Message, error) { 232 config := &quic.Config{ 233 Key: c.Key, 234 } 235 236 if len(c.Header) > 0 { 237 headerConfig, _, err := kcpHeaderLoader.Load(c.Header) 238 if err != nil { 239 return nil, newError("invalid QUIC header config.").Base(err).AtError() 240 } 241 ts, err := headerConfig.(Buildable).Build() 242 if err != nil { 243 return nil, newError("invalid QUIC header config").Base(err).AtError() 244 } 245 config.Header = serial.ToTypedMessage(ts) 246 } 247 248 var st protocol.SecurityType 249 switch strings.ToLower(c.Security) { 250 case "aes-128-gcm": 251 st = protocol.SecurityType_AES128_GCM 252 case "chacha20-poly1305": 253 st = protocol.SecurityType_CHACHA20_POLY1305 254 default: 255 st = protocol.SecurityType_NONE 256 } 257 258 config.Security = &protocol.SecurityConfig{ 259 Type: st, 260 } 261 262 return config, nil 263 } 264 265 type DomainSocketConfig struct { 266 Path string `json:"path"` 267 Abstract bool `json:"abstract"` 268 Padding bool `json:"padding"` 269 } 270 271 // Build implements Buildable. 272 func (c *DomainSocketConfig) Build() (proto.Message, error) { 273 return &domainsocket.Config{ 274 Path: c.Path, 275 Abstract: c.Abstract, 276 Padding: c.Padding, 277 }, nil 278 } 279 280 func readFileOrString(f string, s []string) ([]byte, error) { 281 if len(f) > 0 { 282 return filesystem.ReadFile(f) 283 } 284 if len(s) > 0 { 285 return []byte(strings.Join(s, "\n")), nil 286 } 287 return nil, newError("both file and bytes are empty.") 288 } 289 290 type TLSCertConfig struct { 291 CertFile string `json:"certificateFile"` 292 CertStr []string `json:"certificate"` 293 KeyFile string `json:"keyFile"` 294 KeyStr []string `json:"key"` 295 Usage string `json:"usage"` 296 OcspStapling uint64 `json:"ocspStapling"` 297 OneTimeLoading bool `json:"oneTimeLoading"` 298 } 299 300 // Build implements Buildable. 301 func (c *TLSCertConfig) Build() (*tls.Certificate, error) { 302 certificate := new(tls.Certificate) 303 304 cert, err := readFileOrString(c.CertFile, c.CertStr) 305 if err != nil { 306 return nil, newError("failed to parse certificate").Base(err) 307 } 308 certificate.Certificate = cert 309 certificate.CertificatePath = c.CertFile 310 311 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 312 key, err := readFileOrString(c.KeyFile, c.KeyStr) 313 if err != nil { 314 return nil, newError("failed to parse key").Base(err) 315 } 316 certificate.Key = key 317 certificate.KeyPath = c.KeyFile 318 } 319 320 switch strings.ToLower(c.Usage) { 321 case "encipherment": 322 certificate.Usage = tls.Certificate_ENCIPHERMENT 323 case "verify": 324 certificate.Usage = tls.Certificate_AUTHORITY_VERIFY 325 case "issue": 326 certificate.Usage = tls.Certificate_AUTHORITY_ISSUE 327 default: 328 certificate.Usage = tls.Certificate_ENCIPHERMENT 329 } 330 if certificate.KeyPath == "" && certificate.CertificatePath == "" { 331 certificate.OneTimeLoading = true 332 } else { 333 certificate.OneTimeLoading = c.OneTimeLoading 334 } 335 certificate.OcspStapling = c.OcspStapling 336 337 return certificate, nil 338 } 339 340 type TLSConfig struct { 341 Insecure bool `json:"allowInsecure"` 342 Certs []*TLSCertConfig `json:"certificates"` 343 ServerName string `json:"serverName"` 344 ALPN *StringList `json:"alpn"` 345 EnableSessionResumption bool `json:"enableSessionResumption"` 346 DisableSystemRoot bool `json:"disableSystemRoot"` 347 MinVersion string `json:"minVersion"` 348 MaxVersion string `json:"maxVersion"` 349 CipherSuites string `json:"cipherSuites"` 350 PreferServerCipherSuites bool `json:"preferServerCipherSuites"` 351 Fingerprint string `json:"fingerprint"` 352 RejectUnknownSNI bool `json:"rejectUnknownSni"` 353 PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` 354 } 355 356 // Build implements Buildable. 357 func (c *TLSConfig) Build() (proto.Message, error) { 358 config := new(tls.Config) 359 config.Certificate = make([]*tls.Certificate, len(c.Certs)) 360 for idx, certConf := range c.Certs { 361 cert, err := certConf.Build() 362 if err != nil { 363 return nil, err 364 } 365 config.Certificate[idx] = cert 366 } 367 serverName := c.ServerName 368 config.AllowInsecure = c.Insecure 369 if len(c.ServerName) > 0 { 370 config.ServerName = serverName 371 } 372 if c.ALPN != nil && len(*c.ALPN) > 0 { 373 config.NextProtocol = []string(*c.ALPN) 374 } 375 config.EnableSessionResumption = c.EnableSessionResumption 376 config.DisableSystemRoot = c.DisableSystemRoot 377 config.MinVersion = c.MinVersion 378 config.MaxVersion = c.MaxVersion 379 config.CipherSuites = c.CipherSuites 380 config.PreferServerCipherSuites = c.PreferServerCipherSuites 381 config.Fingerprint = strings.ToLower(c.Fingerprint) 382 config.RejectUnknownSni = c.RejectUnknownSNI 383 384 if c.PinnedPeerCertificateChainSha256 != nil { 385 config.PinnedPeerCertificateChainSha256 = [][]byte{} 386 for _, v := range *c.PinnedPeerCertificateChainSha256 { 387 hashValue, err := base64.StdEncoding.DecodeString(v) 388 if err != nil { 389 return nil, err 390 } 391 config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) 392 } 393 } 394 395 return config, nil 396 } 397 398 type XTLSCertConfig struct { 399 CertFile string `json:"certificateFile"` 400 CertStr []string `json:"certificate"` 401 KeyFile string `json:"keyFile"` 402 KeyStr []string `json:"key"` 403 Usage string `json:"usage"` 404 OcspStapling uint64 `json:"ocspStapling"` 405 OneTimeLoading bool `json:"oneTimeLoading"` 406 } 407 408 // Build implements Buildable. 409 func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) { 410 certificate := new(xtls.Certificate) 411 cert, err := readFileOrString(c.CertFile, c.CertStr) 412 if err != nil { 413 return nil, newError("failed to parse certificate").Base(err) 414 } 415 certificate.Certificate = cert 416 certificate.CertificatePath = c.CertFile 417 418 if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 { 419 key, err := readFileOrString(c.KeyFile, c.KeyStr) 420 if err != nil { 421 return nil, newError("failed to parse key").Base(err) 422 } 423 certificate.Key = key 424 certificate.KeyPath = c.KeyFile 425 } 426 427 switch strings.ToLower(c.Usage) { 428 case "encipherment": 429 certificate.Usage = xtls.Certificate_ENCIPHERMENT 430 case "verify": 431 certificate.Usage = xtls.Certificate_AUTHORITY_VERIFY 432 case "issue": 433 certificate.Usage = xtls.Certificate_AUTHORITY_ISSUE 434 default: 435 certificate.Usage = xtls.Certificate_ENCIPHERMENT 436 } 437 if certificate.KeyPath == "" && certificate.CertificatePath == "" { 438 certificate.OneTimeLoading = true 439 } else { 440 certificate.OneTimeLoading = c.OneTimeLoading 441 } 442 certificate.OcspStapling = c.OcspStapling 443 444 return certificate, nil 445 } 446 447 type XTLSConfig struct { 448 Insecure bool `json:"allowInsecure"` 449 Certs []*XTLSCertConfig `json:"certificates"` 450 ServerName string `json:"serverName"` 451 ALPN *StringList `json:"alpn"` 452 EnableSessionResumption bool `json:"enableSessionResumption"` 453 DisableSystemRoot bool `json:"disableSystemRoot"` 454 MinVersion string `json:"minVersion"` 455 MaxVersion string `json:"maxVersion"` 456 CipherSuites string `json:"cipherSuites"` 457 PreferServerCipherSuites bool `json:"preferServerCipherSuites"` 458 RejectUnknownSNI bool `json:"rejectUnknownSni"` 459 PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"` 460 } 461 462 // Build implements Buildable. 463 func (c *XTLSConfig) Build() (proto.Message, error) { 464 config := new(xtls.Config) 465 config.Certificate = make([]*xtls.Certificate, len(c.Certs)) 466 for idx, certConf := range c.Certs { 467 cert, err := certConf.Build() 468 if err != nil { 469 return nil, err 470 } 471 config.Certificate[idx] = cert 472 } 473 serverName := c.ServerName 474 config.AllowInsecure = c.Insecure 475 if len(c.ServerName) > 0 { 476 config.ServerName = serverName 477 } 478 if c.ALPN != nil && len(*c.ALPN) > 0 { 479 config.NextProtocol = []string(*c.ALPN) 480 } 481 config.EnableSessionResumption = c.EnableSessionResumption 482 config.DisableSystemRoot = c.DisableSystemRoot 483 config.MinVersion = c.MinVersion 484 config.MaxVersion = c.MaxVersion 485 config.CipherSuites = c.CipherSuites 486 config.PreferServerCipherSuites = c.PreferServerCipherSuites 487 config.RejectUnknownSni = c.RejectUnknownSNI 488 489 if c.PinnedPeerCertificateChainSha256 != nil { 490 config.PinnedPeerCertificateChainSha256 = [][]byte{} 491 for _, v := range *c.PinnedPeerCertificateChainSha256 { 492 hashValue, err := base64.StdEncoding.DecodeString(v) 493 if err != nil { 494 return nil, err 495 } 496 config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue) 497 } 498 } 499 500 return config, nil 501 } 502 503 type TransportProtocol string 504 505 // Build implements Buildable. 506 func (p TransportProtocol) Build() (string, error) { 507 switch strings.ToLower(string(p)) { 508 case "tcp": 509 return "tcp", nil 510 case "kcp", "mkcp": 511 return "mkcp", nil 512 case "ws", "websocket": 513 return "websocket", nil 514 case "h2", "http": 515 return "http", nil 516 case "ds", "domainsocket": 517 return "domainsocket", nil 518 case "quic": 519 return "quic", nil 520 case "grpc", "gun": 521 return "grpc", nil 522 default: 523 return "", newError("Config: unknown transport protocol: ", p) 524 } 525 } 526 527 type SocketConfig struct { 528 Mark int32 `json:"mark"` 529 TFO interface{} `json:"tcpFastOpen"` 530 TProxy string `json:"tproxy"` 531 AcceptProxyProtocol bool `json:"acceptProxyProtocol"` 532 DomainStrategy string `json:"domainStrategy"` 533 DialerProxy string `json:"dialerProxy"` 534 TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"` 535 TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"` 536 TCPCongestion string `json:"tcpCongestion"` 537 } 538 539 // Build implements Buildable. 540 func (c *SocketConfig) Build() (*internet.SocketConfig, error) { 541 tfo := int32(0) // don't invoke setsockopt() for TFO 542 if c.TFO != nil { 543 switch v := c.TFO.(type) { 544 case bool: 545 if v { 546 tfo = 256 547 } else { 548 tfo = -1 // TFO need to be disabled 549 } 550 case float64: 551 tfo = int32(math.Min(v, math.MaxInt32)) 552 default: 553 return nil, newError("tcpFastOpen: only boolean and integer value is acceptable") 554 } 555 } 556 var tproxy internet.SocketConfig_TProxyMode 557 switch strings.ToLower(c.TProxy) { 558 case "tproxy": 559 tproxy = internet.SocketConfig_TProxy 560 case "redirect": 561 tproxy = internet.SocketConfig_Redirect 562 default: 563 tproxy = internet.SocketConfig_Off 564 } 565 566 dStrategy := internet.DomainStrategy_AS_IS 567 switch strings.ToLower(c.DomainStrategy) { 568 case "useip", "use_ip": 569 dStrategy = internet.DomainStrategy_USE_IP 570 case "useip4", "useipv4", "use_ipv4", "use_ip_v4", "use_ip4": 571 dStrategy = internet.DomainStrategy_USE_IP4 572 case "useip6", "useipv6", "use_ipv6", "use_ip_v6", "use_ip6": 573 dStrategy = internet.DomainStrategy_USE_IP6 574 } 575 576 return &internet.SocketConfig{ 577 Mark: c.Mark, 578 Tfo: tfo, 579 Tproxy: tproxy, 580 DomainStrategy: dStrategy, 581 AcceptProxyProtocol: c.AcceptProxyProtocol, 582 DialerProxy: c.DialerProxy, 583 TcpKeepAliveInterval: c.TCPKeepAliveInterval, 584 TcpKeepAliveIdle: c.TCPKeepAliveIdle, 585 TcpCongestion: c.TCPCongestion, 586 }, nil 587 } 588 589 type StreamConfig struct { 590 Network *TransportProtocol `json:"network"` 591 Security string `json:"security"` 592 TLSSettings *TLSConfig `json:"tlsSettings"` 593 XTLSSettings *XTLSConfig `json:"xtlsSettings"` 594 TCPSettings *TCPConfig `json:"tcpSettings"` 595 KCPSettings *KCPConfig `json:"kcpSettings"` 596 WSSettings *WebSocketConfig `json:"wsSettings"` 597 HTTPSettings *HTTPConfig `json:"httpSettings"` 598 DSSettings *DomainSocketConfig `json:"dsSettings"` 599 QUICSettings *QUICConfig `json:"quicSettings"` 600 SocketSettings *SocketConfig `json:"sockopt"` 601 GRPCConfig *GRPCConfig `json:"grpcSettings"` 602 GUNConfig *GRPCConfig `json:"gunSettings"` 603 } 604 605 // Build implements Buildable. 606 func (c *StreamConfig) Build() (*internet.StreamConfig, error) { 607 config := &internet.StreamConfig{ 608 ProtocolName: "tcp", 609 } 610 if c.Network != nil { 611 protocol, err := c.Network.Build() 612 if err != nil { 613 return nil, err 614 } 615 config.ProtocolName = protocol 616 } 617 if strings.EqualFold(c.Security, "tls") { 618 tlsSettings := c.TLSSettings 619 if tlsSettings == nil { 620 if c.XTLSSettings != nil { 621 return nil, newError(`TLS: Please use "tlsSettings" instead of "xtlsSettings".`) 622 } 623 tlsSettings = &TLSConfig{} 624 } 625 ts, err := tlsSettings.Build() 626 if err != nil { 627 return nil, newError("Failed to build TLS config.").Base(err) 628 } 629 tm := serial.ToTypedMessage(ts) 630 config.SecuritySettings = append(config.SecuritySettings, tm) 631 config.SecurityType = tm.Type 632 } 633 if strings.EqualFold(c.Security, "xtls") { 634 if config.ProtocolName != "tcp" && config.ProtocolName != "mkcp" && config.ProtocolName != "domainsocket" { 635 return nil, newError("XTLS only supports TCP, mKCP and DomainSocket for now.") 636 } 637 xtlsSettings := c.XTLSSettings 638 if xtlsSettings == nil { 639 if c.TLSSettings != nil { 640 return nil, newError(`XTLS: Please use "xtlsSettings" instead of "tlsSettings".`) 641 } 642 xtlsSettings = &XTLSConfig{} 643 } 644 ts, err := xtlsSettings.Build() 645 if err != nil { 646 return nil, newError("Failed to build XTLS config.").Base(err) 647 } 648 tm := serial.ToTypedMessage(ts) 649 config.SecuritySettings = append(config.SecuritySettings, tm) 650 config.SecurityType = tm.Type 651 } 652 if c.TCPSettings != nil { 653 ts, err := c.TCPSettings.Build() 654 if err != nil { 655 return nil, newError("Failed to build TCP config.").Base(err) 656 } 657 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 658 ProtocolName: "tcp", 659 Settings: serial.ToTypedMessage(ts), 660 }) 661 } 662 if c.KCPSettings != nil { 663 ts, err := c.KCPSettings.Build() 664 if err != nil { 665 return nil, newError("Failed to build mKCP config.").Base(err) 666 } 667 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 668 ProtocolName: "mkcp", 669 Settings: serial.ToTypedMessage(ts), 670 }) 671 } 672 if c.WSSettings != nil { 673 ts, err := c.WSSettings.Build() 674 if err != nil { 675 return nil, newError("Failed to build WebSocket config.").Base(err) 676 } 677 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 678 ProtocolName: "websocket", 679 Settings: serial.ToTypedMessage(ts), 680 }) 681 } 682 if c.HTTPSettings != nil { 683 ts, err := c.HTTPSettings.Build() 684 if err != nil { 685 return nil, newError("Failed to build HTTP config.").Base(err) 686 } 687 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 688 ProtocolName: "http", 689 Settings: serial.ToTypedMessage(ts), 690 }) 691 } 692 if c.DSSettings != nil { 693 ds, err := c.DSSettings.Build() 694 if err != nil { 695 return nil, newError("Failed to build DomainSocket config.").Base(err) 696 } 697 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 698 ProtocolName: "domainsocket", 699 Settings: serial.ToTypedMessage(ds), 700 }) 701 } 702 if c.QUICSettings != nil { 703 qs, err := c.QUICSettings.Build() 704 if err != nil { 705 return nil, newError("Failed to build QUIC config").Base(err) 706 } 707 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 708 ProtocolName: "quic", 709 Settings: serial.ToTypedMessage(qs), 710 }) 711 } 712 if c.GRPCConfig == nil { 713 c.GRPCConfig = c.GUNConfig 714 } 715 if c.GRPCConfig != nil { 716 gs, err := c.GRPCConfig.Build() 717 if err != nil { 718 return nil, newError("Failed to build gRPC config.").Base(err) 719 } 720 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 721 ProtocolName: "grpc", 722 Settings: serial.ToTypedMessage(gs), 723 }) 724 } 725 if c.SocketSettings != nil { 726 ss, err := c.SocketSettings.Build() 727 if err != nil { 728 return nil, newError("Failed to build sockopt").Base(err) 729 } 730 config.SocketSettings = ss 731 } 732 return config, nil 733 } 734 735 type ProxyConfig struct { 736 Tag string `json:"tag"` 737 738 // TransportLayerProxy: For compatibility. 739 TransportLayerProxy bool `json:"transportLayer"` 740 } 741 742 // Build implements Buildable. 743 func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) { 744 if v.Tag == "" { 745 return nil, newError("Proxy tag is not set.") 746 } 747 return &internet.ProxyConfig{ 748 Tag: v.Tag, 749 TransportLayerProxy: v.TransportLayerProxy, 750 }, nil 751 }