diff --git a/cmd/server.go b/cmd/server.go index 16aec39..6dae1cf 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -31,7 +31,7 @@ var serverCommand = cobra.Command{ func init() { serverCommand.PersistentFlags(). StringVarP(&config, "config", "c", - "/etc/V2bX/config.yml", "config file path") + "/etc/V2bX/config.json", "config file path") serverCommand.PersistentFlags(). BoolVarP(&watch, "watch", "w", true, "watch file path change") @@ -46,9 +46,19 @@ func serverHandle(_ *cobra.Command, _ []string) { log.WithField("err", err).Error("Load config file failed") return } + switch c.LogConfig.Level { + case "debug": + log.SetLevel(log.DebugLevel) + case "info": + log.SetLevel(log.InfoLevel) + case "warn": + log.SetLevel(log.WarnLevel) + case "error": + log.SetLevel(log.ErrorLevel) + } limiter.Init() log.Info("Start V2bX...") - vc, err := vCore.NewCore(&c.CoreConfig) + vc, err := vCore.NewCore(c.CoresConfig) if err != nil { log.WithField("err", err).Error("new core failed") return @@ -60,7 +70,7 @@ func serverHandle(_ *cobra.Command, _ []string) { } defer vc.Close() nodes := node.New() - err = nodes.Start(c.NodesConfig, vc) + err = nodes.Start(c.NodeConfig, vc) if err != nil { log.WithField("err", err).Error("Run nodes failed") return @@ -74,7 +84,7 @@ func serverHandle(_ *cobra.Command, _ []string) { log.WithField("err", err).Error("Restart node failed") return } - vc, err = vCore.NewCore(&c.CoreConfig) + vc, err = vCore.NewCore(c.CoresConfig) if err != nil { log.WithField("err", err).Error("New core failed") return @@ -84,7 +94,7 @@ func serverHandle(_ *cobra.Command, _ []string) { log.WithField("err", err).Error("Start core failed") return } - err = nodes.Start(c.NodesConfig, vc) + err = nodes.Start(c.NodeConfig, vc) if err != nil { log.WithField("err", err).Error("Run nodes failed") return diff --git a/conf/cert.go b/conf/cert.go index 7ea0014..1f289dc 100644 --- a/conf/cert.go +++ b/conf/cert.go @@ -1,12 +1,12 @@ package conf type CertConfig struct { - CertMode string `yaml:"CertMode"` // none, file, http, dns - RejectUnknownSni bool `yaml:"RejectUnknownSni"` - CertDomain string `yaml:"CertDomain"` - CertFile string `yaml:"CertFile"` - KeyFile string `yaml:"KeyFile"` - Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy.... - Email string `yaml:"Email"` - DNSEnv map[string]string `yaml:"DNSEnv"` + CertMode string `json:"CertMode"` // none, file, http, dns + RejectUnknownSni bool `json:"RejectUnknownSni"` + CertDomain string `json:"CertDomain"` + CertFile string `json:"CertFile"` + KeyFile string `json:"KeyFile"` + Provider string `json:"Provider"` // alidns, cloudflare, gandi, godaddy.... + Email string `json:"Email"` + DNSEnv map[string]string `json:"DNSEnv"` } diff --git a/conf/conf.go b/conf/conf.go index b466bea..d00824b 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -2,25 +2,23 @@ package conf import ( "fmt" - "io" "os" - "gopkg.in/yaml.v3" + "github.com/goccy/go-json" ) type Conf struct { - CoreConfig CoreConfig `yaml:"CoreConfig"` - NodesConfig []*NodeConfig `yaml:"Nodes"` + LogConfig LogConfig `json:"Log"` + CoresConfig []CoreConfig `json:"Cores"` + NodeConfig []NodeConfig `json:"Nodes"` } func New() *Conf { return &Conf{ - CoreConfig: CoreConfig{ - Type: "xray", - XrayConfig: NewXrayConfig(), - SingConfig: NewSingConfig(), + LogConfig: LogConfig{ + Level: "info", + Output: "", }, - NodesConfig: []*NodeConfig{}, } } @@ -30,13 +28,5 @@ func (p *Conf) LoadFromPath(filePath string) error { return fmt.Errorf("open config file error: %s", err) } defer f.Close() - content, err := io.ReadAll(f) - if err != nil { - return fmt.Errorf("read file error: %s", err) - } - err = yaml.Unmarshal(content, p) - if err != nil { - return fmt.Errorf("decode config error: %s", err) - } - return nil + return json.NewDecoder(f).Decode(p) } diff --git a/conf/conf_test.go b/conf/conf_test.go index c466a6c..4349b92 100644 --- a/conf/conf_test.go +++ b/conf/conf_test.go @@ -1,17 +1,16 @@ package conf import ( - "log" - "strings" "testing" ) func TestConf_LoadFromPath(t *testing.T) { c := New() - t.Log(c.LoadFromPath("../example/config.yml.example")) + t.Log(c.LoadFromPath("./config.json"), c.NodeConfig) } func TestConf_Watch(t *testing.T) { - //c := New() - log.Println(strings.Split("aaaa", " ")) + c := New() + t.Log(c.Watch("./1.json", "", func() {})) + select {} } diff --git a/conf/core.go b/conf/core.go index 625a28b..b55bf03 100644 --- a/conf/core.go +++ b/conf/core.go @@ -1,7 +1,29 @@ package conf +import ( + "encoding/json" +) + type CoreConfig struct { - Type string `yaml:"Type"` - XrayConfig *XrayConfig `yaml:"XrayConfig"` - SingConfig *SingConfig `yaml:"SingConfig"` + Type string `json:"Type"` + XrayConfig *XrayConfig `json:"-"` + SingConfig *SingConfig `json:"-"` +} + +type _CoreConfig CoreConfig + +func (c *CoreConfig) UnmarshalJSON(b []byte) error { + err := json.Unmarshal(b, (*_CoreConfig)(c)) + if err != nil { + return err + } + switch c.Type { + case "xray": + c.XrayConfig = NewXrayConfig() + return json.Unmarshal(b, c.XrayConfig) + case "sing": + c.SingConfig = NewSingConfig() + return json.Unmarshal(b, c.SingConfig) + } + return nil } diff --git a/conf/limit.go b/conf/limit.go index b4ce6e3..3d9f4d1 100644 --- a/conf/limit.go +++ b/conf/limit.go @@ -1,40 +1,40 @@ package conf type LimitConfig struct { - EnableRealtime bool `yaml:"EnableRealtime"` - SpeedLimit int `yaml:"SpeedLimit"` - IPLimit int `yaml:"DeviceLimit"` - ConnLimit int `yaml:"ConnLimit"` - EnableIpRecorder bool `yaml:"EnableIpRecorder"` - IpRecorderConfig *IpReportConfig `yaml:"IpRecorderConfig"` - EnableDynamicSpeedLimit bool `yaml:"EnableDynamicSpeedLimit"` - DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `yaml:"DynamicSpeedLimitConfig"` + EnableRealtime bool `json:"EnableRealtime"` + SpeedLimit int `json:"SpeedLimit"` + IPLimit int `json:"DeviceLimit"` + ConnLimit int `json:"ConnLimit"` + EnableIpRecorder bool `json:"EnableIpRecorder"` + IpRecorderConfig *IpReportConfig `json:"IpRecorderConfig"` + EnableDynamicSpeedLimit bool `json:"EnableDynamicSpeedLimit"` + DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `json:"DynamicSpeedLimitConfig"` } type RecorderConfig struct { - Url string `yaml:"Url"` - Token string `yaml:"Token"` - Timeout int `yaml:"Timeout"` + Url string `json:"Url"` + Token string `json:"Token"` + Timeout int `json:"Timeout"` } type RedisConfig struct { - Address string `yaml:"Address"` - Password string `yaml:"Password"` - Db int `yaml:"Db"` + Address string `json:"Address"` + Password string `json:"Password"` + Db int `json:"Db"` Expiry int `json:"Expiry"` } type IpReportConfig struct { - Periodic int `yaml:"Periodic"` - Type string `yaml:"Type"` - RecorderConfig *RecorderConfig `yaml:"RecorderConfig"` - RedisConfig *RedisConfig `yaml:"RedisConfig"` - EnableIpSync bool `yaml:"EnableIpSync"` + Periodic int `json:"Periodic"` + Type string `json:"Type"` + RecorderConfig *RecorderConfig `json:"RecorderConfig"` + RedisConfig *RedisConfig `json:"RedisConfig"` + EnableIpSync bool `json:"EnableIpSync"` } type DynamicSpeedLimitConfig struct { - Periodic int `yaml:"Periodic"` - Traffic int64 `yaml:"Traffic"` - SpeedLimit int `yaml:"SpeedLimit"` - ExpireTime int `yaml:"ExpireTime"` + Periodic int `json:"Periodic"` + Traffic int64 `json:"Traffic"` + SpeedLimit int `json:"SpeedLimit"` + ExpireTime int `json:"ExpireTime"` } diff --git a/conf/log.go b/conf/log.go new file mode 100644 index 0000000..0f580f0 --- /dev/null +++ b/conf/log.go @@ -0,0 +1,6 @@ +package conf + +type LogConfig struct { + Level string `json:"Level"` + Output string `json:"Output"` +} diff --git a/conf/node.go b/conf/node.go index 365f20b..9a5d815 100644 --- a/conf/node.go +++ b/conf/node.go @@ -1,15 +1,82 @@ package conf +import ( + "github.com/goccy/go-json" +) + type NodeConfig struct { - ApiConfig *ApiConfig `yaml:"ApiConfig"` - Options *Options `yaml:"Options"` + ApiConfig ApiConfig `json:"-"` + Options Options `json:"-"` +} + +type rawNodeConfig struct { + ApiRaw *json.RawMessage `json:"ApiConfig"` + OptRaw *json.RawMessage `json:"Options"` } type ApiConfig struct { - APIHost string `yaml:"ApiHost"` - NodeID int `yaml:"NodeID"` - Key string `yaml:"ApiKey"` - NodeType string `yaml:"NodeType"` - Timeout int `yaml:"Timeout"` - RuleListPath string `yaml:"RuleListPath"` + APIHost string `json:"ApiHost"` + NodeID int `json:"NodeID"` + Key string `json:"ApiKey"` + NodeType string `json:"NodeType"` + Timeout int `json:"Timeout"` + RuleListPath string `json:"RuleListPath"` +} + +type Options struct { + Core string `json:"Core"` + ListenIP string `json:"ListenIP"` + SendIP string `json:"SendIP"` + LimitConfig LimitConfig `json:"LimitConfig"` + XrayOptions *XrayOptions `json:"XrayOptions"` + SingOptions *SingOptions `json:"SingOptions"` + CertConfig *CertConfig `json:"CertConfig"` +} + +func (n *NodeConfig) UnmarshalJSON(b []byte) (err error) { + r := rawNodeConfig{} + err = json.Unmarshal(b, &r) + if err != nil { + return err + } + if r.ApiRaw != nil { + err = json.Unmarshal(*r.ApiRaw, &n.ApiConfig) + if err != nil { + return + } + } else { + n.ApiConfig = ApiConfig{ + Timeout: 30, + } + err = json.Unmarshal(b, &n.ApiConfig) + if err != nil { + return + } + } + + if r.OptRaw != nil { + err = json.Unmarshal(*r.OptRaw, &n.Options) + if err != nil { + return + } + } else { + n.Options = Options{ + Core: "xray", + ListenIP: "0.0.0.0", + SendIP: "0.0.0.0", + } + err = json.Unmarshal(b, &n.Options) + if err != nil { + return + } + switch n.Options.Core { + case "xray": + n.Options.XrayOptions = NewXrayOptions() + return json.Unmarshal(b, n.Options.XrayOptions) + case "sing": + n.Options.SingOptions = NewSingOptions() + return json.Unmarshal(b, n.Options.SingOptions) + } + } + return } diff --git a/conf/option.go b/conf/option.go deleted file mode 100644 index a771393..0000000 --- a/conf/option.go +++ /dev/null @@ -1,48 +0,0 @@ -package conf - -type Options struct { - ListenIP string `yaml:"ListenIP"` - SendIP string `yaml:"SendIP"` - LimitConfig LimitConfig `yaml:"LimitConfig"` - CertConfig *CertConfig `yaml:"CertConfig"` - XrayOptions XrayOptions `yaml:"XrayOptions"` - SingOptions SingOptions `yaml:"SingOptions"` -} - -type XrayOptions struct { - EnableProxyProtocol bool `yaml:"EnableProxyProtocol"` - EnableDNS bool `yaml:"EnableDNS"` - DNSType string `yaml:"DNSType"` - EnableUot bool `yaml:"EnableUot"` - EnableTFO bool `yaml:"EnableTFO"` - DisableIVCheck bool `yaml:"DisableIVCheck"` - DisableSniffing bool `yaml:"DisableSniffing"` - EnableFallback bool `yaml:"EnableFallback"` - FallBackConfigs []FallBackConfigForXray `yaml:"FallBackConfigs"` -} - -type SingOptions struct { - EnableProxyProtocol bool `yaml:"EnableProxyProtocol"` - TCPFastOpen bool `yaml:"EnableTFO"` - SniffEnabled bool `yaml:"EnableSniff"` - SniffOverrideDestination bool `yaml:"SniffOverrideDestination"` - FallBackConfigs *FallBackConfigForSing `yaml:"FallBackConfigs"` -} - -type FallBackConfigForXray struct { - SNI string `yaml:"SNI"` - Alpn string `yaml:"Alpn"` - Path string `yaml:"Path"` - Dest string `yaml:"Dest"` - ProxyProtocolVer uint64 `yaml:"ProxyProtocolVer"` -} - -type FallBackConfigForSing struct { - // sing-box - FallBack FallBack `yaml:"FallBack"` - FallBackForALPN map[string]FallBack `yaml:"FallBackForALPN"` -} -type FallBack struct { - Server string `yaml:"Server"` - ServerPort string `yaml:"ServerPort"` -} diff --git a/conf/sing.go b/conf/sing.go index d734642..cdf4159 100644 --- a/conf/sing.go +++ b/conf/sing.go @@ -1,15 +1,15 @@ package conf type SingConfig struct { - LogConfig SingLogConfig `yaml:"LogConfig"` - OriginalPath string `yaml:"OriginalPath"` + LogConfig SingLogConfig `json:"Log"` + OriginalPath string `json:"OriginalPath"` } type SingLogConfig struct { - Disabled bool `yaml:"Disable"` - Level string `yaml:"Level"` - Output string `yaml:"Output"` - Timestamp bool `yaml:"Timestamp"` + Disabled bool `json:"Disable"` + Level string `json:"Level"` + Output string `json:"Output"` + Timestamp bool `json:"Timestamp"` } func NewSingConfig() *SingConfig { @@ -20,3 +20,32 @@ func NewSingConfig() *SingConfig { }, } } + +type SingOptions struct { + EnableProxyProtocol bool `json:"EnableProxyProtocol"` + TCPFastOpen bool `json:"EnableTFO"` + SniffEnabled bool `json:"EnableSniff"` + SniffOverrideDestination bool `json:"SniffOverrideDestination"` + FallBackConfigs *FallBackConfigForSing `json:"FallBackConfigs"` +} + +type FallBackConfigForSing struct { + // sing-box + FallBack FallBack `json:"FallBack"` + FallBackForALPN map[string]FallBack `json:"FallBackForALPN"` +} + +type FallBack struct { + Server string `json:"Server"` + ServerPort string `json:"ServerPort"` +} + +func NewSingOptions() *SingOptions { + return &SingOptions{ + EnableProxyProtocol: false, + TCPFastOpen: false, + SniffEnabled: true, + SniffOverrideDestination: true, + FallBackConfigs: &FallBackConfigForSing{}, + } +} diff --git a/conf/xray.go b/conf/xray.go index d43c60d..a535423 100644 --- a/conf/xray.go +++ b/conf/xray.go @@ -1,27 +1,27 @@ package conf type XrayConfig struct { - LogConfig *XrayLogConfig `yaml:"Log"` - AssetPath string `yaml:"AssetPath"` - DnsConfigPath string `yaml:"DnsConfigPath"` - RouteConfigPath string `yaml:"RouteConfigPath"` - ConnectionConfig *XrayConnectionConfig `yaml:"XrayConnectionConfig"` - InboundConfigPath string `yaml:"InboundConfigPath"` - OutboundConfigPath string `yaml:"OutboundConfigPath"` + LogConfig *XrayLogConfig `json:"Log"` + AssetPath string `json:"AssetPath"` + DnsConfigPath string `json:"DnsConfigPath"` + RouteConfigPath string `json:"RouteConfigPath"` + ConnectionConfig *XrayConnectionConfig `json:"XrayConnectionConfig"` + InboundConfigPath string `json:"InboundConfigPath"` + OutboundConfigPath string `json:"OutboundConfigPath"` } type XrayLogConfig struct { - Level string `yaml:"Level"` - AccessPath string `yaml:"AccessPath"` - ErrorPath string `yaml:"ErrorPath"` + Level string `json:"Level"` + AccessPath string `json:"AccessPath"` + ErrorPath string `json:"ErrorPath"` } type XrayConnectionConfig struct { - Handshake uint32 `yaml:"handshake"` - ConnIdle uint32 `yaml:"connIdle"` - UplinkOnly uint32 `yaml:"uplinkOnly"` - DownlinkOnly uint32 `yaml:"downlinkOnly"` - BufferSize int32 `yaml:"bufferSize"` + Handshake uint32 `json:"handshake"` + ConnIdle uint32 `json:"connIdle"` + UplinkOnly uint32 `json:"uplinkOnly"` + DownlinkOnly uint32 `json:"downlinkOnly"` + BufferSize int32 `json:"bufferSize"` } func NewXrayConfig() *XrayConfig { @@ -45,3 +45,36 @@ func NewXrayConfig() *XrayConfig { }, } } + +type XrayOptions struct { + EnableProxyProtocol bool `json:"EnableProxyProtocol"` + EnableDNS bool `json:"EnableDNS"` + DNSType string `json:"DNSType"` + EnableUot bool `json:"EnableUot"` + EnableTFO bool `json:"EnableTFO"` + DisableIVCheck bool `json:"DisableIVCheck"` + DisableSniffing bool `json:"DisableSniffing"` + EnableFallback bool `json:"EnableFallback"` + FallBackConfigs []FallBackConfigForXray `json:"FallBackConfigs"` +} + +type FallBackConfigForXray struct { + SNI string `json:"SNI"` + Alpn string `json:"Alpn"` + Path string `json:"Path"` + Dest string `json:"Dest"` + ProxyProtocolVer uint64 `json:"ProxyProtocolVer"` +} + +func NewXrayOptions() *XrayOptions { + return &XrayOptions{ + EnableProxyProtocol: false, + EnableDNS: false, + DNSType: "AsIs", + EnableUot: false, + EnableTFO: false, + DisableIVCheck: false, + DisableSniffing: false, + EnableFallback: false, + } +} diff --git a/core/core.go b/core/core.go index dbaabea..618282f 100644 --- a/core/core.go +++ b/core/core.go @@ -11,16 +11,19 @@ var ( cores = map[string]func(c *conf.CoreConfig) (Core, error){} ) -func NewCore(c *conf.CoreConfig) (Core, error) { +func NewCore(c []conf.CoreConfig) (Core, error) { + if len(c) < 0 { + return nil, errors.New("no have vail core") + } // multi core - if types := strings.Split(c.Type, " "); len(types) > 1 { + if len(c) > 1 { var cs []Core - for _, t := range types { - f, ok := cores[strings.ToLower(t)] + for _, t := range c { + f, ok := cores[strings.ToLower(t.Type)] if !ok { - return nil, errors.New("unknown core type: " + t) + return nil, errors.New("unknown core type: " + t.Type) } - core1, err := f(c) + core1, err := f(&t) if err != nil { return nil, err } @@ -31,8 +34,8 @@ func NewCore(c *conf.CoreConfig) (Core, error) { }, nil } // one core - if f, ok := cores[strings.ToLower(c.Type)]; ok { - return f(c) + if f, ok := cores[c[0].Type]; ok { + return f(&c[0]) } else { return nil, errors.New("unknown core type") } diff --git a/core/interface.go b/core/interface.go index cfd593a..464baa0 100644 --- a/core/interface.go +++ b/core/interface.go @@ -20,4 +20,5 @@ type Core interface { GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) DelUsers(users []panel.UserInfo, tag string) error Protocols() []string + Type() string } diff --git a/core/selector.go b/core/selector.go index 9c729cc..ebc0bad 100644 --- a/core/selector.go +++ b/core/selector.go @@ -39,12 +39,12 @@ func isSupported(protocol string, protocols []string) bool { return false } -func (s *Selector) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error { +func (s *Selector) AddNode(tag string, info *panel.NodeInfo, option *conf.Options) error { for i := range s.cores { - if !isSupported(info.Type, s.cores[i].Protocols()) { + if option.Core != s.cores[i].Type() { continue } - err := s.cores[i].AddNode(tag, info, config) + err := s.cores[i].AddNode(tag, info, option) if err != nil { return err } @@ -97,3 +97,7 @@ func (s *Selector) Protocols() []string { } return protocols } + +func (s *Selector) Type() string { + return "selector" +} diff --git a/core/sing/sing.go b/core/sing/sing.go index 61f7564..c40bc31 100644 --- a/core/sing/sing.go +++ b/core/sing/sing.go @@ -271,3 +271,7 @@ func (b *Box) Protocols() []string { "hysteria", } } + +func (b *Box) Type() string { + return "sing" +} diff --git a/core/xray/xray.go b/core/xray/xray.go index 71a4ca7..659856f 100644 --- a/core/xray/xray.go +++ b/core/xray/xray.go @@ -194,3 +194,7 @@ func (c *Core) Protocols() []string { "trojan", } } + +func (c *Core) Type() string { + return "xray" +} diff --git a/example/config.json b/example/config.json new file mode 100644 index 0000000..c29d2e1 --- /dev/null +++ b/example/config.json @@ -0,0 +1,65 @@ +{ + "Log": { + "Level": "error" + }, + "Cores": [ + { + "Type": "sing", + "Log": { + "Level": "error", + "Timestamp": true + } + },{ + "Type": "xray", + "Log": { + "Level": "error" + }, + "DnsConfigPath": "", + ... + } + ], + "Nodes": [ + { + "Core": "sing", + "ApiHost": "http://127.0.0.1", + "ApiKey": "test", + "NodeID": 33, + "NodeType": "shadowsocks", + "Timeout": 30, + "RuleListPath": "", + "ListenIP": "0.0.0.0", + "SendIP": "0.0.0.0", + "EnableProxyProtocol": true, + "EnableTFO": true, + ... + },{ + "ApiConfig": { + "ApiHost": "http://127.0.0.1", + "ApiKey": "test", + "NodeID": 33, + "Timeout": 30, + "RuleListPath": "" + }, + "Options": { + "Core": "sing", + "EnableProxyProtocol": true, + "EnableTFO": true, + ... + } + }, + { + "Core": "xray", + "ApiHost": "http://127.0.0.1", + "ApiKey": "test", + "NodeID": 33, + "NodeType": "shadowsocks", + "Timeout": 30, + "RuleListPath": "", + "ListenIP": "0.0.0.0", + "SendIP": "0.0.0.0", + "EnableProxyProtocol": true, + "EnableTFO": true, + ... + } + ] +} \ No newline at end of file diff --git a/example/config.yml.example b/example/config.yml.example deleted file mode 100644 index 04959fe..0000000 --- a/example/config.yml.example +++ /dev/null @@ -1,130 +0,0 @@ -CoreConfig: - Type: "xray" # Core type, default support "xray" and "hy". If you need many cores, use " " to split - XrayConfig: - Log: - Level: warning # Log level: none, error, warning, info, debug - AccessPath: # /etc/XrayR/access.Log - ErrorPath: # /etc/XrayR/error.log - DnsConfigPath: # /etc/XrayR/dns.json # Path to dns config, check https://xtls.github.io/config/dns.html for help - RouteConfigPath: # /etc/XrayR/route.json # Path to route config, check https://xtls.github.io/config/routing.html for help - InboundConfigPath: # /etc/XrayR/custom_inbound.json # Path to custom inbound config, check https://xtls.github.io/config/inbound.html for help - OutboundConfigPath: # /etc/XrayR/custom_outbound.json # Path to custom outbound config, check https://xtls.github.io/config/outbound.html for help - ConnectionConfig: - Handshake: 4 # Handshake time limit, Second - ConnIdle: 30 # Connection idle time limit, Second - UplinkOnly: 2 # Time limit when the connection downstream is closed, Second - DownlinkOnly: 4 # Time limit when the connection is closed after the uplink is closed, Second - BufferSize: 64 # The internal cache size of each connection, kB -Nodes: - - ApiConfig: - ApiHost: "http://127.0.0.1:667" - ApiKey: "123" - NodeID: 41 - NodeType: V2ray # Node type: V2ray, Shadowsocks, Trojan - Timeout: 30 # Timeout for the api request - RuleListPath: # /etc/XrayR/rulelist Path to local rulelist file - ControllerConfig: - ListenIP: 0.0.0.0 # IP address you want to listen - SendIP: 0.0.0.0 # IP address you want to send pacakage - XrayOptions: - EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well - DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy - EnableTFO: false # Enable TCP Fast Open - EnableProxyProtocol: false # Only works for WebSocket and TCP - EnableFallback: false # Only support for Trojan and Vless - FallBackConfigs: # Support multiple fallbacks - - SNI: # TLS SNI(Server Name Indication), Empty for any - Alpn: # Alpn, Empty for any - Path: # HTTP PATH, Empty for any - Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details. - ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable - SingOptions: - EnableTFO: true - SniffEnabled: true - SniffOverrideDestination: true - EnableProxyProtocol: false - FallBackConfigs: - FallBack: - Server: 127.0.0.1 - ServerPort: 8080 - FallBackForALPN: - http/1.1: - Server: 127.0.0.1 - ServerPort: 8081 - HyOptions: - Resolver: "udp://1.1.1.1:53" # DNS resolver address - ResolvePreference: 64 # DNS IPv4/IPv6 preference. Available options: "64" (IPv6 first, fallback to IPv4), "46" (IPv4 first, fallback to IPv6), "6" (IPv6 only), "4" (IPv4 only) - SendDevice: "eth0" # Bind device for outbound connections (usually requires root) - LimitConfig: - EnableRealtime: false # Check device limit on real time - SpeedLimit: 0 # Mbps, Local settings will replace remote settings, 0 means disable - DeviceLimit: 0 # Local settings will replace remote settings, 0 means disable - ConnLimit: 0 # Connecting limit, only working for TCP, 0mean - EnableIpRecorder: false # Enable online ip report - IpRecorderConfig: - Type: "Recorder" # Recorder type: Recorder, Redis - RecorderConfig: - Url: "http://127.0.0.1:123" # Report url - Token: "123" # Report token - Timeout: 10 # Report timeout, sec. - RedisConfig: - Address: "127.0.0.1:6379" # Redis address - Password: "" # Redis password - DB: 0 # Redis DB - Expiry: 60 # redis expiry time, sec. - Periodic: 60 # Report interval, sec. - EnableIpSync: false # Enable online ip sync - EnableDynamicSpeedLimit: false # Enable dynamic speed limit - DynamicSpeedLimitConfig: - Periodic: 60 # Time to check the user traffic , sec. - Traffic: 0 # Traffic limit, MB - SpeedLimit: 0 # Speed limit, Mbps - ExpireTime: 0 # Time limit, sec. - CertConfig: - CertMode: dns # Option about how to get certificate: none, file, http, dns, reality, remote. Choose "none" will forcedly disable the tls config. - CertDomain: "node1.test.com" # Domain to cert - CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file - KeyFile: /etc/XrayR/cert/node1.test.com.key - Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ - Email: test@me.com - DNSEnv: # DNS ENV option used by DNS provider - ALICLOUD_ACCESS_KEY: aaa - ALICLOUD_SECRET_KEY: bbb - RealityConfig: # This config like RealityObject for xray-core, please check https://xtls.github.io/config/transport.html#realityobject - Dest: 80 # Same fallback dest - Xver: 0 # Same fallback xver - ServerNames: - - "example.com" - - "www.example.com" - PrivateKey: "" # Private key for server - MinClientVer: "" # Min client version - MaxClientVer: "" # Max client version - MaxTimeDiff: 0 # Max time difference, ms - ShortIds: # Short ids - - "" - - "0123456789abcdef" - # - - # ApiConfig: - # ApiHost: "http://127.0.0.1:668" - # ApiKey: "123" - # NodeID: 4 - # NodeType: Shadowsocks # Node type: V2ray, Shadowsocks, Trojan - # Timeout: 30 # Timeout for the api request - # EnableVless: false # Enable Vless for V2ray Type - # EnableXTLS: false # Enable XTLS for V2ray and Trojan - # SpeedLimit: 0 # Mbps, Local settings will replace remote settings - # DeviceLimit: 0 # Local settings will replace remote settings - # ControllerConfig: - # ListenIP: 0.0.0.0 # IP address you want to listen - # EnableDNS: false # Use custom DNS config, Please ensure that you set the dns.json well - # CertConfig: - # CertMode: dns # Option about how to get certificate: none, file, http, dns - # CertDomain: "node1.test.com" # Domain to cert - # CertFile: /etc/XrayR/cert/node1.test.com.cert # Provided if the CertMode is file - # KeyFile: /etc/XrayR/cert/node1.test.com.pem - # Provider: alidns # DNS cert provider, Get the full support list here: https://go-acme.github.io/lego/dns/ - # Email: test@me.com - # DNSEnv: # DNS ENV option used by DNS provider - # ALICLOUD_ACCESS_KEY: aaa - # ALICLOUD_SECRET_KEY: bbb - diff --git a/node/node.go b/node/node.go index d714df2..f8a4738 100644 --- a/node/node.go +++ b/node/node.go @@ -16,21 +16,21 @@ func New() *Node { return &Node{} } -func (n *Node) Start(nodes []*conf.NodeConfig, core vCore.Core) error { +func (n *Node) Start(nodes []conf.NodeConfig, core vCore.Core) error { n.controllers = make([]*Controller, len(nodes)) - for i, c := range nodes { - p, err := panel.New(c.ApiConfig) + for i := range nodes { + p, err := panel.New(&nodes[i].ApiConfig) if err != nil { return err } // Register controller service - n.controllers[i] = NewController(core, p, c.Options) + n.controllers[i] = NewController(core, p, &nodes[i].Options) err = n.controllers[i].Start() if err != nil { return fmt.Errorf("start node controller [%s-%s-%d] error: %s", - c.ApiConfig.APIHost, - c.ApiConfig.NodeType, - c.ApiConfig.NodeID, + nodes[i].ApiConfig.APIHost, + nodes[i].ApiConfig.NodeType, + nodes[i].ApiConfig.NodeID, err) } }