github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/conf/v2ray.go (about)

     1  package conf
     2  
     3  import (
     4  	"encoding/json"
     5  	"log"
     6  	"os"
     7  	"strings"
     8  
     9  	"v2ray.com/core"
    10  	"v2ray.com/core/app/dispatcher"
    11  	"v2ray.com/core/app/proxyman"
    12  	"v2ray.com/core/app/stats"
    13  	"v2ray.com/core/common/serial"
    14  	"v2ray.com/core/transport/internet/xtls"
    15  )
    16  
    17  var (
    18  	inboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
    19  		"dokodemo-door": func() interface{} { return new(DokodemoConfig) },
    20  		"http":          func() interface{} { return new(HttpServerConfig) },
    21  		"shadowsocks":   func() interface{} { return new(ShadowsocksServerConfig) },
    22  		"socks":         func() interface{} { return new(SocksServerConfig) },
    23  		"vless":         func() interface{} { return new(VLessInboundConfig) },
    24  		"vmess":         func() interface{} { return new(VMessInboundConfig) },
    25  		"trojan":        func() interface{} { return new(TrojanServerConfig) },
    26  		"mtproto":       func() interface{} { return new(MTProtoServerConfig) },
    27  	}, "protocol", "settings")
    28  
    29  	outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
    30  		"blackhole":   func() interface{} { return new(BlackholeConfig) },
    31  		"freedom":     func() interface{} { return new(FreedomConfig) },
    32  		"http":        func() interface{} { return new(HttpClientConfig) },
    33  		"shadowsocks": func() interface{} { return new(ShadowsocksClientConfig) },
    34  		"socks":       func() interface{} { return new(SocksClientConfig) },
    35  		"vless":       func() interface{} { return new(VLessOutboundConfig) },
    36  		"vmess":       func() interface{} { return new(VMessOutboundConfig) },
    37  		"trojan":      func() interface{} { return new(TrojanClientConfig) },
    38  		"mtproto":     func() interface{} { return new(MTProtoClientConfig) },
    39  		"dns":         func() interface{} { return new(DnsOutboundConfig) },
    40  	}, "protocol", "settings")
    41  
    42  	ctllog = log.New(os.Stderr, "v2ctl> ", 0)
    43  )
    44  
    45  func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) {
    46  	kp := make([]proxyman.KnownProtocols, 0, 8)
    47  	for _, p := range s {
    48  		switch strings.ToLower(p) {
    49  		case "http":
    50  			kp = append(kp, proxyman.KnownProtocols_HTTP)
    51  		case "https", "tls", "ssl":
    52  			kp = append(kp, proxyman.KnownProtocols_TLS)
    53  		default:
    54  			return nil, newError("Unknown protocol: ", p)
    55  		}
    56  	}
    57  	return kp, nil
    58  }
    59  
    60  type SniffingConfig struct {
    61  	Enabled      bool        `json:"enabled"`
    62  	DestOverride *StringList `json:"destOverride"`
    63  }
    64  
    65  // Build implements Buildable.
    66  func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
    67  	var p []string
    68  	if c.DestOverride != nil {
    69  		for _, domainOverride := range *c.DestOverride {
    70  			switch strings.ToLower(domainOverride) {
    71  			case "http":
    72  				p = append(p, "http")
    73  			case "tls", "https", "ssl":
    74  				p = append(p, "tls")
    75  			default:
    76  				return nil, newError("unknown protocol: ", domainOverride)
    77  			}
    78  		}
    79  	}
    80  
    81  	return &proxyman.SniffingConfig{
    82  		Enabled:             c.Enabled,
    83  		DestinationOverride: p,
    84  	}, nil
    85  }
    86  
    87  type MuxConfig struct {
    88  	Enabled     bool  `json:"enabled"`
    89  	Concurrency int16 `json:"concurrency"`
    90  }
    91  
    92  // Build creates MultiplexingConfig, Concurrency < 0 completely disables mux.
    93  func (m *MuxConfig) Build() *proxyman.MultiplexingConfig {
    94  	if m.Concurrency < 0 {
    95  		return nil
    96  	}
    97  
    98  	var con uint32 = 8
    99  	if m.Concurrency > 0 {
   100  		con = uint32(m.Concurrency)
   101  	}
   102  
   103  	return &proxyman.MultiplexingConfig{
   104  		Enabled:     m.Enabled,
   105  		Concurrency: con,
   106  	}
   107  }
   108  
   109  type InboundDetourAllocationConfig struct {
   110  	Strategy    string  `json:"strategy"`
   111  	Concurrency *uint32 `json:"concurrency"`
   112  	RefreshMin  *uint32 `json:"refresh"`
   113  }
   114  
   115  // Build implements Buildable.
   116  func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, error) {
   117  	config := new(proxyman.AllocationStrategy)
   118  	switch strings.ToLower(c.Strategy) {
   119  	case "always":
   120  		config.Type = proxyman.AllocationStrategy_Always
   121  	case "random":
   122  		config.Type = proxyman.AllocationStrategy_Random
   123  	case "external":
   124  		config.Type = proxyman.AllocationStrategy_External
   125  	default:
   126  		return nil, newError("unknown allocation strategy: ", c.Strategy)
   127  	}
   128  	if c.Concurrency != nil {
   129  		config.Concurrency = &proxyman.AllocationStrategy_AllocationStrategyConcurrency{
   130  			Value: *c.Concurrency,
   131  		}
   132  	}
   133  
   134  	if c.RefreshMin != nil {
   135  		config.Refresh = &proxyman.AllocationStrategy_AllocationStrategyRefresh{
   136  			Value: *c.RefreshMin,
   137  		}
   138  	}
   139  
   140  	return config, nil
   141  }
   142  
   143  type InboundDetourConfig struct {
   144  	Protocol       string                         `json:"protocol"`
   145  	PortRange      *PortRange                     `json:"port"`
   146  	ListenOn       *Address                       `json:"listen"`
   147  	Settings       *json.RawMessage               `json:"settings"`
   148  	Tag            string                         `json:"tag"`
   149  	Allocation     *InboundDetourAllocationConfig `json:"allocate"`
   150  	StreamSetting  *StreamConfig                  `json:"streamSettings"`
   151  	DomainOverride *StringList                    `json:"domainOverride"`
   152  	SniffingConfig *SniffingConfig                `json:"sniffing"`
   153  }
   154  
   155  // Build implements Buildable.
   156  func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
   157  	receiverSettings := &proxyman.ReceiverConfig{}
   158  
   159  	if c.PortRange == nil {
   160  		return nil, newError("port range not specified in InboundDetour.")
   161  	}
   162  	receiverSettings.PortRange = c.PortRange.Build()
   163  
   164  	if c.ListenOn != nil {
   165  		if c.ListenOn.Family().IsDomain() {
   166  			return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain())
   167  		}
   168  		receiverSettings.Listen = c.ListenOn.Build()
   169  	}
   170  	if c.Allocation != nil {
   171  		concurrency := -1
   172  		if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" {
   173  			concurrency = int(*c.Allocation.Concurrency)
   174  		}
   175  		portRange := int(c.PortRange.To - c.PortRange.From + 1)
   176  		if concurrency >= 0 && concurrency >= portRange {
   177  			return nil, newError("not enough ports. concurrency = ", concurrency, " ports: ", c.PortRange.From, " - ", c.PortRange.To)
   178  		}
   179  
   180  		as, err := c.Allocation.Build()
   181  		if err != nil {
   182  			return nil, err
   183  		}
   184  		receiverSettings.AllocationStrategy = as
   185  	}
   186  	if c.StreamSetting != nil {
   187  		ss, err := c.StreamSetting.Build()
   188  		if err != nil {
   189  			return nil, err
   190  		}
   191  		if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) && !strings.EqualFold(c.Protocol, "vless") {
   192  			return nil, newError("XTLS only supports VLESS for now.")
   193  		}
   194  		receiverSettings.StreamSettings = ss
   195  	}
   196  	if c.SniffingConfig != nil {
   197  		s, err := c.SniffingConfig.Build()
   198  		if err != nil {
   199  			return nil, newError("failed to build sniffing config").Base(err)
   200  		}
   201  		receiverSettings.SniffingSettings = s
   202  	}
   203  	if c.DomainOverride != nil {
   204  		kp, err := toProtocolList(*c.DomainOverride)
   205  		if err != nil {
   206  			return nil, newError("failed to parse inbound detour config").Base(err)
   207  		}
   208  		receiverSettings.DomainOverride = kp
   209  	}
   210  
   211  	settings := []byte("{}")
   212  	if c.Settings != nil {
   213  		settings = ([]byte)(*c.Settings)
   214  	}
   215  	rawConfig, err := inboundConfigLoader.LoadWithID(settings, c.Protocol)
   216  	if err != nil {
   217  		return nil, newError("failed to load inbound detour config.").Base(err)
   218  	}
   219  	if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok {
   220  		receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect
   221  	}
   222  	ts, err := rawConfig.(Buildable).Build()
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	return &core.InboundHandlerConfig{
   228  		Tag:              c.Tag,
   229  		ReceiverSettings: serial.ToTypedMessage(receiverSettings),
   230  		ProxySettings:    serial.ToTypedMessage(ts),
   231  	}, nil
   232  }
   233  
   234  type OutboundDetourConfig struct {
   235  	Protocol      string           `json:"protocol"`
   236  	SendThrough   *Address         `json:"sendThrough"`
   237  	Tag           string           `json:"tag"`
   238  	Settings      *json.RawMessage `json:"settings"`
   239  	StreamSetting *StreamConfig    `json:"streamSettings"`
   240  	ProxySettings *ProxyConfig     `json:"proxySettings"`
   241  	MuxSettings   *MuxConfig       `json:"mux"`
   242  }
   243  
   244  // Build implements Buildable.
   245  func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
   246  	senderSettings := &proxyman.SenderConfig{}
   247  
   248  	if c.SendThrough != nil {
   249  		address := c.SendThrough
   250  		if address.Family().IsDomain() {
   251  			return nil, newError("unable to send through: " + address.String())
   252  		}
   253  		senderSettings.Via = address.Build()
   254  	}
   255  
   256  	if c.StreamSetting != nil {
   257  		ss, err := c.StreamSetting.Build()
   258  		if err != nil {
   259  			return nil, err
   260  		}
   261  		if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) && !strings.EqualFold(c.Protocol, "vless") {
   262  			return nil, newError("XTLS only supports VLESS for now.")
   263  		}
   264  		senderSettings.StreamSettings = ss
   265  	}
   266  
   267  	if c.ProxySettings != nil {
   268  		ps, err := c.ProxySettings.Build()
   269  		if err != nil {
   270  			return nil, newError("invalid outbound detour proxy settings.").Base(err)
   271  		}
   272  		senderSettings.ProxySettings = ps
   273  	}
   274  
   275  	if c.MuxSettings != nil {
   276  		ms := c.MuxSettings.Build()
   277  		if ms != nil && ms.Enabled {
   278  			if ss := senderSettings.StreamSettings; ss != nil {
   279  				if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) {
   280  					return nil, newError("XTLS doesn't support Mux for now.")
   281  				}
   282  			}
   283  		}
   284  		senderSettings.MultiplexSettings = ms
   285  	}
   286  
   287  	settings := []byte("{}")
   288  	if c.Settings != nil {
   289  		settings = ([]byte)(*c.Settings)
   290  	}
   291  	rawConfig, err := outboundConfigLoader.LoadWithID(settings, c.Protocol)
   292  	if err != nil {
   293  		return nil, newError("failed to parse to outbound detour config.").Base(err)
   294  	}
   295  	ts, err := rawConfig.(Buildable).Build()
   296  	if err != nil {
   297  		return nil, err
   298  	}
   299  
   300  	return &core.OutboundHandlerConfig{
   301  		SenderSettings: serial.ToTypedMessage(senderSettings),
   302  		Tag:            c.Tag,
   303  		ProxySettings:  serial.ToTypedMessage(ts),
   304  	}, nil
   305  }
   306  
   307  type StatsConfig struct{}
   308  
   309  // Build implements Buildable.
   310  func (c *StatsConfig) Build() (*stats.Config, error) {
   311  	return &stats.Config{}, nil
   312  }
   313  
   314  type Config struct {
   315  	Port            uint16                 `json:"port"` // Port of this Point server. Deprecated.
   316  	LogConfig       *LogConfig             `json:"log"`
   317  	RouterConfig    *RouterConfig          `json:"routing"`
   318  	DNSConfig       *DnsConfig             `json:"dns"`
   319  	InboundConfigs  []InboundDetourConfig  `json:"inbounds"`
   320  	OutboundConfigs []OutboundDetourConfig `json:"outbounds"`
   321  	InboundConfig   *InboundDetourConfig   `json:"inbound"`        // Deprecated.
   322  	OutboundConfig  *OutboundDetourConfig  `json:"outbound"`       // Deprecated.
   323  	InboundDetours  []InboundDetourConfig  `json:"inboundDetour"`  // Deprecated.
   324  	OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` // Deprecated.
   325  	Transport       *TransportConfig       `json:"transport"`
   326  	Policy          *PolicyConfig          `json:"policy"`
   327  	Api             *ApiConfig             `json:"api"`
   328  	Stats           *StatsConfig           `json:"stats"`
   329  	Reverse         *ReverseConfig         `json:"reverse"`
   330  }
   331  
   332  func (c *Config) findInboundTag(tag string) int {
   333  	found := -1
   334  	for idx, ib := range c.InboundConfigs {
   335  		if ib.Tag == tag {
   336  			found = idx
   337  			break
   338  		}
   339  	}
   340  	return found
   341  }
   342  
   343  func (c *Config) findOutboundTag(tag string) int {
   344  	found := -1
   345  	for idx, ob := range c.OutboundConfigs {
   346  		if ob.Tag == tag {
   347  			found = idx
   348  			break
   349  		}
   350  	}
   351  	return found
   352  }
   353  
   354  // Override method accepts another Config overrides the current attribute
   355  func (c *Config) Override(o *Config, fn string) {
   356  
   357  	// only process the non-deprecated members
   358  
   359  	if o.LogConfig != nil {
   360  		c.LogConfig = o.LogConfig
   361  	}
   362  	if o.RouterConfig != nil {
   363  		c.RouterConfig = o.RouterConfig
   364  	}
   365  	if o.DNSConfig != nil {
   366  		c.DNSConfig = o.DNSConfig
   367  	}
   368  	if o.Transport != nil {
   369  		c.Transport = o.Transport
   370  	}
   371  	if o.Policy != nil {
   372  		c.Policy = o.Policy
   373  	}
   374  	if o.Api != nil {
   375  		c.Api = o.Api
   376  	}
   377  	if o.Stats != nil {
   378  		c.Stats = o.Stats
   379  	}
   380  	if o.Reverse != nil {
   381  		c.Reverse = o.Reverse
   382  	}
   383  
   384  	// deprecated attrs... keep them for now
   385  	if o.InboundConfig != nil {
   386  		c.InboundConfig = o.InboundConfig
   387  	}
   388  	if o.OutboundConfig != nil {
   389  		c.OutboundConfig = o.OutboundConfig
   390  	}
   391  	if o.InboundDetours != nil {
   392  		c.InboundDetours = o.InboundDetours
   393  	}
   394  	if o.OutboundDetours != nil {
   395  		c.OutboundDetours = o.OutboundDetours
   396  	}
   397  	// deprecated attrs
   398  
   399  	// update the Inbound in slice if the only one in overide config has same tag
   400  	if len(o.InboundConfigs) > 0 {
   401  		if len(c.InboundConfigs) > 0 && len(o.InboundConfigs) == 1 {
   402  			if idx := c.findInboundTag(o.InboundConfigs[0].Tag); idx > -1 {
   403  				c.InboundConfigs[idx] = o.InboundConfigs[0]
   404  				ctllog.Println("[", fn, "] updated inbound with tag: ", o.InboundConfigs[0].Tag)
   405  			} else {
   406  				c.InboundConfigs = append(c.InboundConfigs, o.InboundConfigs[0])
   407  				ctllog.Println("[", fn, "] appended inbound with tag: ", o.InboundConfigs[0].Tag)
   408  			}
   409  		} else {
   410  			c.InboundConfigs = o.InboundConfigs
   411  		}
   412  	}
   413  
   414  	// update the Outbound in slice if the only one in overide config has same tag
   415  	if len(o.OutboundConfigs) > 0 {
   416  		if len(c.OutboundConfigs) > 0 && len(o.OutboundConfigs) == 1 {
   417  			if idx := c.findOutboundTag(o.OutboundConfigs[0].Tag); idx > -1 {
   418  				c.OutboundConfigs[idx] = o.OutboundConfigs[0]
   419  				ctllog.Println("[", fn, "] updated outbound with tag: ", o.OutboundConfigs[0].Tag)
   420  			} else {
   421  				if strings.Contains(strings.ToLower(fn), "tail") {
   422  					c.OutboundConfigs = append(c.OutboundConfigs, o.OutboundConfigs[0])
   423  					ctllog.Println("[", fn, "] appended outbound with tag: ", o.OutboundConfigs[0].Tag)
   424  				} else {
   425  					c.OutboundConfigs = append(o.OutboundConfigs, c.OutboundConfigs...)
   426  					ctllog.Println("[", fn, "] prepended outbound with tag: ", o.OutboundConfigs[0].Tag)
   427  				}
   428  			}
   429  		} else {
   430  			c.OutboundConfigs = o.OutboundConfigs
   431  		}
   432  	}
   433  }
   434  
   435  func applyTransportConfig(s *StreamConfig, t *TransportConfig) {
   436  	if s.TCPSettings == nil {
   437  		s.TCPSettings = t.TCPConfig
   438  	}
   439  	if s.KCPSettings == nil {
   440  		s.KCPSettings = t.KCPConfig
   441  	}
   442  	if s.WSSettings == nil {
   443  		s.WSSettings = t.WSConfig
   444  	}
   445  	if s.HTTPSettings == nil {
   446  		s.HTTPSettings = t.HTTPConfig
   447  	}
   448  	if s.DSSettings == nil {
   449  		s.DSSettings = t.DSConfig
   450  	}
   451  }
   452  
   453  // Build implements Buildable.
   454  func (c *Config) Build() (*core.Config, error) {
   455  	config := &core.Config{
   456  		App: []*serial.TypedMessage{
   457  			serial.ToTypedMessage(&dispatcher.Config{}),
   458  			serial.ToTypedMessage(&proxyman.InboundConfig{}),
   459  			serial.ToTypedMessage(&proxyman.OutboundConfig{}),
   460  		},
   461  	}
   462  
   463  	if c.Api != nil {
   464  		apiConf, err := c.Api.Build()
   465  		if err != nil {
   466  			return nil, err
   467  		}
   468  		config.App = append(config.App, serial.ToTypedMessage(apiConf))
   469  	}
   470  
   471  	if c.Stats != nil {
   472  		statsConf, err := c.Stats.Build()
   473  		if err != nil {
   474  			return nil, err
   475  		}
   476  		config.App = append(config.App, serial.ToTypedMessage(statsConf))
   477  	}
   478  
   479  	var logConfMsg *serial.TypedMessage
   480  	if c.LogConfig != nil {
   481  		logConfMsg = serial.ToTypedMessage(c.LogConfig.Build())
   482  	} else {
   483  		logConfMsg = serial.ToTypedMessage(DefaultLogConfig())
   484  	}
   485  	// let logger module be the first App to start,
   486  	// so that other modules could print log during initiating
   487  	config.App = append([]*serial.TypedMessage{logConfMsg}, config.App...)
   488  
   489  	if c.RouterConfig != nil {
   490  		routerConfig, err := c.RouterConfig.Build()
   491  		if err != nil {
   492  			return nil, err
   493  		}
   494  		config.App = append(config.App, serial.ToTypedMessage(routerConfig))
   495  	}
   496  
   497  	if c.DNSConfig != nil {
   498  		dnsApp, err := c.DNSConfig.Build()
   499  		if err != nil {
   500  			return nil, newError("failed to parse DNS config").Base(err)
   501  		}
   502  		config.App = append(config.App, serial.ToTypedMessage(dnsApp))
   503  	}
   504  
   505  	if c.Policy != nil {
   506  		pc, err := c.Policy.Build()
   507  		if err != nil {
   508  			return nil, err
   509  		}
   510  		config.App = append(config.App, serial.ToTypedMessage(pc))
   511  	}
   512  
   513  	if c.Reverse != nil {
   514  		r, err := c.Reverse.Build()
   515  		if err != nil {
   516  			return nil, err
   517  		}
   518  		config.App = append(config.App, serial.ToTypedMessage(r))
   519  	}
   520  
   521  	var inbounds []InboundDetourConfig
   522  
   523  	if c.InboundConfig != nil {
   524  		inbounds = append(inbounds, *c.InboundConfig)
   525  	}
   526  
   527  	if len(c.InboundDetours) > 0 {
   528  		inbounds = append(inbounds, c.InboundDetours...)
   529  	}
   530  
   531  	if len(c.InboundConfigs) > 0 {
   532  		inbounds = append(inbounds, c.InboundConfigs...)
   533  	}
   534  
   535  	// Backward compatibility.
   536  	if len(inbounds) > 0 && inbounds[0].PortRange == nil && c.Port > 0 {
   537  		inbounds[0].PortRange = &PortRange{
   538  			From: uint32(c.Port),
   539  			To:   uint32(c.Port),
   540  		}
   541  	}
   542  
   543  	for _, rawInboundConfig := range inbounds {
   544  		if c.Transport != nil {
   545  			if rawInboundConfig.StreamSetting == nil {
   546  				rawInboundConfig.StreamSetting = &StreamConfig{}
   547  			}
   548  			applyTransportConfig(rawInboundConfig.StreamSetting, c.Transport)
   549  		}
   550  		ic, err := rawInboundConfig.Build()
   551  		if err != nil {
   552  			return nil, err
   553  		}
   554  		config.Inbound = append(config.Inbound, ic)
   555  	}
   556  
   557  	var outbounds []OutboundDetourConfig
   558  
   559  	if c.OutboundConfig != nil {
   560  		outbounds = append(outbounds, *c.OutboundConfig)
   561  	}
   562  
   563  	if len(c.OutboundDetours) > 0 {
   564  		outbounds = append(outbounds, c.OutboundDetours...)
   565  	}
   566  
   567  	if len(c.OutboundConfigs) > 0 {
   568  		outbounds = append(outbounds, c.OutboundConfigs...)
   569  	}
   570  
   571  	for _, rawOutboundConfig := range outbounds {
   572  		if c.Transport != nil {
   573  			if rawOutboundConfig.StreamSetting == nil {
   574  				rawOutboundConfig.StreamSetting = &StreamConfig{}
   575  			}
   576  			applyTransportConfig(rawOutboundConfig.StreamSetting, c.Transport)
   577  		}
   578  		oc, err := rawOutboundConfig.Build()
   579  		if err != nil {
   580  			return nil, err
   581  		}
   582  		config.Outbound = append(config.Outbound, oc)
   583  	}
   584  
   585  	return config, nil
   586  }