refactor conf

This commit is contained in:
Yuzuki616 2023-08-20 15:13:52 +08:00
parent 42407d5c62
commit 214324496d
19 changed files with 346 additions and 287 deletions

View File

@ -31,7 +31,7 @@ var serverCommand = cobra.Command{
func init() { func init() {
serverCommand.PersistentFlags(). serverCommand.PersistentFlags().
StringVarP(&config, "config", "c", StringVarP(&config, "config", "c",
"/etc/V2bX/config.yml", "config file path") "/etc/V2bX/config.json", "config file path")
serverCommand.PersistentFlags(). serverCommand.PersistentFlags().
BoolVarP(&watch, "watch", "w", BoolVarP(&watch, "watch", "w",
true, "watch file path change") true, "watch file path change")
@ -46,9 +46,19 @@ func serverHandle(_ *cobra.Command, _ []string) {
log.WithField("err", err).Error("Load config file failed") log.WithField("err", err).Error("Load config file failed")
return 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() limiter.Init()
log.Info("Start V2bX...") log.Info("Start V2bX...")
vc, err := vCore.NewCore(&c.CoreConfig) vc, err := vCore.NewCore(c.CoresConfig)
if err != nil { if err != nil {
log.WithField("err", err).Error("new core failed") log.WithField("err", err).Error("new core failed")
return return
@ -60,7 +70,7 @@ func serverHandle(_ *cobra.Command, _ []string) {
} }
defer vc.Close() defer vc.Close()
nodes := node.New() nodes := node.New()
err = nodes.Start(c.NodesConfig, vc) err = nodes.Start(c.NodeConfig, vc)
if err != nil { if err != nil {
log.WithField("err", err).Error("Run nodes failed") log.WithField("err", err).Error("Run nodes failed")
return return
@ -74,7 +84,7 @@ func serverHandle(_ *cobra.Command, _ []string) {
log.WithField("err", err).Error("Restart node failed") log.WithField("err", err).Error("Restart node failed")
return return
} }
vc, err = vCore.NewCore(&c.CoreConfig) vc, err = vCore.NewCore(c.CoresConfig)
if err != nil { if err != nil {
log.WithField("err", err).Error("New core failed") log.WithField("err", err).Error("New core failed")
return return
@ -84,7 +94,7 @@ func serverHandle(_ *cobra.Command, _ []string) {
log.WithField("err", err).Error("Start core failed") log.WithField("err", err).Error("Start core failed")
return return
} }
err = nodes.Start(c.NodesConfig, vc) err = nodes.Start(c.NodeConfig, vc)
if err != nil { if err != nil {
log.WithField("err", err).Error("Run nodes failed") log.WithField("err", err).Error("Run nodes failed")
return return

View File

@ -1,12 +1,12 @@
package conf package conf
type CertConfig struct { type CertConfig struct {
CertMode string `yaml:"CertMode"` // none, file, http, dns CertMode string `json:"CertMode"` // none, file, http, dns
RejectUnknownSni bool `yaml:"RejectUnknownSni"` RejectUnknownSni bool `json:"RejectUnknownSni"`
CertDomain string `yaml:"CertDomain"` CertDomain string `json:"CertDomain"`
CertFile string `yaml:"CertFile"` CertFile string `json:"CertFile"`
KeyFile string `yaml:"KeyFile"` KeyFile string `json:"KeyFile"`
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy.... Provider string `json:"Provider"` // alidns, cloudflare, gandi, godaddy....
Email string `yaml:"Email"` Email string `json:"Email"`
DNSEnv map[string]string `yaml:"DNSEnv"` DNSEnv map[string]string `json:"DNSEnv"`
} }

View File

@ -2,25 +2,23 @@ package conf
import ( import (
"fmt" "fmt"
"io"
"os" "os"
"gopkg.in/yaml.v3" "github.com/goccy/go-json"
) )
type Conf struct { type Conf struct {
CoreConfig CoreConfig `yaml:"CoreConfig"` LogConfig LogConfig `json:"Log"`
NodesConfig []*NodeConfig `yaml:"Nodes"` CoresConfig []CoreConfig `json:"Cores"`
NodeConfig []NodeConfig `json:"Nodes"`
} }
func New() *Conf { func New() *Conf {
return &Conf{ return &Conf{
CoreConfig: CoreConfig{ LogConfig: LogConfig{
Type: "xray", Level: "info",
XrayConfig: NewXrayConfig(), Output: "",
SingConfig: NewSingConfig(),
}, },
NodesConfig: []*NodeConfig{},
} }
} }
@ -30,13 +28,5 @@ func (p *Conf) LoadFromPath(filePath string) error {
return fmt.Errorf("open config file error: %s", err) return fmt.Errorf("open config file error: %s", err)
} }
defer f.Close() defer f.Close()
content, err := io.ReadAll(f) return json.NewDecoder(f).Decode(p)
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
} }

View File

@ -1,17 +1,16 @@
package conf package conf
import ( import (
"log"
"strings"
"testing" "testing"
) )
func TestConf_LoadFromPath(t *testing.T) { func TestConf_LoadFromPath(t *testing.T) {
c := New() c := New()
t.Log(c.LoadFromPath("../example/config.yml.example")) t.Log(c.LoadFromPath("./config.json"), c.NodeConfig)
} }
func TestConf_Watch(t *testing.T) { func TestConf_Watch(t *testing.T) {
//c := New() c := New()
log.Println(strings.Split("aaaa", " ")) t.Log(c.Watch("./1.json", "", func() {}))
select {}
} }

View File

@ -1,7 +1,29 @@
package conf package conf
import (
"encoding/json"
)
type CoreConfig struct { type CoreConfig struct {
Type string `yaml:"Type"` Type string `json:"Type"`
XrayConfig *XrayConfig `yaml:"XrayConfig"` XrayConfig *XrayConfig `json:"-"`
SingConfig *SingConfig `yaml:"SingConfig"` 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
} }

View File

@ -1,40 +1,40 @@
package conf package conf
type LimitConfig struct { type LimitConfig struct {
EnableRealtime bool `yaml:"EnableRealtime"` EnableRealtime bool `json:"EnableRealtime"`
SpeedLimit int `yaml:"SpeedLimit"` SpeedLimit int `json:"SpeedLimit"`
IPLimit int `yaml:"DeviceLimit"` IPLimit int `json:"DeviceLimit"`
ConnLimit int `yaml:"ConnLimit"` ConnLimit int `json:"ConnLimit"`
EnableIpRecorder bool `yaml:"EnableIpRecorder"` EnableIpRecorder bool `json:"EnableIpRecorder"`
IpRecorderConfig *IpReportConfig `yaml:"IpRecorderConfig"` IpRecorderConfig *IpReportConfig `json:"IpRecorderConfig"`
EnableDynamicSpeedLimit bool `yaml:"EnableDynamicSpeedLimit"` EnableDynamicSpeedLimit bool `json:"EnableDynamicSpeedLimit"`
DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `yaml:"DynamicSpeedLimitConfig"` DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `json:"DynamicSpeedLimitConfig"`
} }
type RecorderConfig struct { type RecorderConfig struct {
Url string `yaml:"Url"` Url string `json:"Url"`
Token string `yaml:"Token"` Token string `json:"Token"`
Timeout int `yaml:"Timeout"` Timeout int `json:"Timeout"`
} }
type RedisConfig struct { type RedisConfig struct {
Address string `yaml:"Address"` Address string `json:"Address"`
Password string `yaml:"Password"` Password string `json:"Password"`
Db int `yaml:"Db"` Db int `json:"Db"`
Expiry int `json:"Expiry"` Expiry int `json:"Expiry"`
} }
type IpReportConfig struct { type IpReportConfig struct {
Periodic int `yaml:"Periodic"` Periodic int `json:"Periodic"`
Type string `yaml:"Type"` Type string `json:"Type"`
RecorderConfig *RecorderConfig `yaml:"RecorderConfig"` RecorderConfig *RecorderConfig `json:"RecorderConfig"`
RedisConfig *RedisConfig `yaml:"RedisConfig"` RedisConfig *RedisConfig `json:"RedisConfig"`
EnableIpSync bool `yaml:"EnableIpSync"` EnableIpSync bool `json:"EnableIpSync"`
} }
type DynamicSpeedLimitConfig struct { type DynamicSpeedLimitConfig struct {
Periodic int `yaml:"Periodic"` Periodic int `json:"Periodic"`
Traffic int64 `yaml:"Traffic"` Traffic int64 `json:"Traffic"`
SpeedLimit int `yaml:"SpeedLimit"` SpeedLimit int `json:"SpeedLimit"`
ExpireTime int `yaml:"ExpireTime"` ExpireTime int `json:"ExpireTime"`
} }

6
conf/log.go Normal file
View File

@ -0,0 +1,6 @@
package conf
type LogConfig struct {
Level string `json:"Level"`
Output string `json:"Output"`
}

View File

@ -1,15 +1,82 @@
package conf package conf
import (
"github.com/goccy/go-json"
)
type NodeConfig struct { type NodeConfig struct {
ApiConfig *ApiConfig `yaml:"ApiConfig"` ApiConfig ApiConfig `json:"-"`
Options *Options `yaml:"Options"` Options Options `json:"-"`
}
type rawNodeConfig struct {
ApiRaw *json.RawMessage `json:"ApiConfig"`
OptRaw *json.RawMessage `json:"Options"`
} }
type ApiConfig struct { type ApiConfig struct {
APIHost string `yaml:"ApiHost"` APIHost string `json:"ApiHost"`
NodeID int `yaml:"NodeID"` NodeID int `json:"NodeID"`
Key string `yaml:"ApiKey"` Key string `json:"ApiKey"`
NodeType string `yaml:"NodeType"` NodeType string `json:"NodeType"`
Timeout int `yaml:"Timeout"` Timeout int `json:"Timeout"`
RuleListPath string `yaml:"RuleListPath"` 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
} }

View File

@ -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"`
}

View File

@ -1,15 +1,15 @@
package conf package conf
type SingConfig struct { type SingConfig struct {
LogConfig SingLogConfig `yaml:"LogConfig"` LogConfig SingLogConfig `json:"Log"`
OriginalPath string `yaml:"OriginalPath"` OriginalPath string `json:"OriginalPath"`
} }
type SingLogConfig struct { type SingLogConfig struct {
Disabled bool `yaml:"Disable"` Disabled bool `json:"Disable"`
Level string `yaml:"Level"` Level string `json:"Level"`
Output string `yaml:"Output"` Output string `json:"Output"`
Timestamp bool `yaml:"Timestamp"` Timestamp bool `json:"Timestamp"`
} }
func NewSingConfig() *SingConfig { 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{},
}
}

View File

@ -1,27 +1,27 @@
package conf package conf
type XrayConfig struct { type XrayConfig struct {
LogConfig *XrayLogConfig `yaml:"Log"` LogConfig *XrayLogConfig `json:"Log"`
AssetPath string `yaml:"AssetPath"` AssetPath string `json:"AssetPath"`
DnsConfigPath string `yaml:"DnsConfigPath"` DnsConfigPath string `json:"DnsConfigPath"`
RouteConfigPath string `yaml:"RouteConfigPath"` RouteConfigPath string `json:"RouteConfigPath"`
ConnectionConfig *XrayConnectionConfig `yaml:"XrayConnectionConfig"` ConnectionConfig *XrayConnectionConfig `json:"XrayConnectionConfig"`
InboundConfigPath string `yaml:"InboundConfigPath"` InboundConfigPath string `json:"InboundConfigPath"`
OutboundConfigPath string `yaml:"OutboundConfigPath"` OutboundConfigPath string `json:"OutboundConfigPath"`
} }
type XrayLogConfig struct { type XrayLogConfig struct {
Level string `yaml:"Level"` Level string `json:"Level"`
AccessPath string `yaml:"AccessPath"` AccessPath string `json:"AccessPath"`
ErrorPath string `yaml:"ErrorPath"` ErrorPath string `json:"ErrorPath"`
} }
type XrayConnectionConfig struct { type XrayConnectionConfig struct {
Handshake uint32 `yaml:"handshake"` Handshake uint32 `json:"handshake"`
ConnIdle uint32 `yaml:"connIdle"` ConnIdle uint32 `json:"connIdle"`
UplinkOnly uint32 `yaml:"uplinkOnly"` UplinkOnly uint32 `json:"uplinkOnly"`
DownlinkOnly uint32 `yaml:"downlinkOnly"` DownlinkOnly uint32 `json:"downlinkOnly"`
BufferSize int32 `yaml:"bufferSize"` BufferSize int32 `json:"bufferSize"`
} }
func NewXrayConfig() *XrayConfig { 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,
}
}

View File

@ -11,16 +11,19 @@ var (
cores = map[string]func(c *conf.CoreConfig) (Core, error){} cores = map[string]func(c *conf.CoreConfig) (Core, error){}
) )
func NewCore(c *conf.CoreConfig) (Core, error) { func NewCore(c []conf.CoreConfig) (Core, error) {
// multi core if len(c) < 0 {
if types := strings.Split(c.Type, " "); len(types) > 1 { return nil, errors.New("no have vail core")
var cs []Core
for _, t := range types {
f, ok := cores[strings.ToLower(t)]
if !ok {
return nil, errors.New("unknown core type: " + t)
} }
core1, err := f(c) // multi core
if len(c) > 1 {
var cs []Core
for _, t := range c {
f, ok := cores[strings.ToLower(t.Type)]
if !ok {
return nil, errors.New("unknown core type: " + t.Type)
}
core1, err := f(&t)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -31,8 +34,8 @@ func NewCore(c *conf.CoreConfig) (Core, error) {
}, nil }, nil
} }
// one core // one core
if f, ok := cores[strings.ToLower(c.Type)]; ok { if f, ok := cores[c[0].Type]; ok {
return f(c) return f(&c[0])
} else { } else {
return nil, errors.New("unknown core type") return nil, errors.New("unknown core type")
} }

View File

@ -20,4 +20,5 @@ type Core interface {
GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64)
DelUsers(users []panel.UserInfo, tag string) error DelUsers(users []panel.UserInfo, tag string) error
Protocols() []string Protocols() []string
Type() string
} }

View File

@ -39,12 +39,12 @@ func isSupported(protocol string, protocols []string) bool {
return false 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 { for i := range s.cores {
if !isSupported(info.Type, s.cores[i].Protocols()) { if option.Core != s.cores[i].Type() {
continue continue
} }
err := s.cores[i].AddNode(tag, info, config) err := s.cores[i].AddNode(tag, info, option)
if err != nil { if err != nil {
return err return err
} }
@ -97,3 +97,7 @@ func (s *Selector) Protocols() []string {
} }
return protocols return protocols
} }
func (s *Selector) Type() string {
return "selector"
}

View File

@ -271,3 +271,7 @@ func (b *Box) Protocols() []string {
"hysteria", "hysteria",
} }
} }
func (b *Box) Type() string {
return "sing"
}

View File

@ -194,3 +194,7 @@ func (c *Core) Protocols() []string {
"trojan", "trojan",
} }
} }
func (c *Core) Type() string {
return "xray"
}

65
example/config.json Normal file
View File

@ -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,
...
}
]
}

View File

@ -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

View File

@ -16,21 +16,21 @@ func New() *Node {
return &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)) n.controllers = make([]*Controller, len(nodes))
for i, c := range nodes { for i := range nodes {
p, err := panel.New(c.ApiConfig) p, err := panel.New(&nodes[i].ApiConfig)
if err != nil { if err != nil {
return err return err
} }
// Register controller service // 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() err = n.controllers[i].Start()
if err != nil { if err != nil {
return fmt.Errorf("start node controller [%s-%s-%d] error: %s", return fmt.Errorf("start node controller [%s-%s-%d] error: %s",
c.ApiConfig.APIHost, nodes[i].ApiConfig.APIHost,
c.ApiConfig.NodeType, nodes[i].ApiConfig.NodeType,
c.ApiConfig.NodeID, nodes[i].ApiConfig.NodeID,
err) err)
} }
} }