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