github.com/imannamdari/v2ray-core/v5@v5.0.5/infra/conf/v4/v2ray.go (about) 1 package v4 2 3 import ( 4 "encoding/json" 5 "strings" 6 7 "google.golang.org/protobuf/types/known/anypb" 8 9 core "github.com/imannamdari/v2ray-core/v5" 10 "github.com/imannamdari/v2ray-core/v5/app/dispatcher" 11 "github.com/imannamdari/v2ray-core/v5/app/proxyman" 12 "github.com/imannamdari/v2ray-core/v5/app/stats" 13 "github.com/imannamdari/v2ray-core/v5/common/serial" 14 "github.com/imannamdari/v2ray-core/v5/features" 15 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon" 16 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon/loader" 17 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon/muxcfg" 18 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon/proxycfg" 19 "github.com/imannamdari/v2ray-core/v5/infra/conf/cfgcommon/sniffer" 20 "github.com/imannamdari/v2ray-core/v5/infra/conf/synthetic/dns" 21 "github.com/imannamdari/v2ray-core/v5/infra/conf/synthetic/log" 22 "github.com/imannamdari/v2ray-core/v5/infra/conf/synthetic/router" 23 ) 24 25 var ( 26 inboundConfigLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{ 27 "dokodemo-door": func() interface{} { return new(DokodemoConfig) }, 28 "http": func() interface{} { return new(HTTPServerConfig) }, 29 "shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) }, 30 "socks": func() interface{} { return new(SocksServerConfig) }, 31 "vless": func() interface{} { return new(VLessInboundConfig) }, 32 "vmess": func() interface{} { return new(VMessInboundConfig) }, 33 "trojan": func() interface{} { return new(TrojanServerConfig) }, 34 }, "protocol", "settings") 35 36 outboundConfigLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{ 37 "blackhole": func() interface{} { return new(BlackholeConfig) }, 38 "freedom": func() interface{} { return new(FreedomConfig) }, 39 "http": func() interface{} { return new(HTTPClientConfig) }, 40 "shadowsocks": func() interface{} { return new(ShadowsocksClientConfig) }, 41 "socks": func() interface{} { return new(SocksClientConfig) }, 42 "vless": func() interface{} { return new(VLessOutboundConfig) }, 43 "vmess": func() interface{} { return new(VMessOutboundConfig) }, 44 "trojan": func() interface{} { return new(TrojanClientConfig) }, 45 "dns": func() interface{} { return new(DNSOutboundConfig) }, 46 "loopback": func() interface{} { return new(LoopbackConfig) }, 47 }, "protocol", "settings") 48 ) 49 50 func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) { 51 kp := make([]proxyman.KnownProtocols, 0, 8) 52 for _, p := range s { 53 switch strings.ToLower(p) { 54 case "http": 55 kp = append(kp, proxyman.KnownProtocols_HTTP) 56 case "https", "tls", "ssl": 57 kp = append(kp, proxyman.KnownProtocols_TLS) 58 default: 59 return nil, newError("Unknown protocol: ", p) 60 } 61 } 62 return kp, nil 63 } 64 65 type InboundDetourAllocationConfig struct { 66 Strategy string `json:"strategy"` 67 Concurrency *uint32 `json:"concurrency"` 68 RefreshMin *uint32 `json:"refresh"` 69 } 70 71 // Build implements Buildable. 72 func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, error) { 73 config := new(proxyman.AllocationStrategy) 74 switch strings.ToLower(c.Strategy) { 75 case "always": 76 config.Type = proxyman.AllocationStrategy_Always 77 case "random": 78 config.Type = proxyman.AllocationStrategy_Random 79 case "external": 80 config.Type = proxyman.AllocationStrategy_External 81 default: 82 return nil, newError("unknown allocation strategy: ", c.Strategy) 83 } 84 if c.Concurrency != nil { 85 config.Concurrency = &proxyman.AllocationStrategy_AllocationStrategyConcurrency{ 86 Value: *c.Concurrency, 87 } 88 } 89 90 if c.RefreshMin != nil { 91 config.Refresh = &proxyman.AllocationStrategy_AllocationStrategyRefresh{ 92 Value: *c.RefreshMin, 93 } 94 } 95 96 return config, nil 97 } 98 99 type InboundDetourConfig struct { 100 Protocol string `json:"protocol"` 101 PortRange *cfgcommon.PortRange `json:"port"` 102 ListenOn *cfgcommon.Address `json:"listen"` 103 Settings *json.RawMessage `json:"settings"` 104 Tag string `json:"tag"` 105 Allocation *InboundDetourAllocationConfig `json:"allocate"` 106 StreamSetting *StreamConfig `json:"streamSettings"` 107 DomainOverride *cfgcommon.StringList `json:"domainOverride"` 108 SniffingConfig *sniffer.SniffingConfig `json:"sniffing"` 109 } 110 111 // Build implements Buildable. 112 func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) { 113 receiverSettings := &proxyman.ReceiverConfig{} 114 115 if c.ListenOn == nil { 116 // Listen on anyip, must set PortRange 117 if c.PortRange == nil { 118 return nil, newError("Listen on AnyIP but no Port(s) set in InboundDetour.") 119 } 120 receiverSettings.PortRange = c.PortRange.Build() 121 } else { 122 // Listen on specific IP or Unix Domain Socket 123 receiverSettings.Listen = c.ListenOn.Build() 124 listenDS := c.ListenOn.Family().IsDomain() && (c.ListenOn.Domain()[0] == '/' || c.ListenOn.Domain()[0] == '@') 125 listenIP := c.ListenOn.Family().IsIP() || (c.ListenOn.Family().IsDomain() && c.ListenOn.Domain() == "localhost") 126 switch { 127 case listenIP: 128 // Listen on specific IP, must set PortRange 129 if c.PortRange == nil { 130 return nil, newError("Listen on specific ip without port in InboundDetour.") 131 } 132 // Listen on IP:Port 133 receiverSettings.PortRange = c.PortRange.Build() 134 case listenDS: 135 if c.PortRange != nil { 136 // Listen on Unix Domain Socket, PortRange should be nil 137 receiverSettings.PortRange = nil 138 } 139 default: 140 return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain()) 141 } 142 } 143 144 if c.Allocation != nil { 145 concurrency := -1 146 if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" { 147 concurrency = int(*c.Allocation.Concurrency) 148 } 149 portRange := int(c.PortRange.To - c.PortRange.From + 1) 150 if concurrency >= 0 && concurrency >= portRange { 151 return nil, newError("not enough ports. concurrency = ", concurrency, " ports: ", c.PortRange.From, " - ", c.PortRange.To) 152 } 153 154 as, err := c.Allocation.Build() 155 if err != nil { 156 return nil, err 157 } 158 receiverSettings.AllocationStrategy = as 159 } 160 if c.StreamSetting != nil { 161 ss, err := c.StreamSetting.Build() 162 if err != nil { 163 return nil, err 164 } 165 receiverSettings.StreamSettings = ss 166 } 167 if c.SniffingConfig != nil { 168 s, err := c.SniffingConfig.Build() 169 if err != nil { 170 return nil, newError("failed to build sniffing config").Base(err) 171 } 172 receiverSettings.SniffingSettings = s 173 } 174 if c.DomainOverride != nil { 175 kp, err := toProtocolList(*c.DomainOverride) 176 if err != nil { 177 return nil, newError("failed to parse inbound detour config").Base(err) 178 } 179 receiverSettings.DomainOverride = kp 180 } 181 182 settings := []byte("{}") 183 if c.Settings != nil { 184 settings = ([]byte)(*c.Settings) 185 } 186 rawConfig, err := inboundConfigLoader.LoadWithID(settings, c.Protocol) 187 if err != nil { 188 return nil, newError("failed to load inbound detour config.").Base(err) 189 } 190 if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok { 191 receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect 192 } 193 ts, err := rawConfig.(cfgcommon.Buildable).Build() 194 if err != nil { 195 return nil, err 196 } 197 198 return &core.InboundHandlerConfig{ 199 Tag: c.Tag, 200 ReceiverSettings: serial.ToTypedMessage(receiverSettings), 201 ProxySettings: serial.ToTypedMessage(ts), 202 }, nil 203 } 204 205 type OutboundDetourConfig struct { 206 Protocol string `json:"protocol"` 207 SendThrough *cfgcommon.Address `json:"sendThrough"` 208 Tag string `json:"tag"` 209 Settings *json.RawMessage `json:"settings"` 210 StreamSetting *StreamConfig `json:"streamSettings"` 211 ProxySettings *proxycfg.ProxyConfig `json:"proxySettings"` 212 MuxSettings *muxcfg.MuxConfig `json:"mux"` 213 DomainStrategy string `json:"domainStrategy"` 214 } 215 216 // Build implements Buildable. 217 func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) { 218 senderSettings := &proxyman.SenderConfig{} 219 220 if c.SendThrough != nil { 221 address := c.SendThrough 222 if address.Family().IsDomain() { 223 return nil, newError("unable to send through: " + address.String()) 224 } 225 senderSettings.Via = address.Build() 226 } 227 228 if c.StreamSetting != nil { 229 ss, err := c.StreamSetting.Build() 230 if err != nil { 231 return nil, err 232 } 233 senderSettings.StreamSettings = ss 234 } 235 236 if c.ProxySettings != nil { 237 ps, err := c.ProxySettings.Build() 238 if err != nil { 239 return nil, newError("invalid outbound detour proxy settings.").Base(err) 240 } 241 senderSettings.ProxySettings = ps 242 } 243 244 if c.MuxSettings != nil { 245 senderSettings.MultiplexSettings = c.MuxSettings.Build() 246 } 247 248 senderSettings.DomainStrategy = proxyman.SenderConfig_AS_IS 249 switch strings.ToLower(c.DomainStrategy) { 250 case "useip", "use_ip", "use-ip": 251 senderSettings.DomainStrategy = proxyman.SenderConfig_USE_IP 252 case "useip4", "useipv4", "use_ip4", "use_ipv4", "use_ip_v4", "use-ip4", "use-ipv4", "use-ip-v4": 253 senderSettings.DomainStrategy = proxyman.SenderConfig_USE_IP4 254 case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6": 255 senderSettings.DomainStrategy = proxyman.SenderConfig_USE_IP6 256 } 257 258 settings := []byte("{}") 259 if c.Settings != nil { 260 settings = ([]byte)(*c.Settings) 261 } 262 rawConfig, err := outboundConfigLoader.LoadWithID(settings, c.Protocol) 263 if err != nil { 264 return nil, newError("failed to parse to outbound detour config.").Base(err) 265 } 266 ts, err := rawConfig.(cfgcommon.Buildable).Build() 267 if err != nil { 268 return nil, err 269 } 270 271 return &core.OutboundHandlerConfig{ 272 SenderSettings: serial.ToTypedMessage(senderSettings), 273 Tag: c.Tag, 274 ProxySettings: serial.ToTypedMessage(ts), 275 }, nil 276 } 277 278 type StatsConfig struct{} 279 280 // Build implements Buildable. 281 func (c *StatsConfig) Build() (*stats.Config, error) { 282 return &stats.Config{}, nil 283 } 284 285 type Config struct { 286 // Port of this Point server. 287 // Deprecated: Port exists for historical compatibility 288 // and should not be used. 289 Port uint16 `json:"port"` 290 291 // Deprecated: InboundConfig exists for historical compatibility 292 // and should not be used. 293 InboundConfig *InboundDetourConfig `json:"inbound"` 294 295 // Deprecated: OutboundConfig exists for historical compatibility 296 // and should not be used. 297 OutboundConfig *OutboundDetourConfig `json:"outbound"` 298 299 // Deprecated: InboundDetours exists for historical compatibility 300 // and should not be used. 301 InboundDetours []InboundDetourConfig `json:"inboundDetour"` 302 303 // Deprecated: OutboundDetours exists for historical compatibility 304 // and should not be used. 305 OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` 306 307 LogConfig *log.LogConfig `json:"log"` 308 RouterConfig *router.RouterConfig `json:"routing"` 309 DNSConfig *dns.DNSConfig `json:"dns"` 310 InboundConfigs []InboundDetourConfig `json:"inbounds"` 311 OutboundConfigs []OutboundDetourConfig `json:"outbounds"` 312 Transport *TransportConfig `json:"transport"` 313 Policy *PolicyConfig `json:"policy"` 314 API *APIConfig `json:"api"` 315 Stats *StatsConfig `json:"stats"` 316 Reverse *ReverseConfig `json:"reverse"` 317 FakeDNS *dns.FakeDNSConfig `json:"fakeDns"` 318 BrowserForwarder *BrowserForwarderConfig `json:"browserForwarder"` 319 Observatory *ObservatoryConfig `json:"observatory"` 320 BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"` 321 MultiObservatory *MultiObservatoryConfig `json:"multiObservatory"` 322 323 Services map[string]*json.RawMessage `json:"services"` 324 } 325 326 func (c *Config) findInboundTag(tag string) int { 327 found := -1 328 for idx, ib := range c.InboundConfigs { 329 if ib.Tag == tag { 330 found = idx 331 break 332 } 333 } 334 return found 335 } 336 337 func (c *Config) findOutboundTag(tag string) int { 338 found := -1 339 for idx, ob := range c.OutboundConfigs { 340 if ob.Tag == tag { 341 found = idx 342 break 343 } 344 } 345 return found 346 } 347 348 func applyTransportConfig(s *StreamConfig, t *TransportConfig) { 349 if s.TCPSettings == nil { 350 s.TCPSettings = t.TCPConfig 351 } 352 if s.KCPSettings == nil { 353 s.KCPSettings = t.KCPConfig 354 } 355 if s.WSSettings == nil { 356 s.WSSettings = t.WSConfig 357 } 358 if s.HTTPSettings == nil { 359 s.HTTPSettings = t.HTTPConfig 360 } 361 if s.DSSettings == nil { 362 s.DSSettings = t.DSConfig 363 } 364 } 365 366 // Build implements Buildable. 367 func (c *Config) Build() (*core.Config, error) { 368 if err := PostProcessConfigureFile(c); err != nil { 369 return nil, err 370 } 371 372 config := &core.Config{ 373 App: []*anypb.Any{ 374 serial.ToTypedMessage(&dispatcher.Config{}), 375 serial.ToTypedMessage(&proxyman.InboundConfig{}), 376 serial.ToTypedMessage(&proxyman.OutboundConfig{}), 377 }, 378 } 379 380 if c.API != nil { 381 apiConf, err := c.API.Build() 382 if err != nil { 383 return nil, err 384 } 385 config.App = append(config.App, serial.ToTypedMessage(apiConf)) 386 } 387 388 if c.Stats != nil { 389 statsConf, err := c.Stats.Build() 390 if err != nil { 391 return nil, err 392 } 393 config.App = append(config.App, serial.ToTypedMessage(statsConf)) 394 } 395 396 var logConfMsg *anypb.Any 397 if c.LogConfig != nil { 398 logConfMsg = serial.ToTypedMessage(c.LogConfig.Build()) 399 } else { 400 logConfMsg = serial.ToTypedMessage(log.DefaultLogConfig()) 401 } 402 // let logger module be the first App to start, 403 // so that other modules could print log during initiating 404 config.App = append([]*anypb.Any{logConfMsg}, config.App...) 405 406 if c.RouterConfig != nil { 407 routerConfig, err := c.RouterConfig.Build() 408 if err != nil { 409 return nil, err 410 } 411 config.App = append(config.App, serial.ToTypedMessage(routerConfig)) 412 } 413 414 if c.FakeDNS != nil { 415 features.PrintDeprecatedFeatureWarning("root fakedns settings") 416 if c.DNSConfig != nil { 417 c.DNSConfig.FakeDNS = c.FakeDNS 418 } else { 419 c.DNSConfig = &dns.DNSConfig{ 420 FakeDNS: c.FakeDNS, 421 } 422 } 423 } 424 425 if c.DNSConfig != nil { 426 dnsApp, err := c.DNSConfig.Build() 427 if err != nil { 428 return nil, newError("failed to parse DNS config").Base(err) 429 } 430 config.App = append(config.App, serial.ToTypedMessage(dnsApp)) 431 } 432 433 if c.Policy != nil { 434 pc, err := c.Policy.Build() 435 if err != nil { 436 return nil, err 437 } 438 config.App = append(config.App, serial.ToTypedMessage(pc)) 439 } 440 441 if c.Reverse != nil { 442 r, err := c.Reverse.Build() 443 if err != nil { 444 return nil, err 445 } 446 config.App = append(config.App, serial.ToTypedMessage(r)) 447 } 448 449 if c.BrowserForwarder != nil { 450 r, err := c.BrowserForwarder.Build() 451 if err != nil { 452 return nil, err 453 } 454 config.App = append(config.App, serial.ToTypedMessage(r)) 455 } 456 457 if c.Observatory != nil { 458 r, err := c.Observatory.Build() 459 if err != nil { 460 return nil, err 461 } 462 config.App = append(config.App, serial.ToTypedMessage(r)) 463 } 464 465 if c.BurstObservatory != nil { 466 r, err := c.BurstObservatory.Build() 467 if err != nil { 468 return nil, err 469 } 470 config.App = append(config.App, serial.ToTypedMessage(r)) 471 } 472 473 if c.MultiObservatory != nil { 474 r, err := c.MultiObservatory.Build() 475 if err != nil { 476 return nil, err 477 } 478 config.App = append(config.App, serial.ToTypedMessage(r)) 479 } 480 481 // Load Additional Services that do not have a json translator 482 483 if msg, err := c.BuildServices(c.Services); err != nil { 484 developererr := newError("Loading a V2Ray Features as a service is intended for developers only. " + 485 "This is used for developers to prototype new features or for an advanced client to use special features in V2Ray," + 486 " instead of allowing end user to enable it without special tool and knowledge.") 487 sb := strings.Builder{} 488 return nil, newError("Cannot load service").Base(developererr).Base(err).Base(newError(sb.String())) 489 } else { // nolint: revive 490 // Using a else here is required to keep msg in scope 491 config.App = append(config.App, msg...) 492 } 493 494 var inbounds []InboundDetourConfig 495 496 if c.InboundConfig != nil { 497 inbounds = append(inbounds, *c.InboundConfig) 498 } 499 500 if len(c.InboundDetours) > 0 { 501 inbounds = append(inbounds, c.InboundDetours...) 502 } 503 504 if len(c.InboundConfigs) > 0 { 505 inbounds = append(inbounds, c.InboundConfigs...) 506 } 507 508 // Backward compatibility. 509 if len(inbounds) > 0 && inbounds[0].PortRange == nil && c.Port > 0 { 510 inbounds[0].PortRange = &cfgcommon.PortRange{ 511 From: uint32(c.Port), 512 To: uint32(c.Port), 513 } 514 } 515 516 for _, rawInboundConfig := range inbounds { 517 if c.Transport != nil { 518 if rawInboundConfig.StreamSetting == nil { 519 rawInboundConfig.StreamSetting = &StreamConfig{} 520 } 521 applyTransportConfig(rawInboundConfig.StreamSetting, c.Transport) 522 } 523 ic, err := rawInboundConfig.Build() 524 if err != nil { 525 return nil, err 526 } 527 config.Inbound = append(config.Inbound, ic) 528 } 529 530 var outbounds []OutboundDetourConfig 531 532 if c.OutboundConfig != nil { 533 outbounds = append(outbounds, *c.OutboundConfig) 534 } 535 536 if len(c.OutboundDetours) > 0 { 537 outbounds = append(outbounds, c.OutboundDetours...) 538 } 539 540 if len(c.OutboundConfigs) > 0 { 541 outbounds = append(outbounds, c.OutboundConfigs...) 542 } 543 544 for _, rawOutboundConfig := range outbounds { 545 if c.Transport != nil { 546 if rawOutboundConfig.StreamSetting == nil { 547 rawOutboundConfig.StreamSetting = &StreamConfig{} 548 } 549 applyTransportConfig(rawOutboundConfig.StreamSetting, c.Transport) 550 } 551 oc, err := rawOutboundConfig.Build() 552 if err != nil { 553 return nil, err 554 } 555 config.Outbound = append(config.Outbound, oc) 556 } 557 558 return config, nil 559 }