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() {
|
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
|
||||||
|
16
conf/cert.go
16
conf/cert.go
@ -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"`
|
||||||
}
|
}
|
||||||
|
26
conf/conf.go
26
conf/conf.go
@ -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
|
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
||||||
}
|
}
|
||||||
|
28
conf/core.go
28
conf/core.go
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
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
|
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
|
||||||
}
|
}
|
||||||
|
@ -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
|
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{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
63
conf/xray.go
63
conf/xray.go
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
19
core/core.go
19
core/core.go
@ -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) {
|
||||||
|
if len(c) < 0 {
|
||||||
|
return nil, errors.New("no have vail core")
|
||||||
|
}
|
||||||
// multi core
|
// multi core
|
||||||
if types := strings.Split(c.Type, " "); len(types) > 1 {
|
if len(c) > 1 {
|
||||||
var cs []Core
|
var cs []Core
|
||||||
for _, t := range types {
|
for _, t := range c {
|
||||||
f, ok := cores[strings.ToLower(t)]
|
f, ok := cores[strings.ToLower(t.Type)]
|
||||||
if !ok {
|
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 {
|
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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
}
|
||||||
|
@ -271,3 +271,7 @@ func (b *Box) Protocols() []string {
|
|||||||
"hysteria",
|
"hysteria",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Box) Type() string {
|
||||||
|
return "sing"
|
||||||
|
}
|
||||||
|
@ -194,3 +194,7 @@ func (c *Core) Protocols() []string {
|
|||||||
"trojan",
|
"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{}
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user