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  }