github.com/moqsien/xraycore@v1.8.5/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/moqsien/xraycore/common/net" 15 "github.com/moqsien/xraycore/common/platform/filesystem" 16 "github.com/moqsien/xraycore/common/protocol" 17 "github.com/moqsien/xraycore/common/serial" 18 "github.com/moqsien/xraycore/transport/internet" 19 "github.com/moqsien/xraycore/transport/internet/domainsocket" 20 httpheader "github.com/moqsien/xraycore/transport/internet/headers/http" 21 "github.com/moqsien/xraycore/transport/internet/http" 22 "github.com/moqsien/xraycore/transport/internet/kcp" 23 "github.com/moqsien/xraycore/transport/internet/quic" 24 "github.com/moqsien/xraycore/transport/internet/reality" 25 "github.com/moqsien/xraycore/transport/internet/tcp" 26 "github.com/moqsien/xraycore/transport/internet/tls" 27 "github.com/moqsien/xraycore/transport/internet/websocket" 28 "google.golang.org/protobuf/proto" 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 TCPMaxSeg int32 `json:"tcpMaxSeg"` 621 TcpNoDelay bool `json:"tcpNoDelay"` 622 TCPUserTimeout int32 `json:"tcpUserTimeout"` 623 V6only bool `json:"v6only"` 624 Interface string `json:"interface"` 625 } 626 627 // Build implements Buildable. 628 func (c *SocketConfig) Build() (*internet.SocketConfig, error) { 629 tfo := int32(0) // don't invoke setsockopt() for TFO 630 if c.TFO != nil { 631 switch v := c.TFO.(type) { 632 case bool: 633 if v { 634 tfo = 256 635 } else { 636 tfo = -1 // TFO need to be disabled 637 } 638 case float64: 639 tfo = int32(math.Min(v, math.MaxInt32)) 640 default: 641 return nil, newError("tcpFastOpen: only boolean and integer value is acceptable") 642 } 643 } 644 var tproxy internet.SocketConfig_TProxyMode 645 switch strings.ToLower(c.TProxy) { 646 case "tproxy": 647 tproxy = internet.SocketConfig_TProxy 648 case "redirect": 649 tproxy = internet.SocketConfig_Redirect 650 default: 651 tproxy = internet.SocketConfig_Off 652 } 653 654 dStrategy := internet.DomainStrategy_AS_IS 655 switch strings.ToLower(c.DomainStrategy) { 656 case "useip", "use_ip": 657 dStrategy = internet.DomainStrategy_USE_IP 658 case "useip4", "useipv4", "use_ipv4", "use_ip_v4", "use_ip4": 659 dStrategy = internet.DomainStrategy_USE_IP4 660 case "useip6", "useipv6", "use_ipv6", "use_ip_v6", "use_ip6": 661 dStrategy = internet.DomainStrategy_USE_IP6 662 } 663 664 return &internet.SocketConfig{ 665 Mark: c.Mark, 666 Tfo: tfo, 667 Tproxy: tproxy, 668 DomainStrategy: dStrategy, 669 AcceptProxyProtocol: c.AcceptProxyProtocol, 670 DialerProxy: c.DialerProxy, 671 TcpKeepAliveInterval: c.TCPKeepAliveInterval, 672 TcpKeepAliveIdle: c.TCPKeepAliveIdle, 673 TcpCongestion: c.TCPCongestion, 674 TcpWindowClamp: c.TCPWindowClamp, 675 TcpMaxSeg: c.TCPMaxSeg, 676 TcpNoDelay: c.TcpNoDelay, 677 TcpUserTimeout: c.TCPUserTimeout, 678 V6Only: c.V6only, 679 Interface: c.Interface, 680 }, nil 681 } 682 683 type StreamConfig struct { 684 Network *TransportProtocol `json:"network"` 685 Security string `json:"security"` 686 TLSSettings *TLSConfig `json:"tlsSettings"` 687 REALITYSettings *REALITYConfig `json:"realitySettings"` 688 TCPSettings *TCPConfig `json:"tcpSettings"` 689 KCPSettings *KCPConfig `json:"kcpSettings"` 690 WSSettings *WebSocketConfig `json:"wsSettings"` 691 HTTPSettings *HTTPConfig `json:"httpSettings"` 692 DSSettings *DomainSocketConfig `json:"dsSettings"` 693 QUICSettings *QUICConfig `json:"quicSettings"` 694 SocketSettings *SocketConfig `json:"sockopt"` 695 GRPCConfig *GRPCConfig `json:"grpcSettings"` 696 GUNConfig *GRPCConfig `json:"gunSettings"` 697 } 698 699 // Build implements Buildable. 700 func (c *StreamConfig) Build() (*internet.StreamConfig, error) { 701 config := &internet.StreamConfig{ 702 ProtocolName: "tcp", 703 } 704 if c.Network != nil { 705 protocol, err := c.Network.Build() 706 if err != nil { 707 return nil, err 708 } 709 config.ProtocolName = protocol 710 } 711 switch strings.ToLower(c.Security) { 712 case "", "none": 713 case "tls": 714 tlsSettings := c.TLSSettings 715 if tlsSettings == nil { 716 tlsSettings = &TLSConfig{} 717 } 718 ts, err := tlsSettings.Build() 719 if err != nil { 720 return nil, newError("Failed to build TLS config.").Base(err) 721 } 722 tm := serial.ToTypedMessage(ts) 723 config.SecuritySettings = append(config.SecuritySettings, tm) 724 config.SecurityType = tm.Type 725 case "reality": 726 if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "grpc" && config.ProtocolName != "domainsocket" { 727 return nil, newError("REALITY only supports TCP, H2, gRPC and DomainSocket for now.") 728 } 729 if c.REALITYSettings == nil { 730 return nil, newError(`REALITY: Empty "realitySettings".`) 731 } 732 ts, err := c.REALITYSettings.Build() 733 if err != nil { 734 return nil, newError("Failed to build REALITY config.").Base(err) 735 } 736 tm := serial.ToTypedMessage(ts) 737 config.SecuritySettings = append(config.SecuritySettings, tm) 738 config.SecurityType = tm.Type 739 case "xtls": 740 return nil, newError(`Please use VLESS flow "xtls-rprx-vision" with TLS or REALITY.`) 741 default: 742 return nil, newError(`Unknown security "` + c.Security + `".`) 743 } 744 if c.TCPSettings != nil { 745 ts, err := c.TCPSettings.Build() 746 if err != nil { 747 return nil, newError("Failed to build TCP config.").Base(err) 748 } 749 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 750 ProtocolName: "tcp", 751 Settings: serial.ToTypedMessage(ts), 752 }) 753 } 754 if c.KCPSettings != nil { 755 ts, err := c.KCPSettings.Build() 756 if err != nil { 757 return nil, newError("Failed to build mKCP config.").Base(err) 758 } 759 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 760 ProtocolName: "mkcp", 761 Settings: serial.ToTypedMessage(ts), 762 }) 763 } 764 if c.WSSettings != nil { 765 ts, err := c.WSSettings.Build() 766 if err != nil { 767 return nil, newError("Failed to build WebSocket config.").Base(err) 768 } 769 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 770 ProtocolName: "websocket", 771 Settings: serial.ToTypedMessage(ts), 772 }) 773 } 774 if c.HTTPSettings != nil { 775 ts, err := c.HTTPSettings.Build() 776 if err != nil { 777 return nil, newError("Failed to build HTTP config.").Base(err) 778 } 779 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 780 ProtocolName: "http", 781 Settings: serial.ToTypedMessage(ts), 782 }) 783 } 784 if c.DSSettings != nil { 785 ds, err := c.DSSettings.Build() 786 if err != nil { 787 return nil, newError("Failed to build DomainSocket config.").Base(err) 788 } 789 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 790 ProtocolName: "domainsocket", 791 Settings: serial.ToTypedMessage(ds), 792 }) 793 } 794 if c.QUICSettings != nil { 795 qs, err := c.QUICSettings.Build() 796 if err != nil { 797 return nil, newError("Failed to build QUIC config").Base(err) 798 } 799 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 800 ProtocolName: "quic", 801 Settings: serial.ToTypedMessage(qs), 802 }) 803 } 804 if c.GRPCConfig == nil { 805 c.GRPCConfig = c.GUNConfig 806 } 807 if c.GRPCConfig != nil { 808 gs, err := c.GRPCConfig.Build() 809 if err != nil { 810 return nil, newError("Failed to build gRPC config.").Base(err) 811 } 812 config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{ 813 ProtocolName: "grpc", 814 Settings: serial.ToTypedMessage(gs), 815 }) 816 } 817 if c.SocketSettings != nil { 818 ss, err := c.SocketSettings.Build() 819 if err != nil { 820 return nil, newError("Failed to build sockopt").Base(err) 821 } 822 config.SocketSettings = ss 823 } 824 return config, nil 825 } 826 827 type ProxyConfig struct { 828 Tag string `json:"tag"` 829 830 // TransportLayerProxy: For compatibility. 831 TransportLayerProxy bool `json:"transportLayer"` 832 } 833 834 // Build implements Buildable. 835 func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) { 836 if v.Tag == "" { 837 return nil, newError("Proxy tag is not set.") 838 } 839 return &internet.ProxyConfig{ 840 Tag: v.Tag, 841 TransportLayerProxy: v.TransportLayerProxy, 842 }, nil 843 }