mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-22 09:58:14 -05:00
refactor conf
This commit is contained in:
parent
42407d5c62
commit
214324496d
@ -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
|
||||
|
16
conf/cert.go
16
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"`
|
||||
}
|
||||
|
26
conf/conf.go
26
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)
|
||||
}
|
||||
|
@ -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 {}
|
||||
}
|
||||
|
28
conf/core.go
28
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
|
||||
}
|
||||
|
@ -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"`
|
||||
}
|
||||
|
6
conf/log.go
Normal file
6
conf/log.go
Normal file
@ -0,0 +1,6 @@
|
||||
package conf
|
||||
|
||||
type LogConfig struct {
|
||||
Level string `json:"Level"`
|
||||
Output string `json:"Output"`
|
||||
}
|
83
conf/node.go
83
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
|
||||
}
|
||||
|
@ -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"`
|
||||
}
|
41
conf/sing.go
41
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{},
|
||||
}
|
||||
}
|
||||
|
63
conf/xray.go
63
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,
|
||||
}
|
||||
}
|
||||
|
25
core/core.go
25
core/core.go
@ -11,16 +11,19 @@ var (
|
||||
cores = map[string]func(c *conf.CoreConfig) (Core, error){}
|
||||
)
|
||||
|
||||
func NewCore(c *conf.CoreConfig) (Core, error) {
|
||||
// multi core
|
||||
if types := strings.Split(c.Type, " "); len(types) > 1 {
|
||||
var cs []Core
|
||||
for _, t := range types {
|
||||
f, ok := cores[strings.ToLower(t)]
|
||||
if !ok {
|
||||
return nil, errors.New("unknown core type: " + t)
|
||||
func NewCore(c []conf.CoreConfig) (Core, error) {
|
||||
if len(c) < 0 {
|
||||
return nil, errors.New("no have vail core")
|
||||
}
|
||||
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 {
|
||||
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")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -271,3 +271,7 @@ func (b *Box) Protocols() []string {
|
||||
"hysteria",
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Box) Type() string {
|
||||
return "sing"
|
||||
}
|
||||
|
@ -194,3 +194,7 @@ func (c *Core) Protocols() []string {
|
||||
"trojan",
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Core) Type() string {
|
||||
return "xray"
|
||||
}
|
||||
|
65
example/config.json
Normal file
65
example/config.json
Normal 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,
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
@ -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
|
||||
|
14
node/node.go
14
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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user