From c4eb73da49e02896aa8ed333cb628cf37fa325e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 04:07:24 +0000 Subject: [PATCH 01/21] Bump github.com/apernet/hysteria/core from 1.3.4 to 1.3.5 Bumps [github.com/apernet/hysteria/core](https://github.com/apernet/hysteria) from 1.3.4 to 1.3.5. - [Release notes](https://github.com/apernet/hysteria/releases) - [Changelog](https://github.com/apernet/hysteria/blob/master/CHANGELOG.md) - [Commits](https://github.com/apernet/hysteria/compare/v1.3.4...v1.3.5) --- updated-dependencies: - dependency-name: github.com/apernet/hysteria/core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index fbc0667..dbc3af2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Yuzuki616/V2bX go 1.20 require ( - github.com/apernet/hysteria/core v1.3.4 + github.com/apernet/hysteria/core v1.3.5 github.com/beevik/ntp v1.0.0 github.com/folbricht/routedns v0.1.21-0.20230220022436-4ae86ce30d53 github.com/fsnotify/fsnotify v1.6.0 @@ -14,7 +14,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/juju/ratelimit v1.0.2 github.com/oschwald/geoip2-golang v1.8.0 - github.com/quic-go/quic-go v0.33.0 + github.com/quic-go/quic-go v0.34.0 github.com/sagernet/sing-box v1.2.7 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 diff --git a/go.sum b/go.sum index d36cc2e..175584c 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apernet/hysteria/core v1.3.4 h1:i5EqGIf7FZqwsOrT7PagLQeh+P5gHfLkDZWn7/pXUjo= -github.com/apernet/hysteria/core v1.3.4/go.mod h1:WxFihvoDBhatefn4w8Lipzy97CWjK6NF1/duT0kGUG0= +github.com/apernet/hysteria/core v1.3.5 h1:Pg7w7rcdXhkGUJoG3ALpT9waz+ZmWpIpD5QqJe8MbuI= +github.com/apernet/hysteria/core v1.3.5/go.mod h1:7jmeIvXeTaRDuXvK6suvxYq65E4erdi3nEkKy9Qusj4= github.com/apernet/quic-go v0.34.1-0.20230507231629-ec008b7e8473 h1:3KFetJ/lUFn0m9xTFg+rMmz2nyHg+D2boJX0Rp4OF6c= github.com/apernet/quic-go v0.34.1-0.20230507231629-ec008b7e8473/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= From 9726df8ff99c3ca80de056951018ae52f58d0d5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 04:00:34 +0000 Subject: [PATCH 02/21] Bump github.com/beevik/ntp from 1.0.0 to 1.1.1 Bumps [github.com/beevik/ntp](https://github.com/beevik/ntp) from 1.0.0 to 1.1.1. - [Release notes](https://github.com/beevik/ntp/releases) - [Changelog](https://github.com/beevik/ntp/blob/main/RELEASE_NOTES.md) - [Commits](https://github.com/beevik/ntp/compare/v1.0.0...v1.1.1) --- updated-dependencies: - dependency-name: github.com/beevik/ntp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 16 +++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index dbc3af2..920c2c3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/apernet/hysteria/core v1.3.5 - github.com/beevik/ntp v1.0.0 + github.com/beevik/ntp v1.1.1 github.com/folbricht/routedns v0.1.21-0.20230220022436-4ae86ce30d53 github.com/fsnotify/fsnotify v1.6.0 github.com/go-acme/lego/v4 v4.12.1 @@ -164,7 +164,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/stretchr/testify v1.8.3 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect @@ -188,7 +188,7 @@ require ( golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.9.0 // indirect golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.8.0 // indirect diff --git a/go.sum b/go.sum index 175584c..591f6c9 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo= github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/beevik/ntp v1.0.0 h1:d0Lgy1xbNNqVyGfvg2Z96ItKcfyn3lzgus/oRoj9vnk= -github.com/beevik/ntp v1.0.0/go.mod h1:JN7/74B0Z4GUGO/1aUeRI2adARlfJGUeaJb0y0Wvnf4= +github.com/beevik/ntp v1.1.1 h1:ah1SrQMwiyL8eRpb7+Erm7l4PvXnZ/Dnh/gjGZXPvp0= +github.com/beevik/ntp v1.1.1/go.mod h1:br1ZC24XiJQWuIUdrmQT3Bf5jQXIOLaPT+MoAK9Vlk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -761,9 +761,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= @@ -958,7 +957,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1065,9 +1063,9 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1075,8 +1073,8 @@ golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From fee53a83841541c319505c36200d305b58fc0648 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Fri, 16 Jun 2023 10:04:39 +0800 Subject: [PATCH 03/21] fix some bugs support ip limit for hy --- common/task/task.go | 83 ++++++++++++++++++++++++++++++++++ conf/conf.go | 50 +------------------- conf/watch.go | 52 +++++++++++++++++++++ core/hy/node.go | 9 +++- core/hy/server.go | 10 +++- core/xray/user.go | 1 - node/cert.go | 14 ++++++ node/controller.go | 44 ++++++------------ node/task.go | 108 ++++++++++---------------------------------- node/user.go | 30 ++++++++++++ 10 files changed, 236 insertions(+), 165 deletions(-) create mode 100644 common/task/task.go create mode 100644 conf/watch.go diff --git a/common/task/task.go b/common/task/task.go new file mode 100644 index 0000000..b04eeb7 --- /dev/null +++ b/common/task/task.go @@ -0,0 +1,83 @@ +package task + +import ( + "sync" + "time" +) + +// Task is a task that runs periodically. +type Task struct { + // Interval of the task being run + Interval time.Duration + // Execute is the task function + Execute func() error + + access sync.Mutex + timer *time.Timer + running bool +} + +func (t *Task) hasClosed() bool { + t.access.Lock() + defer t.access.Unlock() + + return !t.running +} + +func (t *Task) checkedExecute() error { + if t.hasClosed() { + return nil + } + + t.access.Lock() + defer t.access.Unlock() + + if !t.running { + return nil + } + + t.timer = time.AfterFunc(t.Interval, func() { + t.checkedExecute() + }) + + return nil +} + +// Start implements common.Runnable. +func (t *Task) Start(first bool) error { + t.access.Lock() + if t.running { + t.access.Unlock() + return nil + } + t.running = true + t.access.Unlock() + if first { + if err := t.Execute(); err != nil { + t.access.Lock() + t.running = false + t.access.Unlock() + return err + } + } + if err := t.checkedExecute(); err != nil { + t.access.Lock() + t.running = false + t.access.Unlock() + return err + } + + return nil +} + +// Close implements common.Closable. +func (t *Task) Close() { + t.access.Lock() + defer t.access.Unlock() + + t.running = false + if t.timer != nil { + t.timer.Stop() + t.timer = nil + } +} diff --git a/conf/conf.go b/conf/conf.go index e54997c..4f2c7e8 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -2,14 +2,9 @@ package conf import ( "fmt" - "io" - "log" - "os" - "path" - "time" - - "github.com/fsnotify/fsnotify" "gopkg.in/yaml.v3" + "io" + "os" ) type Conf struct { @@ -56,44 +51,3 @@ func (p *Conf) LoadFromPath(filePath string) error { } return nil } - -func (p *Conf) Watch(filePath string, reload func()) error { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return fmt.Errorf("new watcher error: %s", err) - } - go func() { - var pre time.Time - defer watcher.Close() - for { - select { - case e := <-watcher.Events: - if e.Has(fsnotify.Chmod) { - continue - } - if pre.Add(1 * time.Second).After(time.Now()) { - continue - } - time.Sleep(2 * time.Second) - pre = time.Now() - log.Println("config dir changed, reloading...") - *p = *New() - err := p.LoadFromPath(filePath) - if err != nil { - log.Printf("reload config error: %s", err) - } - reload() - log.Println("reload config success") - case err := <-watcher.Errors: - if err != nil { - log.Printf("File watcher error: %s", err) - } - } - } - }() - err = watcher.Add(path.Dir(filePath)) - if err != nil { - return fmt.Errorf("watch file error: %s", err) - } - return nil -} diff --git a/conf/watch.go b/conf/watch.go new file mode 100644 index 0000000..eacf0fa --- /dev/null +++ b/conf/watch.go @@ -0,0 +1,52 @@ +package conf + +import ( + "fmt" + "github.com/fsnotify/fsnotify" + "log" + "path" + "time" +) + +func (p *Conf) Watch(filePath string, reload func()) error { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return fmt.Errorf("new watcher error: %s", err) + } + go func() { + var pre time.Time + defer watcher.Close() + for { + select { + case e := <-watcher.Events: + if e.Has(fsnotify.Chmod) { + continue + } + if pre.Add(10 * time.Second).After(time.Now()) { + continue + } + pre = time.Now() + go func() { + time.Sleep(10 * time.Second) + log.Println("config dir changed, reloading...") + *p = *New() + err := p.LoadFromPath(filePath) + if err != nil { + log.Printf("reload config error: %s", err) + } + reload() + log.Println("reload config success") + }() + case err := <-watcher.Errors: + if err != nil { + log.Printf("File watcher error: %s", err) + } + } + } + }() + err = watcher.Add(path.Dir(filePath)) + if err != nil { + return fmt.Errorf("watch file error: %s", err) + } + return nil +} diff --git a/core/hy/node.go b/core/hy/node.go index a39908b..f97aa97 100644 --- a/core/hy/node.go +++ b/core/hy/node.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/conf" + "github.com/Yuzuki616/V2bX/limiter" "github.com/apernet/hysteria/core/cs" ) @@ -16,8 +17,12 @@ func (h *Hy) AddNode(tag string, info *panel.NodeInfo, c *conf.ControllerConfig) case "reality", "none", "": return errors.New("hysteria need normal tls cert") } - s := NewServer(tag) - err := s.runServer(info, c) + l, err := limiter.GetLimiter(tag) + if err != nil { + return fmt.Errorf("get limiter error: %s", err) + } + s := NewServer(tag, l) + err = s.runServer(info, c) if err != nil { return fmt.Errorf("run hy server error: %s", err) } diff --git a/core/hy/server.go b/core/hy/server.go index fda7f6c..6e34831 100644 --- a/core/hy/server.go +++ b/core/hy/server.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/conf" + "github.com/Yuzuki616/V2bX/limiter" "github.com/apernet/hysteria/core/sockopt" "io" "net" @@ -32,15 +33,17 @@ var serverPacketConnFuncFactoryMap = map[string]pktconns.ServerPacketConnFuncFac type Server struct { tag string + l *limiter.Limiter counter *UserTrafficCounter users sync.Map running atomic.Bool *cs.Server } -func NewServer(tag string) *Server { +func NewServer(tag string, l *limiter.Limiter) *Server { return &Server{ tag: tag, + l: l, } } @@ -173,6 +176,9 @@ func (s *Server) runServer(node *panel.NodeInfo, c *conf.ControllerConfig) error } func (s *Server) authByUser(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + if _, r := s.l.CheckLimit(string(auth), addr.String(), false); r { + return false, "device limited" + } if _, ok := s.users.Load(string(auth)); ok { return true, "Done" } @@ -180,6 +186,7 @@ func (s *Server) authByUser(addr net.Addr, auth []byte, sSend uint64, sRecv uint } func (s *Server) connectFunc(addr net.Addr, auth []byte, sSend uint64, sRecv uint64) (bool, string) { + s.l.ConnLimiter.AddConnCount(addr.String(), string(auth), false) ok, msg := s.authByUser(addr, auth, sSend, sRecv) if !ok { logrus.WithFields(logrus.Fields{ @@ -196,6 +203,7 @@ func (s *Server) connectFunc(addr net.Addr, auth []byte, sSend uint64, sRecv uin } func (s *Server) disconnectFunc(addr net.Addr, auth []byte, err error) { + s.l.ConnLimiter.DelConnCount(addr.String(), string(auth)) logrus.WithFields(logrus.Fields{ "src": defaultIPMasker.Mask(addr.String()), "error": err, diff --git a/core/xray/user.go b/core/xray/user.go index 43f2c63..c636bc0 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -3,7 +3,6 @@ package xray import ( "context" "fmt" - "github.com/Yuzuki616/V2bX/common/builder" vCore "github.com/Yuzuki616/V2bX/core" "github.com/xtls/xray-core/common/protocol" diff --git a/node/cert.go b/node/cert.go index d80857c..500c631 100644 --- a/node/cert.go +++ b/node/cert.go @@ -4,8 +4,22 @@ import ( "fmt" "github.com/Yuzuki616/V2bX/common/file" "github.com/Yuzuki616/V2bX/node/lego" + "log" ) +func (c *Controller) renewCertTask() { + l, err := lego.New(c.CertConfig) + if err != nil { + log.Print("new lego error: ", err) + return + } + err = l.RenewCert() + if err != nil { + log.Print("renew cert error: ", err) + return + } +} + func (c *Controller) requestCert() error { if c.CertConfig.CertFile == "" || c.CertConfig.KeyFile == "" { return fmt.Errorf("cert file path or key file path not exist") diff --git a/node/controller.go b/node/controller.go index d9c1bb1..2753d4c 100644 --- a/node/controller.go +++ b/node/controller.go @@ -3,14 +3,13 @@ package node import ( "errors" "fmt" - "log" - "github.com/Yuzuki616/V2bX/api/iprecoder" "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/common/task" "github.com/Yuzuki616/V2bX/conf" vCore "github.com/Yuzuki616/V2bX/core" "github.com/Yuzuki616/V2bX/limiter" - "github.com/xtls/xray-core/common/task" + "log" ) type Controller struct { @@ -20,11 +19,11 @@ type Controller struct { Tag string userList []panel.UserInfo ipRecorder iprecoder.IpRecorder - nodeInfoMonitorPeriodic *task.Periodic - userReportPeriodic *task.Periodic - renewCertPeriodic *task.Periodic - dynamicSpeedLimitPeriodic *task.Periodic - onlineIpReportPeriodic *task.Periodic + nodeInfoMonitorPeriodic *task.Task + userReportPeriodic *task.Task + renewCertPeriodic *task.Task + dynamicSpeedLimitPeriodic *task.Task + onlineIpReportPeriodic *task.Task *conf.ControllerConfig } @@ -93,38 +92,23 @@ func (c *Controller) Start() error { func (c *Controller) Close() error { limiter.DeleteLimiter(c.Tag) if c.nodeInfoMonitorPeriodic != nil { - err := c.nodeInfoMonitorPeriodic.Close() - if err != nil { - return fmt.Errorf("node info periodic close error: %s", err) - } + c.nodeInfoMonitorPeriodic.Close() } - if c.nodeInfoMonitorPeriodic != nil { - err := c.userReportPeriodic.Close() - if err != nil { - return fmt.Errorf("user report periodic close error: %s", err) - } + if c.userReportPeriodic != nil { + c.userReportPeriodic.Close() } if c.renewCertPeriodic != nil { - err := c.renewCertPeriodic.Close() - if err != nil { - return fmt.Errorf("renew cert periodic close error: %s", err) - } + c.renewCertPeriodic.Close() } if c.dynamicSpeedLimitPeriodic != nil { - err := c.dynamicSpeedLimitPeriodic.Close() - if err != nil { - return fmt.Errorf("dynamic speed limit periodic close error: %s", err) - } + c.dynamicSpeedLimitPeriodic.Close() } if c.onlineIpReportPeriodic != nil { - err := c.onlineIpReportPeriodic.Close() - if err != nil { - return fmt.Errorf("online ip report periodic close error: %s", err) - } + c.onlineIpReportPeriodic.Close() } return nil } func (c *Controller) buildNodeTag() string { - return fmt.Sprintf("%s_%s_%d", c.nodeInfo.Type, c.ListenIP, c.nodeInfo.Id) + return fmt.Sprintf("%s-%s-%d", c.apiClient.APIHost, c.nodeInfo.Type, c.nodeInfo.Id) } diff --git a/node/task.go b/node/task.go index b029ecc..768b7e2 100644 --- a/node/task.go +++ b/node/task.go @@ -2,52 +2,41 @@ package node import ( "fmt" - "log" - "runtime" - "time" - + "github.com/Yuzuki616/V2bX/common/task" vCore "github.com/Yuzuki616/V2bX/core" - - "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/limiter" - "github.com/Yuzuki616/V2bX/node/lego" - "github.com/xtls/xray-core/common/task" + "log" + "time" ) func (c *Controller) initTask() { // fetch node info task - c.nodeInfoMonitorPeriodic = &task.Periodic{ + c.nodeInfoMonitorPeriodic = &task.Task{ Interval: c.nodeInfo.PullInterval, Execute: c.nodeInfoMonitor, } // fetch user list task - c.userReportPeriodic = &task.Periodic{ + c.userReportPeriodic = &task.Task{ Interval: c.nodeInfo.PushInterval, - Execute: c.reportUserTraffic, + Execute: c.reportUserTrafficTask, } - log.Printf("[%s: %d] Start monitor node status", c.nodeInfo.Type, c.nodeInfo.Id) + log.Printf("[%s] Start monitor node status", c.Tag) // delay to start nodeInfoMonitor - go func() { - time.Sleep(c.nodeInfo.PullInterval) - _ = c.nodeInfoMonitorPeriodic.Start() - }() - log.Printf("[%s: %d] Start report node status", c.nodeInfo.Type, c.nodeInfo.Id) - // delay to start userReport - go func() { - time.Sleep(c.nodeInfo.PullInterval) - _ = c.userReportPeriodic.Start() - }() - if c.nodeInfo.Tls && c.CertConfig.CertMode != "none" && - (c.CertConfig.CertMode == "dns" || c.CertConfig.CertMode == "http") { - c.renewCertPeriodic = &task.Periodic{ - Interval: time.Hour * 24, - Execute: c.reportUserTraffic, + _ = c.nodeInfoMonitorPeriodic.Start(false) + log.Printf("[%s] Start report node status", c.Tag) + _ = c.userReportPeriodic.Start(false) + if c.nodeInfo.Tls { + switch c.CertConfig.CertMode { + case "reality", "none", "": + default: + c.renewCertPeriodic = &task.Task{ + Interval: time.Hour * 24, + Execute: c.reportUserTrafficTask, + } + log.Printf("[%s] Start renew cert", c.Tag) + // delay to start renewCert + _ = c.renewCertPeriodic.Start(true) } - log.Printf("[%s: %d] Start renew cert", c.nodeInfo.Type, c.nodeInfo.Id) - // delay to start renewCert - go func() { - _ = c.renewCertPeriodic.Start() - }() } } @@ -114,20 +103,14 @@ func (c *Controller) nodeInfoMonitor() (err error) { if c.nodeInfoMonitorPeriodic.Interval != newNodeInfo.PullInterval && newNodeInfo.PullInterval != 0 { c.nodeInfoMonitorPeriodic.Interval = newNodeInfo.PullInterval - _ = c.nodeInfoMonitorPeriodic.Close() - go func() { - time.Sleep(c.nodeInfoMonitorPeriodic.Interval) - _ = c.nodeInfoMonitorPeriodic.Start() - }() + c.nodeInfoMonitorPeriodic.Close() + _ = c.nodeInfoMonitorPeriodic.Start(false) } if c.userReportPeriodic.Interval != newNodeInfo.PushInterval && newNodeInfo.PushInterval != 0 { c.userReportPeriodic.Interval = newNodeInfo.PullInterval - _ = c.userReportPeriodic.Close() - go func() { - time.Sleep(c.userReportPeriodic.Interval) - _ = c.userReportPeriodic.Start() - }() + c.userReportPeriodic.Close() + _ = c.userReportPeriodic.Start(false) } } else { deleted, added := compareUserList(c.userList, newUserInfo) @@ -168,44 +151,3 @@ func (c *Controller) nodeInfoMonitor() (err error) { } return nil } - -func (c *Controller) reportUserTraffic() (err error) { - // Get User traffic - userTraffic := make([]panel.UserTraffic, 0) - for i := range c.userList { - up, down := c.server.GetUserTraffic(c.Tag, c.userList[i].Uuid, true) - if up > 0 || down > 0 { - if c.LimitConfig.EnableDynamicSpeedLimit { - c.userList[i].Traffic += up + down - } - userTraffic = append(userTraffic, panel.UserTraffic{ - UID: (c.userList)[i].Id, - Upload: up, - Download: down}) - } - } - if len(userTraffic) > 0 && !c.DisableUploadTraffic { - err = c.apiClient.ReportUserTraffic(userTraffic) - if err != nil { - log.Printf("Report user traffic faild: %s", err) - } else { - log.Printf("[%s: %d] Report %d online users", c.nodeInfo.Type, c.nodeInfo.Id, len(userTraffic)) - } - } - userTraffic = nil - runtime.GC() - return nil -} - -func (c *Controller) RenewCert() { - l, err := lego.New(c.CertConfig) - if err != nil { - log.Print("new lego error: ", err) - return - } - err = l.RenewCert() - if err != nil { - log.Print("renew cert error: ", err) - return - } -} diff --git a/node/user.go b/node/user.go index 31857f0..25b1318 100644 --- a/node/user.go +++ b/node/user.go @@ -2,9 +2,39 @@ package node import ( "github.com/Yuzuki616/V2bX/api/panel" + "log" + "runtime" "strconv" ) +func (c *Controller) reportUserTrafficTask() (err error) { + // Get User traffic + userTraffic := make([]panel.UserTraffic, 0) + for i := range c.userList { + up, down := c.server.GetUserTraffic(c.Tag, c.userList[i].Uuid, true) + if up > 0 || down > 0 { + if c.LimitConfig.EnableDynamicSpeedLimit { + c.userList[i].Traffic += up + down + } + userTraffic = append(userTraffic, panel.UserTraffic{ + UID: (c.userList)[i].Id, + Upload: up, + Download: down}) + } + } + if len(userTraffic) > 0 && !c.DisableUploadTraffic { + err = c.apiClient.ReportUserTraffic(userTraffic) + if err != nil { + log.Printf("Report user traffic faild: %s", err) + } else { + log.Printf("[%s] Report %d online users", c.Tag, len(userTraffic)) + } + } + userTraffic = nil + runtime.GC() + return nil +} + func compareUserList(old, new []panel.UserInfo) (deleted, added []panel.UserInfo) { tmp := map[string]struct{}{} tmp2 := map[string]struct{}{} From 676daadec7f31a0942f34544822e7e6f1ccf32b6 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Fri, 16 Jun 2023 10:14:42 +0800 Subject: [PATCH 04/21] update readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eca3c32..9a45d33 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ A V2board node server based on multi core, modified from XrayR. | 在线人数统计 | √ | √ | √ | √ | | 审计规则 | √ | √ | √ | | | 自定义DNS | √ | √ | √ | √ | -| 在线IP数限制 | √ | √ | √ | | +| 在线IP数限制 | √ | √ | √ | √ | | 连接数限制 | √ | √ | √ | | | 跨节点IP数限制 | √ | √ | √ | | | 按照用户限速 | √ | √ | √ | | @@ -43,6 +43,7 @@ A V2board node server based on multi core, modified from XrayR. - [x] 集成基本操作Command(Start, Stop, Restart, Status, Uninstall) - [ ] 完善Hysteria内核支持 - [ ] 完善使用文档 +- [ ] 尽可能统一日志输出格式 ## 软件安装 From dea858f29fa7059cb347f4dbec8416a944f4e404 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jun 2023 02:18:14 +0000 Subject: [PATCH 05/21] Bump golang.org/x/crypto from 0.9.0 to 0.10.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.9.0 to 0.10.0. - [Commits](https://github.com/golang/crypto/compare/v0.9.0...v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 5 ++--- go.sum | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 8aaaffb..8c797bf 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/xtls/xray-core v1.8.1 - golang.org/x/crypto v0.9.0 + golang.org/x/crypto v0.10.0 google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -159,7 +159,6 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/testify v1.8.4 // indirect - github.com/subosito/gotenv v1.4.2 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect github.com/transip/gotransip/v6 v6.17.0 // indirect @@ -183,7 +182,7 @@ require ( golang.org/x/net v0.10.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/text v0.10.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.8.0 // indirect google.golang.org/api v0.114.0 // indirect diff --git a/go.sum b/go.sum index b50b901..0522074 100644 --- a/go.sum +++ b/go.sum @@ -787,8 +787,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -945,9 +945,8 @@ golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -959,8 +958,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From c536c46703c116091ca01bcc0b175c4ef9a85d10 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Sun, 18 Jun 2023 03:37:27 +0800 Subject: [PATCH 06/21] fix hy tls bug fix task --- common/task/task.go | 23 +++++++++-------------- common/task/task_test.go | 15 +++++++++++++++ go.mod | 1 - go.sum | 1 - node/controller.go | 2 +- node/lego/lego.go | 3 ++- node/task.go | 2 +- 7 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 common/task/task_test.go diff --git a/common/task/task.go b/common/task/task.go index b04eeb7..f5a3234 100644 --- a/common/task/task.go +++ b/common/task/task.go @@ -24,20 +24,24 @@ func (t *Task) hasClosed() bool { return !t.running } -func (t *Task) checkedExecute() error { +func (t *Task) checkedExecute(first bool) error { if t.hasClosed() { return nil } t.access.Lock() defer t.access.Unlock() - + if first { + if err := t.Execute(); err != nil { + t.running = false + return err + } + } if !t.running { return nil } - t.timer = time.AfterFunc(t.Interval, func() { - t.checkedExecute() + t.checkedExecute(true) }) return nil @@ -52,21 +56,12 @@ func (t *Task) Start(first bool) error { } t.running = true t.access.Unlock() - if first { - if err := t.Execute(); err != nil { - t.access.Lock() - t.running = false - t.access.Unlock() - return err - } - } - if err := t.checkedExecute(); err != nil { + if err := t.checkedExecute(first); err != nil { t.access.Lock() t.running = false t.access.Unlock() return err } - return nil } diff --git a/common/task/task_test.go b/common/task/task_test.go new file mode 100644 index 0000000..dec33b1 --- /dev/null +++ b/common/task/task_test.go @@ -0,0 +1,15 @@ +package task + +import ( + "log" + "testing" + "time" +) + +func TestTask(t *testing.T) { + ts := Task{Execute: func() error { + log.Println("q") + return nil + }, Interval: time.Second} + ts.Start(false) +} diff --git a/go.mod b/go.mod index 8aaaffb..5e83c7f 100644 --- a/go.mod +++ b/go.mod @@ -159,7 +159,6 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/testify v1.8.4 // indirect - github.com/subosito/gotenv v1.4.2 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect github.com/transip/gotransip/v6 v6.17.0 // indirect diff --git a/go.sum b/go.sum index b50b901..82cf811 100644 --- a/go.sum +++ b/go.sum @@ -947,7 +947,6 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/node/controller.go b/node/controller.go index 2753d4c..cd64eaf 100644 --- a/node/controller.go +++ b/node/controller.go @@ -63,7 +63,7 @@ func (c *Controller) Start() error { return fmt.Errorf("update rule error: %s", err) } } - if c.nodeInfo.Tls { + if c.nodeInfo.Tls || c.nodeInfo.Type == "hysteria" { err = c.requestCert() if err != nil { return fmt.Errorf("request cert error: %s", err) diff --git a/node/lego/lego.go b/node/lego/lego.go index 374acd4..4a29c9c 100644 --- a/node/lego/lego.go +++ b/node/lego/lego.go @@ -16,7 +16,8 @@ type Lego struct { } func New(config *conf.CertConfig) (*Lego, error) { - user, err := NewUser(path.Join("/etc/V2bX/cert/user/", + user, err := NewUser(path.Join(path.Dir(config.CertFile), + "user", fmt.Sprintf("user-%s.json", config.Email)), config.Email) if err != nil { diff --git a/node/task.go b/node/task.go index 768b7e2..59d3ee2 100644 --- a/node/task.go +++ b/node/task.go @@ -67,7 +67,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { log.Print(err) return nil } - if newNodeInfo.Tls { + if c.nodeInfo.Tls || c.nodeInfo.Type == "hysteria" { err = c.requestCert() if err != nil { return fmt.Errorf("request cert error: %s", err) From 2358ed8a1f0eb3f1647dd398895912ff408e3124 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 08:30:10 +0800 Subject: [PATCH 07/21] fix hy counter --- core/hy/user.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/hy/user.go b/core/hy/user.go index 30cb651..7aa2dda 100644 --- a/core/hy/user.go +++ b/core/hy/user.go @@ -23,9 +23,9 @@ func (h *Hy) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) s := v.(*Server) auth := base64.StdEncoding.EncodeToString([]byte(uuid)) up = s.counter.getCounters(auth).UpCounter.Load() - down = s.counter.getCounters(uuid).DownCounter.Load() + down = s.counter.getCounters(auth).DownCounter.Load() if reset { - s.counter.Reset(uuid) + s.counter.Reset(auth) } return } From 2232bf46e5300b7df7aa45fa66d55fb5051ced0e Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 08:34:59 +0800 Subject: [PATCH 08/21] fix hy server type --- core/hy/node.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/hy/node.go b/core/hy/node.go index f97aa97..5cdf889 100644 --- a/core/hy/node.go +++ b/core/hy/node.go @@ -6,7 +6,6 @@ import ( "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/conf" "github.com/Yuzuki616/V2bX/limiter" - "github.com/apernet/hysteria/core/cs" ) func (h *Hy) AddNode(tag string, info *panel.NodeInfo, c *conf.ControllerConfig) error { @@ -32,7 +31,7 @@ func (h *Hy) AddNode(tag string, info *panel.NodeInfo, c *conf.ControllerConfig) func (h *Hy) DelNode(tag string) error { if s, e := h.servers.Load(tag); e { - err := s.(*cs.Server).Close() + err := s.(*Server).Close() if err != nil { return err } From 82c1753672e2a21d8e770e11666dc659af2d0ab5 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 09:24:05 +0800 Subject: [PATCH 09/21] fix node change --- node/controller.go | 2 +- node/task.go | 133 +++++++++++++++++++++++---------------------- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/node/controller.go b/node/controller.go index cd64eaf..e633832 100644 --- a/node/controller.go +++ b/node/controller.go @@ -83,7 +83,7 @@ func (c *Controller) Start() error { if err != nil { return fmt.Errorf("add users error: %s", err) } - log.Printf("[%s: %d] Added %d new users", c.nodeInfo.Type, c.nodeInfo.Id, added) + log.Printf("[%s] Added %d new users", c.Tag, added) c.initTask() return nil } diff --git a/node/task.go b/node/task.go index 59d3ee2..713c023 100644 --- a/node/task.go +++ b/node/task.go @@ -41,50 +41,44 @@ func (c *Controller) initTask() { } func (c *Controller) nodeInfoMonitor() (err error) { - // First fetch Node Info + // get node info newNodeInfo, err := c.apiClient.GetNodeInfo() if err != nil { - log.Print(err) + log.Printf("[%s] Get node info error: %s", c.Tag, err) + return nil + } + // get user info + newUserInfo, err := c.apiClient.GetUserList() + if err != nil { + log.Printf("[%s] Get user list error: %s", c.Tag, err) return nil } - var nodeInfoChanged = false - // If nodeInfo changed if newNodeInfo != nil { + // nodeInfo changed // Remove old tag - oldTag := c.Tag - err := c.server.DelNode(oldTag) + err = c.server.DelNode(c.Tag) if err != nil { - log.Print(err) + log.Printf("[%s] Del node error: %s", c.Tag, err) return nil } // Remove Old limiter - limiter.DeleteLimiter(oldTag) - // Add new tag - c.nodeInfo = newNodeInfo + limiter.DeleteLimiter(c.Tag) + // Add new Limiter c.Tag = c.buildNodeTag() - err = c.server.AddNode(c.Tag, newNodeInfo, c.ControllerConfig) - if err != nil { - log.Print(err) - return nil - } - if c.nodeInfo.Tls || c.nodeInfo.Type == "hysteria" { + l := limiter.AddLimiter(c.Tag, &c.LimitConfig, newUserInfo) + // check cert + if newNodeInfo.Tls || newNodeInfo.Type == "hysteria" { err = c.requestCert() if err != nil { - return fmt.Errorf("request cert error: %s", err) + log.Printf("[%s] Request cert error: %s", c.Tag, err) } } - nodeInfoChanged = true - } - // Update User - newUserInfo, err := c.apiClient.GetUserList() - if err != nil { - log.Print(err) - return nil - } - if nodeInfoChanged { - c.userList = newUserInfo - // Add new Limiter - l := limiter.AddLimiter(c.Tag, &c.LimitConfig, newUserInfo) + // add new node + err = c.server.AddNode(c.Tag, newNodeInfo, c.ControllerConfig) + if err != nil { + log.Printf("[%s] Add node error: %s", c.Tag, err) + return nil + } _, err = c.server.AddUsers(&vCore.AddUsersParams{ Tag: c.Tag, Config: c.ControllerConfig, @@ -92,12 +86,12 @@ func (c *Controller) nodeInfoMonitor() (err error) { NodeInfo: newNodeInfo, }) if err != nil { - log.Print(err) + log.Printf("[%s] Add users error: %s", c.Tag, err) return nil } err = l.UpdateRule(newNodeInfo.Rules) if err != nil { - log.Printf("Update Rule error: %s", err) + log.Printf("[%s] Update Rule error: %s", c.Tag, err) } // Check interval if c.nodeInfoMonitorPeriodic.Interval != newNodeInfo.PullInterval && @@ -112,42 +106,49 @@ func (c *Controller) nodeInfoMonitor() (err error) { c.userReportPeriodic.Close() _ = c.userReportPeriodic.Start(false) } - } else { - deleted, added := compareUserList(c.userList, newUserInfo) - if len(deleted) > 0 { - deletedEmail := make([]string, len(deleted)) - for i := range deleted { - deletedEmail[i] = fmt.Sprintf("%s|%s|%d", - c.Tag, - (deleted)[i].Uuid, - (deleted)[i].Id) - } - err := c.server.DelUsers(deletedEmail, c.Tag) - if err != nil { - log.Print(err) - } - } - if len(added) > 0 { - _, err := c.server.AddUsers(&vCore.AddUsersParams{ - Tag: c.Tag, - Config: c.ControllerConfig, - UserInfo: added, - NodeInfo: c.nodeInfo, - }) - if err != nil { - log.Print(err) - } - } - if len(added) > 0 || len(deleted) > 0 { - // Update Limiter - err = limiter.UpdateLimiter(c.Tag, added, deleted) - if err != nil { - log.Print("update limiter:", err) - } - } - log.Printf("[%s: %d] %d user deleted, %d user added", c.nodeInfo.Type, c.nodeInfo.Id, - len(deleted), len(added)) + c.nodeInfo = newNodeInfo c.userList = newUserInfo + // exit + return nil } + + // node no changed, check users + deleted, added := compareUserList(c.userList, newUserInfo) + if len(deleted) > 0 { + // have deleted users + deletedEmail := make([]string, len(deleted)) + for i := range deleted { + deletedEmail[i] = fmt.Sprintf("%s|%s|%d", + c.Tag, + (deleted)[i].Uuid, + (deleted)[i].Id) + } + err = c.server.DelUsers(deletedEmail, c.Tag) + if err != nil { + log.Printf("[%s] Del users error: %s", c.Tag, err) + } + } + if len(added) > 0 { + // have added users + _, err = c.server.AddUsers(&vCore.AddUsersParams{ + Tag: c.Tag, + Config: c.ControllerConfig, + UserInfo: added, + NodeInfo: c.nodeInfo, + }) + if err != nil { + log.Printf("[%s] Add users error: %s", c.Tag, err) + } + } + if len(added) > 0 || len(deleted) > 0 { + // update Limiter + err = limiter.UpdateLimiter(c.Tag, added, deleted) + if err != nil { + log.Printf("[%s] Update limiter error: %s", c.Tag, err) + } + } + c.userList = newUserInfo + log.Printf("[%s] %d user deleted, %d user added", c.Tag, + len(deleted), len(added)) return nil } From d3fe0c8afec23dc00e3b0d66e19ce7656465dc65 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 09:33:20 +0800 Subject: [PATCH 10/21] del no need option --- conf/node.go | 16 +++++++--------- node/controller.go | 6 ++---- node/user.go | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/conf/node.go b/conf/node.go index ac1b134..074f738 100644 --- a/conf/node.go +++ b/conf/node.go @@ -15,15 +15,13 @@ type ApiConfig struct { } type ControllerConfig struct { - DisableUploadTraffic bool `yaml:"DisableUploadTraffic"` - DisableGetRule bool `yaml:"DisableGetRule"` - ListenIP string `yaml:"ListenIP"` - SendIP string `yaml:"SendIP"` - EnableProxyProtocol bool `yaml:"EnableProxyProtocol"` - XrayOptions XrayOptions `yaml:"XrayOptions"` - HyOptions HyOptions `yaml:"HyOptions"` - LimitConfig LimitConfig `yaml:"LimitConfig"` - CertConfig *CertConfig `yaml:"CertConfig"` + ListenIP string `yaml:"ListenIP"` + SendIP string `yaml:"SendIP"` + EnableProxyProtocol bool `yaml:"EnableProxyProtocol"` + XrayOptions XrayOptions `yaml:"XrayOptions"` + HyOptions HyOptions `yaml:"HyOptions"` + LimitConfig LimitConfig `yaml:"LimitConfig"` + CertConfig *CertConfig `yaml:"CertConfig"` } type XrayOptions struct { diff --git a/node/controller.go b/node/controller.go index e633832..85b0b4a 100644 --- a/node/controller.go +++ b/node/controller.go @@ -58,10 +58,8 @@ func (c *Controller) Start() error { // add limiter l := limiter.AddLimiter(c.Tag, &c.LimitConfig, c.userList) // add rule limiter - if !c.DisableGetRule { - if err = l.UpdateRule(c.nodeInfo.Rules); err != nil { - return fmt.Errorf("update rule error: %s", err) - } + if err = l.UpdateRule(c.nodeInfo.Rules); err != nil { + return fmt.Errorf("update rule error: %s", err) } if c.nodeInfo.Tls || c.nodeInfo.Type == "hysteria" { err = c.requestCert() diff --git a/node/user.go b/node/user.go index 25b1318..d832b09 100644 --- a/node/user.go +++ b/node/user.go @@ -22,7 +22,7 @@ func (c *Controller) reportUserTrafficTask() (err error) { Download: down}) } } - if len(userTraffic) > 0 && !c.DisableUploadTraffic { + if len(userTraffic) > 0 { err = c.apiClient.ReportUserTraffic(userTraffic) if err != nil { log.Printf("Report user traffic faild: %s", err) From a729b2ec003d70765591dd174caa1a46fa1a2cf7 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 09:47:03 +0800 Subject: [PATCH 11/21] update example --- example/config.yml.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/config.yml.example b/example/config.yml.example index b27f79e..58f0141 100644 --- a/example/config.yml.example +++ b/example/config.yml.example @@ -1,5 +1,5 @@ CoreConfig: - Type: "xray" # Core type. if you need many cores, use " " to split + 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 @@ -39,7 +39,7 @@ Nodes: 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 dsable + ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable 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) From adf5c60c2a42ecad2f1bd506c05d7cca7b2ed76c Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 09:56:18 +0800 Subject: [PATCH 12/21] fix misspell --- core/core.go | 2 +- core/{selecter.go => selector.go} | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) rename core/{selecter.go => selector.go} (78%) diff --git a/core/core.go b/core/core.go index ad00877..825cac8 100644 --- a/core/core.go +++ b/core/core.go @@ -26,7 +26,7 @@ func NewCore(c *conf.CoreConfig) (Core, error) { } cs = append(cs, core1) } - return &Selecter{ + return &Selector{ cores: cs, }, nil } diff --git a/core/selecter.go b/core/selector.go similarity index 78% rename from core/selecter.go rename to core/selector.go index 38127a9..03c25c7 100644 --- a/core/selecter.go +++ b/core/selector.go @@ -9,12 +9,12 @@ import ( "github.com/hashicorp/go-multierror" ) -type Selecter struct { +type Selector struct { cores []Core nodes sync.Map } -func (s *Selecter) Start() error { +func (s *Selector) Start() error { for i := range s.cores { err := s.cores[i].Start() return err @@ -22,7 +22,7 @@ func (s *Selecter) Start() error { return nil } -func (s *Selecter) Close() error { +func (s *Selector) Close() error { var errs error for i := range s.cores { errs = multierror.Append(errs, s.cores[i].Close()) @@ -39,7 +39,7 @@ func isSupported(protocol string, protocols []string) bool { return false } -func (s *Selecter) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error { +func (s *Selector) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error { for i := range s.cores { if !isSupported(info.Type, s.cores[i].Protocols()) { continue @@ -53,7 +53,7 @@ func (s *Selecter) AddNode(tag string, info *panel.NodeInfo, config *conf.Contro return errors.New("the node type is not support") } -func (s *Selecter) DelNode(tag string) error { +func (s *Selector) DelNode(tag string) error { if t, e := s.nodes.Load(tag); e { err := s.cores[t.(int)].DelNode(tag) if err != nil { @@ -65,7 +65,7 @@ func (s *Selecter) DelNode(tag string) error { return errors.New("the node is not have") } -func (s *Selecter) AddUsers(p *AddUsersParams) (added int, err error) { +func (s *Selector) AddUsers(p *AddUsersParams) (added int, err error) { t, e := s.nodes.Load(p.Tag) if !e { return 0, errors.New("the node is not have") @@ -73,7 +73,7 @@ func (s *Selecter) AddUsers(p *AddUsersParams) (added int, err error) { return s.cores[t.(int)].AddUsers(p) } -func (s *Selecter) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) { +func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) { t, e := s.nodes.Load(tag) if !e { return 0, 0 @@ -81,7 +81,7 @@ func (s *Selecter) GetUserTraffic(tag, uuid string, reset bool) (up int64, down return s.cores[t.(int)].GetUserTraffic(tag, uuid, reset) } -func (s *Selecter) DelUsers(users []string, tag string) error { +func (s *Selector) DelUsers(users []string, tag string) error { t, e := s.nodes.Load(tag) if !e { return errors.New("the node is not have") @@ -89,7 +89,7 @@ func (s *Selecter) DelUsers(users []string, tag string) error { return s.cores[t.(int)].DelUsers(users, tag) } -func (s *Selecter) Protocols() []string { +func (s *Selector) Protocols() []string { protocols := make([]string, 0) for i := range s.cores { protocols = append(protocols, s.cores[i].Protocols()...) From 95a141ef59287361ec29393b10e0699346f4e816 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 10:31:42 +0800 Subject: [PATCH 13/21] fix user tag --- api/panel/node.go | 10 ---------- common/builder/user.go | 2 +- core/hy/user.go | 7 ++++--- core/interface.go | 2 +- core/selector.go | 2 +- core/xray/user.go | 7 ++++--- limiter/dynamic.go | 4 ++-- limiter/limiter.go | 10 ++-------- node/task.go | 10 +--------- 9 files changed, 16 insertions(+), 38 deletions(-) diff --git a/api/panel/node.go b/api/panel/node.go index e731d42..a48e64c 100644 --- a/api/panel/node.go +++ b/api/panel/node.go @@ -41,11 +41,6 @@ type ShadowsocksNodeRsp struct { ServerKey string `json:"server_key"` } -type TrojanNodeRsp struct { - Host string `json:"host"` - ServerName string `json:"server_name"` -} - type HysteriaNodeRsp struct { UpMbps int `json:"up_mbps"` DownMbps int `json:"down_mbps"` @@ -131,11 +126,6 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { node.ServerKey = rsp.ServerKey node.Cipher = rsp.Cipher case "trojan": - rsp := TrojanNodeRsp{} - err = json.Unmarshal(r.Body(), &rsp) - if err != nil { - return nil, fmt.Errorf("decode v2ray params error: %s", err) - } case "hysteria": rsp := HysteriaNodeRsp{} err = json.Unmarshal(r.Body(), &rsp) diff --git a/common/builder/user.go b/common/builder/user.go index a410a1d..4239626 100644 --- a/common/builder/user.go +++ b/common/builder/user.go @@ -93,7 +93,7 @@ func BuildSSUser(tag string, userInfo *panel.UserInfo, cypher string, serverKey } return &protocol.User{ Level: 0, - Email: tag, + Email: BuildUserTag(tag, userInfo.Uuid), Account: serial.ToTypedMessage(ssAccount), } } else { diff --git a/core/hy/user.go b/core/hy/user.go index 7aa2dda..a286dcc 100644 --- a/core/hy/user.go +++ b/core/hy/user.go @@ -3,6 +3,7 @@ package hy import ( "encoding/base64" "errors" + "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/core" ) @@ -30,15 +31,15 @@ func (h *Hy) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) return } -func (h *Hy) DelUsers(users []string, tag string) error { +func (h *Hy) DelUsers(users []panel.UserInfo, tag string) error { v, e := h.servers.Load(tag) if !e { return errors.New("the node is not have") } s := v.(*Server) for i := range users { - s.users.Delete(users[i]) - s.counter.Delete(users[i]) + s.users.Delete(users[i].Uuid) + s.counter.Delete(base64.StdEncoding.EncodeToString([]byte(users[i].Uuid))) } return nil } diff --git a/core/interface.go b/core/interface.go index 0af41fa..af29058 100644 --- a/core/interface.go +++ b/core/interface.go @@ -18,6 +18,6 @@ type Core interface { DelNode(tag string) error AddUsers(p *AddUsersParams) (added int, err error) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) - DelUsers(users []string, tag string) error + DelUsers(users []panel.UserInfo, tag string) error Protocols() []string } diff --git a/core/selector.go b/core/selector.go index 03c25c7..997be8a 100644 --- a/core/selector.go +++ b/core/selector.go @@ -81,7 +81,7 @@ func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down return s.cores[t.(int)].GetUserTraffic(tag, uuid, reset) } -func (s *Selector) DelUsers(users []string, tag string) error { +func (s *Selector) DelUsers(users []panel.UserInfo, tag string) error { t, e := s.nodes.Load(tag) if !e { return errors.New("the node is not have") diff --git a/core/xray/user.go b/core/xray/user.go index c636bc0..571bf46 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -3,6 +3,7 @@ package xray import ( "context" "fmt" + "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/common/builder" vCore "github.com/Yuzuki616/V2bX/core" "github.com/xtls/xray-core/common/protocol" @@ -25,13 +26,13 @@ func (c *Core) GetUserManager(tag string) (proxy.UserManager, error) { return userManager, nil } -func (c *Core) DelUsers(users []string, tag string) error { +func (c *Core) DelUsers(users []panel.UserInfo, tag string) error { userManager, err := c.GetUserManager(tag) if err != nil { return fmt.Errorf("get user manager error: %s", err) } - for _, email := range users { - err = userManager.RemoveUser(context.Background(), email) + for i := range users { + err = userManager.RemoveUser(context.Background(), builder.BuildUserTag(tag, users[i].Uuid)) if err != nil { return err } diff --git a/limiter/dynamic.go b/limiter/dynamic.go index 7e7d8c5..a74599e 100644 --- a/limiter/dynamic.go +++ b/limiter/dynamic.go @@ -1,8 +1,8 @@ package limiter import ( - "fmt" "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/common/builder" "time" ) @@ -11,7 +11,7 @@ func (l *Limiter) AddDynamicSpeedLimit(tag string, userInfo *panel.UserInfo, lim DynamicSpeedLimit: limitNum, ExpireTime: time.Now().Add(time.Duration(expire) * time.Second).Unix(), } - l.UserLimitInfo.Store(fmt.Sprintf("%s|%s|%d", tag, userInfo.Uuid, userInfo.Id), userLimit) + l.UserLimitInfo.Store(builder.BuildUserTag(tag, userInfo.Uuid), userLimit) return nil } diff --git a/limiter/limiter.go b/limiter/limiter.go index ff45148..f8faf07 100644 --- a/limiter/limiter.go +++ b/limiter/limiter.go @@ -85,10 +85,7 @@ func UpdateLimiter(tag string, added []panel.UserInfo, deleted []panel.UserInfo) return fmt.Errorf("get limit error: %s", err) } for i := range deleted { - l.UserLimitInfo.Delete(fmt.Sprintf("%s|%s|%d", - tag, - deleted[i].Uuid, - deleted[i].Id)) + l.UserLimitInfo.Delete(builder.BuildUserTag(tag, deleted[i].Uuid)) } for i := range added { if added[i].SpeedLimit != 0 { @@ -97,10 +94,7 @@ func UpdateLimiter(tag string, added []panel.UserInfo, deleted []panel.UserInfo) SpeedLimit: added[i].SpeedLimit, ExpireTime: 0, } - l.UserLimitInfo.Store(fmt.Sprintf("%s|%s|%d", - tag, - added[i].Uuid, - added[i].Id), userLimit) + l.UserLimitInfo.Store(builder.BuildUserTag(tag, added[i].Uuid), userLimit) } } return nil diff --git a/node/task.go b/node/task.go index 713c023..6ee3c0f 100644 --- a/node/task.go +++ b/node/task.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "github.com/Yuzuki616/V2bX/common/task" vCore "github.com/Yuzuki616/V2bX/core" "github.com/Yuzuki616/V2bX/limiter" @@ -116,14 +115,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { deleted, added := compareUserList(c.userList, newUserInfo) if len(deleted) > 0 { // have deleted users - deletedEmail := make([]string, len(deleted)) - for i := range deleted { - deletedEmail[i] = fmt.Sprintf("%s|%s|%d", - c.Tag, - (deleted)[i].Uuid, - (deleted)[i].Id) - } - err = c.server.DelUsers(deletedEmail, c.Tag) + err = c.server.DelUsers(deleted, c.Tag) if err != nil { log.Printf("[%s] Del users error: %s", c.Tag, err) } From 41b06e0bc68c4d392e6ec602dbaa1f4f27cd38cd Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 10:48:11 +0800 Subject: [PATCH 14/21] clear xray counter --- core/xray/user.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/xray/user.go b/core/xray/user.go index 571bf46..cea922b 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -31,11 +31,17 @@ func (c *Core) DelUsers(users []panel.UserInfo, tag string) error { if err != nil { return fmt.Errorf("get user manager error: %s", err) } + var up, down, user string for i := range users { - err = userManager.RemoveUser(context.Background(), builder.BuildUserTag(tag, users[i].Uuid)) + user = builder.BuildUserTag(tag, users[i].Uuid) + err = userManager.RemoveUser(context.Background(), user) if err != nil { return err } + up = "user>>>" + user + ">>>traffic>>>uplink" + down = "user>>>" + user + ">>>traffic>>>downlink" + c.shm.UnregisterCounter(up) + c.shm.UnregisterCounter(down) } return nil } From ad03c272892ec96fc90fd9e1a571b97b35ada8eb Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Mon, 19 Jun 2023 11:08:15 +0800 Subject: [PATCH 15/21] add node change log --- core/xray/distro/all/all.go | 2 +- node/task.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/xray/distro/all/all.go b/core/xray/distro/all/all.go index 1a5f307..18057ee 100644 --- a/core/xray/distro/all/all.go +++ b/core/xray/distro/all/all.go @@ -21,7 +21,7 @@ import ( _ "github.com/xtls/xray-core/app/dns" _ "github.com/xtls/xray-core/app/dns/fakedns" _ "github.com/xtls/xray-core/app/log" - _ "github.com/xtls/xray-core/app/metrics" + //_ "github.com/xtls/xray-core/app/metrics" _ "github.com/xtls/xray-core/app/policy" _ "github.com/xtls/xray-core/app/reverse" _ "github.com/xtls/xray-core/app/router" diff --git a/node/task.go b/node/task.go index 6ee3c0f..0cc05de 100644 --- a/node/task.go +++ b/node/task.go @@ -55,6 +55,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { if newNodeInfo != nil { // nodeInfo changed // Remove old tag + log.Printf("[%s] Node changed, reload...", c.Tag) err = c.server.DelNode(c.Tag) if err != nil { log.Printf("[%s] Del node error: %s", c.Tag, err) @@ -107,6 +108,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { } c.nodeInfo = newNodeInfo c.userList = newUserInfo + log.Printf("[%s] Added %d new users", c.Tag, len(newUserInfo)) // exit return nil } From 040dcaca588558c40532007afaeb85d003476262 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 04:06:32 +0000 Subject: [PATCH 16/21] Bump github.com/oschwald/geoip2-golang from 1.8.0 to 1.9.0 Bumps [github.com/oschwald/geoip2-golang](https://github.com/oschwald/geoip2-golang) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/oschwald/geoip2-golang/releases) - [Commits](https://github.com/oschwald/geoip2-golang/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: github.com/oschwald/geoip2-golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8c797bf..74139b7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/goccy/go-json v0.10.2 github.com/hashicorp/go-multierror v1.1.1 github.com/juju/ratelimit v1.0.2 - github.com/oschwald/geoip2-golang v1.8.0 + github.com/oschwald/geoip2-golang v1.9.0 github.com/quic-go/quic-go v0.34.0 github.com/sagernet/sing-box v1.2.7 github.com/sirupsen/logrus v1.9.3 @@ -121,7 +121,7 @@ require ( github.com/nrdcg/porkbun v0.1.1 // indirect github.com/onsi/ginkgo/v2 v2.9.2 // indirect github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect - github.com/oschwald/maxminddb-golang v1.10.0 // indirect + github.com/oschwald/maxminddb-golang v1.11.0 // indirect github.com/ovh/go-ovh v1.1.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pion/dtls/v2 v2.2.4 // indirect diff --git a/go.sum b/go.sum index 0522074..039f90d 100644 --- a/go.sum +++ b/go.sum @@ -519,10 +519,10 @@ github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU= github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= -github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6SLNcKTs= -github.com/oschwald/geoip2-golang v1.8.0/go.mod h1:R7bRvYjOeaoenAp9sKRS8GX5bJWcZ0laWO5+DauEktw= -github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg= -github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0= +github.com/oschwald/geoip2-golang v1.9.0 h1:uvD3O6fXAXs+usU+UGExshpdP13GAqp4GBrzN7IgKZc= +github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOMi2zSFXizL3K81Y= +github.com/oschwald/maxminddb-golang v1.11.0 h1:aSXMqYR/EPNjGE8epgqwDay+P30hCBZIveY0WZbAWh0= +github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfglAFj3PuCmui13+P9zDg= github.com/ovh/go-ovh v1.1.0 h1:bHXZmw8nTgZin4Nv7JuaLs0KG5x54EQR7migYTd1zrk= github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= From eb975011b49e6196dbc75226e522dba82ef6769a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 04:02:07 +0000 Subject: [PATCH 17/21] Bump github.com/go-acme/lego/v4 from 4.12.1 to 4.12.3 Bumps [github.com/go-acme/lego/v4](https://github.com/go-acme/lego) from 4.12.1 to 4.12.3. - [Release notes](https://github.com/go-acme/lego/releases) - [Changelog](https://github.com/go-acme/lego/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-acme/lego/compare/v4.12.1...v4.12.3) --- updated-dependencies: - dependency-name: github.com/go-acme/lego/v4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8c797bf..abef7d3 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/beevik/ntp v1.1.1 github.com/folbricht/routedns v0.1.21-0.20230220022436-4ae86ce30d53 github.com/fsnotify/fsnotify v1.6.0 - github.com/go-acme/lego/v4 v4.12.1 + github.com/go-acme/lego/v4 v4.12.3 github.com/go-redis/redis/v8 v8.11.5 github.com/go-resty/resty/v2 v2.7.0 github.com/goccy/go-json v0.10.2 diff --git a/go.sum b/go.sum index 0522074..feabaf3 100644 --- a/go.sum +++ b/go.sum @@ -176,8 +176,8 @@ github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-acme/lego/v4 v4.12.1 h1:Cy3FS7wADLNBqCLpz2wdfdNrThW9rZy8RCAfnUrL2uE= -github.com/go-acme/lego/v4 v4.12.1/go.mod h1:UZoOlhVmUYP/N0z4tEbfUjoCNHRZNObzqWZtT76DIsc= +github.com/go-acme/lego/v4 v4.12.3 h1:aWPYhBopAZXWBASPgvi1LnWGrr5YiXOsrpVaFaVJipo= +github.com/go-acme/lego/v4 v4.12.3/go.mod h1:UZoOlhVmUYP/N0z4tEbfUjoCNHRZNObzqWZtT76DIsc= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= From 4d6686a11e71561a4e2fe0a9d1f249a2cfec14fd Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Tue, 20 Jun 2023 17:08:36 +0800 Subject: [PATCH 18/21] fix tls for xray --- api/panel/node.go | 2 +- common/builder/inbound.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/panel/node.go b/api/panel/node.go index a48e64c..d69a533 100644 --- a/api/panel/node.go +++ b/api/panel/node.go @@ -136,7 +136,7 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { node.UpMbps = rsp.UpMbps node.HyObfs = rsp.Obfs } - c.etag = r.Header().Get("Etag") + c.etag = r.Header().Get("ETag") return } diff --git a/common/builder/inbound.go b/common/builder/inbound.go index dc576f9..ad2b357 100644 --- a/common/builder/inbound.go +++ b/common/builder/inbound.go @@ -89,6 +89,7 @@ func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s } default: // Normal tls + in.StreamSetting.Security = "tls" in.StreamSetting.TLSSettings = &coreConf.TLSConfig{ Certs: []*coreConf.TLSCertConfig{ { From 9af5d1a6e79d6dea8c5e6bfc15aea732acc00bb5 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Sun, 25 Jun 2023 07:49:51 +0800 Subject: [PATCH 19/21] support If-None-Match --- api/panel/node.go | 7 +++++-- api/panel/node_test.go | 1 + api/panel/utils.go | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api/panel/node.go b/api/panel/node.go index d69a533..8a4ea4e 100644 --- a/api/panel/node.go +++ b/api/panel/node.go @@ -68,11 +68,14 @@ type NodeInfo struct { func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { const path = "/api/v1/server/UniProxy/config" - r, err := c.client.R().Get(path) + r, err := c.client. + R(). + SetHeader("If-None-Match", c.etag). + Get(path) if err = c.checkResponse(r, path, err); err != nil { return } - if c.etag == r.Header().Get("ETag") { // node info not changed + if r.StatusCode() == 304 { return nil, nil } // parse common params diff --git a/api/panel/node_test.go b/api/panel/node_test.go index dea16e8..570182f 100644 --- a/api/panel/node_test.go +++ b/api/panel/node_test.go @@ -23,6 +23,7 @@ func init() { func TestClient_GetNodeInfo(t *testing.T) { log.Println(client.GetNodeInfo()) + log.Println(client.GetNodeInfo()) } func TestClient_ReportUserTraffic(t *testing.T) { diff --git a/api/panel/utils.go b/api/panel/utils.go index 938bec9..74ef5b3 100644 --- a/api/panel/utils.go +++ b/api/panel/utils.go @@ -18,7 +18,7 @@ func (c *Client) checkResponse(res *resty.Response, path string, err error) erro if err != nil { return fmt.Errorf("request %s failed: %s", c.assembleURL(path), err) } - if res.StatusCode() != 200 { + if res.StatusCode() >= 400 { body := res.Body() return fmt.Errorf("request %s failed: %s", c.assembleURL(path), string(body)) } From 07b7ec9b3e691f6cbe0886276794520227ce0406 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Sun, 25 Jun 2023 08:22:05 +0800 Subject: [PATCH 20/21] use route group to storage extra config --- api/panel/node.go | 40 ++++++++++++++++++++++++++++++++------ common/builder/inbound.go | 22 ++++++++++++++++++++- common/builder/user.go | 12 ++++-------- conf/node.go | 18 ++++++++--------- core/hy/server_test.go | 18 +++++++++++++++-- core/xray/user.go | 17 ++++++++++++++-- example/config.yml.example | 2 +- 7 files changed, 100 insertions(+), 29 deletions(-) diff --git a/api/panel/node.go b/api/panel/node.go index 8a4ea4e..4d7dac1 100644 --- a/api/panel/node.go +++ b/api/panel/node.go @@ -2,6 +2,7 @@ package panel import ( "fmt" + "github.com/Yuzuki616/V2bX/conf" "github.com/goccy/go-json" "reflect" "regexp" @@ -54,6 +55,7 @@ type NodeInfo struct { Host string Port int Network string + ExtraConfig V2rayExtraConfig NetworkSettings json.RawMessage Tls bool ServerName string @@ -66,6 +68,13 @@ type NodeInfo struct { PullInterval time.Duration } +type V2rayExtraConfig struct { + EnableVless bool `json:"EnableVless"` + VlessFlow string `json:"VlessFlow"` + EnableReality bool `json:"EnableReality"` + RealityConfig conf.RealityConfig `json:"RealityConfig"` +} + func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { const path = "/api/v1/server/UniProxy/config" r, err := c.client. @@ -88,17 +97,30 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { if err != nil { return nil, fmt.Errorf("decode common params error: %s", err) } + var extra []byte for i := range common.Routes { // parse rules from routes - if common.Routes[i].Action == "block" { - var matchs []string - if _, ok := common.Routes[i].Match.(string); ok { - matchs = strings.Split(common.Routes[i].Match.(string), ",") - } else { - matchs = common.Routes[i].Match.([]string) + var matchs []string + if _, ok := common.Routes[i].Match.(string); ok { + matchs = strings.Split(common.Routes[i].Match.(string), ",") + } else if _, ok = common.Routes[i].Match.([]string); ok { + matchs = common.Routes[i].Match.([]string) + } else { + temp := common.Routes[i].Match.([]interface{}) + matchs = make([]string, len(temp)) + for i := range temp { + matchs[i] = temp[i].(string) } + } + switch common.Routes[i].Action { + case "block": for _, v := range matchs { node.Rules = append(node.Rules, regexp.MustCompile(v)) } + case "dns": + if matchs[0] != "extra" { + break + } + extra = []byte(strings.Join(matchs[1:], "")) } } node.ServerName = common.ServerName @@ -120,6 +142,12 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { if rsp.Tls == 1 { node.Tls = true } + if len(extra) != 0 { + err = json.Unmarshal(extra, &node.ExtraConfig) + if err != nil { + return nil, fmt.Errorf("decode v2ray extra error: %s", err) + } + } case "shadowsocks": rsp := ShadowsocksNodeRsp{} err = json.Unmarshal(r.Body(), &rsp) diff --git a/common/builder/inbound.go b/common/builder/inbound.go index ad2b357..e8a6d8f 100644 --- a/common/builder/inbound.go +++ b/common/builder/inbound.go @@ -102,6 +102,25 @@ func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s } } } + // use remote reality replace local config + if nodeInfo.ExtraConfig.EnableReality { + rc := nodeInfo.ExtraConfig.RealityConfig + in.StreamSetting.Security = "reality" + d, err := json.Marshal(rc.Dest) + if err != nil { + return nil, fmt.Errorf("marshal reality dest error: %s", err) + } + in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{ + Dest: d, + Xver: rc.Xver, + ServerNames: rc.ServerNames, + PrivateKey: rc.PrivateKey, + MinClientVer: rc.MinClientVer, + MaxClientVer: rc.MaxClientVer, + MaxTimeDiff: rc.MaxTimeDiff, + ShortIds: rc.ShortIds, + } + } // Support ProxyProtocol for any transport protocol if *in.StreamSetting.Network != "tcp" && *in.StreamSetting.Network != "ws" && @@ -117,7 +136,8 @@ func BuildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s } func buildV2ray(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error { - if config.XrayOptions.EnableVless { + if config.XrayOptions.EnableVless || + nodeInfo.ExtraConfig.EnableVless { //Set vless inbound.Protocol = "vless" if config.XrayOptions.EnableFallback { diff --git a/common/builder/user.go b/common/builder/user.go index 4239626..bde1c86 100644 --- a/common/builder/user.go +++ b/common/builder/user.go @@ -14,8 +14,6 @@ import ( "strings" ) -const xtlsFLow = "xtls-rprx-vision" - func BuildVmessUsers(tag string, userInfo []panel.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(userInfo)) for i, user := range userInfo { @@ -37,21 +35,19 @@ func BuildVmessUser(tag string, userInfo *panel.UserInfo) (user *protocol.User) } } -func BuildVlessUsers(tag string, userInfo []panel.UserInfo, xtls bool) (users []*protocol.User) { +func BuildVlessUsers(tag string, userInfo []panel.UserInfo, flow string) (users []*protocol.User) { users = make([]*protocol.User, len(userInfo)) for i := range userInfo { - users[i] = BuildVlessUser(tag, &(userInfo)[i], xtls) + users[i] = BuildVlessUser(tag, &(userInfo)[i], flow) } return users } -func BuildVlessUser(tag string, userInfo *panel.UserInfo, xtls bool) (user *protocol.User) { +func BuildVlessUser(tag string, userInfo *panel.UserInfo, flow string) (user *protocol.User) { vlessAccount := &vless.Account{ Id: userInfo.Uuid, } - if xtls { - vlessAccount.Flow = xtlsFLow - } + vlessAccount.Flow = flow return &protocol.User{ Level: 0, Email: BuildUserTag(tag, userInfo.Uuid), diff --git a/conf/node.go b/conf/node.go index 074f738..f8b38c9 100644 --- a/conf/node.go +++ b/conf/node.go @@ -28,7 +28,7 @@ type XrayOptions struct { EnableDNS bool `yaml:"EnableDNS"` DNSType string `yaml:"DNSType"` EnableVless bool `yaml:"EnableVless"` - EnableXtls bool `yaml:"EnableXtls"` + VlessFlow string `json:"VlessFlow"` EnableUot bool `yaml:"EnableUot"` EnableTFO bool `yaml:"EnableTFO"` DisableIVCheck bool `yaml:"DisableIVCheck"` @@ -103,12 +103,12 @@ type CertConfig struct { } type RealityConfig struct { - Dest interface{} `yaml:"Dest"` - Xver uint64 `yaml:"Xver"` - ServerNames []string `yaml:"ServerNames"` - PrivateKey string `yaml:"PrivateKey"` - MinClientVer string `yaml:"MinClientVer"` - MaxClientVer string `yaml:"MaxClientVer"` - MaxTimeDiff uint64 `yaml:"MaxTimeDiff"` - ShortIds []string `yaml:"ShortIds"` + Dest interface{} `yaml:"Dest" json:"Dest"` + Xver uint64 `yaml:"Xver" json:"Xver"` + ServerNames []string `yaml:"ServerNames" json:"ServerNames"` + PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"` + MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"` + MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"` + MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"` + ShortIds []string `yaml:"ShortIds" json:"ShortIds"` } diff --git a/core/hy/server_test.go b/core/hy/server_test.go index 95c8f9a..db16d4f 100644 --- a/core/hy/server_test.go +++ b/core/hy/server_test.go @@ -1,17 +1,23 @@ package hy import ( + "encoding/base64" "github.com/Yuzuki616/V2bX/api/panel" "github.com/Yuzuki616/V2bX/conf" + "github.com/Yuzuki616/V2bX/limiter" "github.com/sirupsen/logrus" + "log" "testing" + "time" ) func TestServer(t *testing.T) { logrus.SetLevel(logrus.DebugLevel) - s := NewServer("test") + limiter.Init() + l := limiter.AddLimiter("test", &conf.LimitConfig{}, nil) + s := NewServer("test", l) t.Log(s.runServer(&panel.NodeInfo{ - Port: 11415, + Port: 1145, UpMbps: 100, DownMbps: 100, HyObfs: "atresssdaaaadd", @@ -24,5 +30,13 @@ func TestServer(t *testing.T) { }, })) s.users.Store("test1111", struct{}{}) + go func() { + for { + time.Sleep(10 * time.Second) + auth := base64.StdEncoding.EncodeToString([]byte("test1111")) + log.Println(auth) + log.Println(s.counter.getCounters(auth).UpCounter.Load()) + } + }() select {} } diff --git a/core/xray/user.go b/core/xray/user.go index cea922b..b5cc330 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -73,11 +73,24 @@ func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) { users := make([]*protocol.User, 0, len(p.UserInfo)) switch p.NodeInfo.Type { case "v2ray": - if p.Config.XrayOptions.EnableXtls { - users = builder.BuildVlessUsers(p.Tag, p.UserInfo, true) + + if p.Config.XrayOptions.EnableVless || + p.NodeInfo.ExtraConfig.EnableVless { + + if p.Config.XrayOptions.VlessFlow != "" { + if p.Config.XrayOptions.VlessFlow == p.NodeInfo.ExtraConfig.VlessFlow { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.Config.XrayOptions.VlessFlow) + } else { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + } + + } else { + users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) + } } else { users = builder.BuildVmessUsers(p.Tag, p.UserInfo) } + case "trojan": users = builder.BuildTrojanUsers(p.Tag, p.UserInfo) case "shadowsocks": diff --git a/example/config.yml.example b/example/config.yml.example index 58f0141..697ca57 100644 --- a/example/config.yml.example +++ b/example/config.yml.example @@ -31,7 +31,7 @@ Nodes: DNSType: AsIs # AsIs, UseIP, UseIPv4, UseIPv6, DNS strategy EnableTFO: false # Enable TCP Fast Open EnableVless: false # Enable Vless for V2ray Type - EnableXtls: false # Enable xtls-rprx-vision, only vless + VlessFlow: "xtls-rprx-vision" # flow for vless, "xtls-rprx-vision" or "none" or "" EnableProxyProtocol: false # Only works for WebSocket and TCP EnableFallback: false # Only support for Trojan and Vless FallBackConfigs: # Support multiple fallbacks From 65629c0dfbe4f7a585d58956f87e64e8a38be053 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Fri, 30 Jun 2023 11:07:27 +0800 Subject: [PATCH 21/21] change log to logrus --- cmd/cmd.go | 4 +-- cmd/server.go | 30 +++++++++++++------- core/xray/user.go | 2 -- core/xray/xray.go | 31 ++++++++++---------- limiter/clear.go | 8 ++++-- limiter/limiter.go | 5 ++-- node/controller.go | 4 +-- node/task.go | 71 ++++++++++++++++++++++++++++++++++------------ node/user.go | 9 ++++-- 9 files changed, 105 insertions(+), 59 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 8bf7d47..26f9130 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,7 +1,7 @@ package cmd import ( - "log" + log "github.com/sirupsen/logrus" _ "github.com/Yuzuki616/V2bX/core/imports" "github.com/spf13/cobra" @@ -14,6 +14,6 @@ var command = &cobra.Command{ func Run() { err := command.Execute() if err != nil { - log.Println("execute failed, error:", err) + log.WithField("err", err).Error("Execute command failed") } } diff --git a/cmd/server.go b/cmd/server.go index 1542389..34ceeae 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,7 +1,7 @@ package cmd import ( - "log" + log "github.com/sirupsen/logrus" "os" "os/signal" "runtime" @@ -42,23 +42,26 @@ func serverHandle(_ *cobra.Command, _ []string) { c := conf.New() err := c.LoadFromPath(config) if err != nil { - log.Fatalf("can't unmarshal config file: %s \n", err) + log.WithField("err", err).Error("Load config file failed") + return } limiter.Init() - log.Println("Start V2bX...") + log.Info("Start V2bX...") vc, err := vCore.NewCore(&c.CoreConfig) if err != nil { - log.Fatalf("New core error: %s", err) + log.WithField("err", err).Error("new core failed") + return } err = vc.Start() if err != nil { - log.Fatalf("Start core error: %s", err) + log.WithField("err", err).Error("Start core failed") + return } defer vc.Close() nodes := node.New() err = nodes.Start(c.NodesConfig, vc) if err != nil { - log.Fatalf("Run nodes error: %s", err) + log.WithField("err", err).Error("Run nodes failed") return } if watch { @@ -66,24 +69,29 @@ func serverHandle(_ *cobra.Command, _ []string) { nodes.Close() err = vc.Close() if err != nil { - log.Fatalf("Failed to restart xray-core: %s", err) + log.WithField("err", err).Error("Restart node failed") + return } vc, err = vCore.NewCore(&c.CoreConfig) if err != nil { - log.Fatalf("New core error: %s", err) + log.WithField("err", err).Error("New core failed") + return } err = vc.Start() if err != nil { - log.Fatalf("Start core error: %s", err) + log.WithField("err", err).Error("Start core failed") + return } err = nodes.Start(c.NodesConfig, vc) if err != nil { - log.Fatalf("Run nodes error: %s", err) + log.WithField("err", err).Error("Run nodes failed") + return } runtime.GC() }) if err != nil { - log.Fatalf("Watch config file error: %s", err) + log.WithField("err", err).Error("start watch failed") + return } } // clear memory diff --git a/core/xray/user.go b/core/xray/user.go index b5cc330..b2a51e4 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -73,10 +73,8 @@ func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) { users := make([]*protocol.User, 0, len(p.UserInfo)) switch p.NodeInfo.Type { case "v2ray": - if p.Config.XrayOptions.EnableVless || p.NodeInfo.ExtraConfig.EnableVless { - if p.Config.XrayOptions.VlessFlow != "" { if p.Config.XrayOptions.VlessFlow == p.NodeInfo.ExtraConfig.VlessFlow { users = builder.BuildVlessUsers(p.Tag, p.UserInfo, p.Config.XrayOptions.VlessFlow) diff --git a/core/xray/xray.go b/core/xray/xray.go index 280eb10..2520e46 100644 --- a/core/xray/xray.go +++ b/core/xray/xray.go @@ -1,7 +1,6 @@ package xray import ( - "log" "os" "sync" @@ -10,6 +9,7 @@ import ( "github.com/Yuzuki616/V2bX/core/xray/app/dispatcher" _ "github.com/Yuzuki616/V2bX/core/xray/distro/all" "github.com/goccy/go-json" + log "github.com/sirupsen/logrus" "github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/common/serial" @@ -63,40 +63,40 @@ func getCore(c *conf.XrayConfig) *core.Instance { coreDnsConfig := &coreConf.DNSConfig{} if c.DnsConfigPath != "" { if f, err := os.Open(c.DnsConfigPath); err != nil { - log.Panicf("Failed to read DNS config file at: %s", c.DnsConfigPath) + log.WithField("err", err).Panic("Failed to read DNS config file") } else { if err = json.NewDecoder(f).Decode(coreDnsConfig); err != nil { - log.Panicf("Failed to unmarshal DNS config: %s", c.DnsConfigPath) + log.WithField("err", err).Panic("Failed to unmarshal DNS config") } } } dnsConfig, err := coreDnsConfig.Build() if err != nil { - log.Panicf("Failed to understand DNS config, Please check: https://xtls.github.io/config/dns.html for help: %s", err) + log.WithField("err", err).Panic("Failed to understand DNS config, Please check: https://xtls.github.io/config/dns.html for help") } // Routing config coreRouterConfig := &coreConf.RouterConfig{} if c.RouteConfigPath != "" { if f, err := os.Open(c.RouteConfigPath); err != nil { - log.Panicf("Failed to read Routing config file at: %s", c.RouteConfigPath) + log.WithField("err", err).Panic("Failed to read Routing config file") } else { if err = json.NewDecoder(f).Decode(coreRouterConfig); err != nil { - log.Panicf("Failed to unmarshal Routing config: %s", c.RouteConfigPath) + log.WithField("err", err).Panic("Failed to unmarshal Routing config") } } } routeConfig, err := coreRouterConfig.Build() if err != nil { - log.Panicf("Failed to understand Routing config Please check: https://xtls.github.io/config/routing.html for help: %s", err) + log.WithField("err", err).Panic("Failed to understand Routing config Please check: https://xtls.github.io/config/routing.html") } // Custom Inbound config var coreCustomInboundConfig []coreConf.InboundDetourConfig if c.InboundConfigPath != "" { if f, err := os.Open(c.InboundConfigPath); err != nil { - log.Panicf("Failed to read Custom Inbound config file at: %s", c.OutboundConfigPath) + log.WithField("err", err).Panic("Failed to read Custom Inbound config file") } else { if err = json.NewDecoder(f).Decode(&coreCustomInboundConfig); err != nil { - log.Panicf("Failed to unmarshal Custom Inbound config: %s", c.OutboundConfigPath) + log.WithField("err", err).Panic("Failed to unmarshal Custom Inbound config") } } } @@ -104,7 +104,7 @@ func getCore(c *conf.XrayConfig) *core.Instance { for _, config := range coreCustomInboundConfig { oc, err := config.Build() if err != nil { - log.Panicf("Failed to understand Inbound config, Please check: https://xtls.github.io/config/inbound.html for help: %s", err) + log.WithField("err", err).Panic("Failed to understand Inbound config, Please check: https://xtls.github.io/config/inbound.html for help") } inBoundConfig = append(inBoundConfig, oc) } @@ -112,10 +112,10 @@ func getCore(c *conf.XrayConfig) *core.Instance { var coreCustomOutboundConfig []coreConf.OutboundDetourConfig if c.OutboundConfigPath != "" { if f, err := os.Open(c.OutboundConfigPath); err != nil { - log.Panicf("Failed to read Custom Outbound config file at: %s", c.OutboundConfigPath) + log.WithField("err", err).Panic("Failed to read Custom Outbound config file") } else { if err = json.NewDecoder(f).Decode(&coreCustomOutboundConfig); err != nil { - log.Panicf("Failed to unmarshal Custom Outbound config: %s", c.OutboundConfigPath) + log.WithField("err", err).Panic("Failed to unmarshal Custom Outbound config") } } } @@ -123,7 +123,7 @@ func getCore(c *conf.XrayConfig) *core.Instance { for _, config := range coreCustomOutboundConfig { oc, err := config.Build() if err != nil { - log.Panicf("Failed to understand Outbound config, Please check: https://xtls.github.io/config/outbound.html for help: %s", err) + log.WithField("err", err).Panic("Failed to understand Outbound config, Please check: https://xtls.github.io/config/outbound.html for help") } outBoundConfig = append(outBoundConfig, oc) } @@ -149,10 +149,9 @@ func getCore(c *conf.XrayConfig) *core.Instance { } server, err := core.New(config) if err != nil { - log.Panicf("failed to create instance: %s", err) + log.WithField("err", err).Panic("failed to create instance") } - log.Printf("Core Version: %s", core.Version()) - + log.Info("Xray Core Version: ", core.Version()) return server } diff --git a/limiter/clear.go b/limiter/clear.go index 47db76f..a926854 100644 --- a/limiter/clear.go +++ b/limiter/clear.go @@ -1,14 +1,16 @@ package limiter -import "log" +import log "github.com/sirupsen/logrus" func ClearOnlineIP() error { - log.Println("Limiter: Clear online ip...") + log.WithField("Type", "Limiter"). + Debug("Clear online ip...") limitLock.RLock() for _, l := range limiter { l.ConnLimiter.ClearOnlineIP() } limitLock.RUnlock() - log.Println("Limiter: Clear online ip done") + log.WithField("Type", "Limiter"). + Debug("Clear online ip done") return nil } diff --git a/limiter/limiter.go b/limiter/limiter.go index f8faf07..45c4583 100644 --- a/limiter/limiter.go +++ b/limiter/limiter.go @@ -7,8 +7,8 @@ import ( "github.com/Yuzuki616/V2bX/common/builder" "github.com/Yuzuki616/V2bX/conf" "github.com/juju/ratelimit" + log "github.com/sirupsen/logrus" "github.com/xtls/xray-core/common/task" - "log" "regexp" "sync" "time" @@ -24,7 +24,8 @@ func Init() { Execute: ClearOnlineIP, } go func() { - log.Println("Limiter: ClearOnlineIP started") + log.WithField("Type", "Limiter"). + Debug("ClearOnlineIP started") time.Sleep(time.Minute * 2) _ = c.Start() }() diff --git a/node/controller.go b/node/controller.go index 85b0b4a..725b2ad 100644 --- a/node/controller.go +++ b/node/controller.go @@ -9,7 +9,7 @@ import ( "github.com/Yuzuki616/V2bX/conf" vCore "github.com/Yuzuki616/V2bX/core" "github.com/Yuzuki616/V2bX/limiter" - "log" + log "github.com/sirupsen/logrus" ) type Controller struct { @@ -81,7 +81,7 @@ func (c *Controller) Start() error { if err != nil { return fmt.Errorf("add users error: %s", err) } - log.Printf("[%s] Added %d new users", c.Tag, added) + log.WithField("tag", c.Tag).Infof("Added %d new users", added) c.initTask() return nil } diff --git a/node/task.go b/node/task.go index 0cc05de..d87b380 100644 --- a/node/task.go +++ b/node/task.go @@ -4,7 +4,7 @@ import ( "github.com/Yuzuki616/V2bX/common/task" vCore "github.com/Yuzuki616/V2bX/core" "github.com/Yuzuki616/V2bX/limiter" - "log" + log "github.com/sirupsen/logrus" "time" ) @@ -19,10 +19,10 @@ func (c *Controller) initTask() { Interval: c.nodeInfo.PushInterval, Execute: c.reportUserTrafficTask, } - log.Printf("[%s] Start monitor node status", c.Tag) + log.WithField("tag", c.Tag).Info("Start monitor node status") // delay to start nodeInfoMonitor _ = c.nodeInfoMonitorPeriodic.Start(false) - log.Printf("[%s] Start report node status", c.Tag) + log.WithField("tag", c.Tag).Info("Start report node status") _ = c.userReportPeriodic.Start(false) if c.nodeInfo.Tls { switch c.CertConfig.CertMode { @@ -32,7 +32,7 @@ func (c *Controller) initTask() { Interval: time.Hour * 24, Execute: c.reportUserTrafficTask, } - log.Printf("[%s] Start renew cert", c.Tag) + log.WithField("tag", c.Tag).Info("Start renew cert") // delay to start renewCert _ = c.renewCertPeriodic.Start(true) } @@ -43,22 +43,31 @@ func (c *Controller) nodeInfoMonitor() (err error) { // get node info newNodeInfo, err := c.apiClient.GetNodeInfo() if err != nil { - log.Printf("[%s] Get node info error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Get node info failed") return nil } // get user info newUserInfo, err := c.apiClient.GetUserList() if err != nil { - log.Printf("[%s] Get user list error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Get user list failed") return nil } if newNodeInfo != nil { // nodeInfo changed // Remove old tag - log.Printf("[%s] Node changed, reload...", c.Tag) + log.WithField("tag", c.Tag).Info("Node changed, reload") err = c.server.DelNode(c.Tag) if err != nil { - log.Printf("[%s] Del node error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Delete node failed") return nil } // Remove Old limiter @@ -70,13 +79,20 @@ func (c *Controller) nodeInfoMonitor() (err error) { if newNodeInfo.Tls || newNodeInfo.Type == "hysteria" { err = c.requestCert() if err != nil { - log.Printf("[%s] Request cert error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Request cert failed") + return nil } } // add new node err = c.server.AddNode(c.Tag, newNodeInfo, c.ControllerConfig) if err != nil { - log.Printf("[%s] Add node error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Add node failed") return nil } _, err = c.server.AddUsers(&vCore.AddUsersParams{ @@ -86,12 +102,19 @@ func (c *Controller) nodeInfoMonitor() (err error) { NodeInfo: newNodeInfo, }) if err != nil { - log.Printf("[%s] Add users error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Add users failed") return nil } err = l.UpdateRule(newNodeInfo.Rules) if err != nil { - log.Printf("[%s] Update Rule error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Update Rule failed") + return nil } // Check interval if c.nodeInfoMonitorPeriodic.Interval != newNodeInfo.PullInterval && @@ -108,7 +131,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { } c.nodeInfo = newNodeInfo c.userList = newUserInfo - log.Printf("[%s] Added %d new users", c.Tag, len(newUserInfo)) + log.WithField("tag", c.Tag).Infof("Added %d new users", len(newUserInfo)) // exit return nil } @@ -119,7 +142,11 @@ func (c *Controller) nodeInfoMonitor() (err error) { // have deleted users err = c.server.DelUsers(deleted, c.Tag) if err != nil { - log.Printf("[%s] Del users error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Delete users failed") + return nil } } if len(added) > 0 { @@ -131,18 +158,26 @@ func (c *Controller) nodeInfoMonitor() (err error) { NodeInfo: c.nodeInfo, }) if err != nil { - log.Printf("[%s] Add users error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Add users failed") + return nil } } if len(added) > 0 || len(deleted) > 0 { // update Limiter err = limiter.UpdateLimiter(c.Tag, added, deleted) if err != nil { - log.Printf("[%s] Update limiter error: %s", c.Tag, err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("limiter users failed") + return nil } } c.userList = newUserInfo - log.Printf("[%s] %d user deleted, %d user added", c.Tag, - len(deleted), len(added)) + log.WithField("tag", c.Tag). + Errorf("%d user deleted, %d user added", len(deleted), len(added)) return nil } diff --git a/node/user.go b/node/user.go index d832b09..b8e95cc 100644 --- a/node/user.go +++ b/node/user.go @@ -2,7 +2,7 @@ package node import ( "github.com/Yuzuki616/V2bX/api/panel" - "log" + log "github.com/sirupsen/logrus" "runtime" "strconv" ) @@ -25,9 +25,12 @@ func (c *Controller) reportUserTrafficTask() (err error) { if len(userTraffic) > 0 { err = c.apiClient.ReportUserTraffic(userTraffic) if err != nil { - log.Printf("Report user traffic faild: %s", err) + log.WithFields(log.Fields{ + "tag": c.Tag, + "err": err, + }).Error("Report user traffic faild") } else { - log.Printf("[%s] Report %d online users", c.Tag, len(userTraffic)) + log.WithField("tag", err).Errorf("Report %d online users", len(userTraffic)) } } userTraffic = nil