Compare commits

...

17 Commits

Author SHA1 Message Date
wyx2685
71277de69e fix: compile 2025-12-03 06:26:10 +09:00
wyx2685
f32c672c4d Merge branch 'dev_new' of github.com:wyx2685/V2bX into dev_new 2025-12-03 05:24:57 +09:00
LinboLen
33b7faba53 Merge pull request #120 from LinboLen/fix_limit_problem
fix: adjust rate limiting to use actual bytes transferred
2025-12-03 04:23:31 +08:00
wyx2685
8615620ce9 update xray v25.12.2 hysteria2 v2.6.4 2025-12-03 05:23:08 +09:00
wyx2685
98777eb1b5 Merge pull request #116 from darthstren/dev_new
添加 APISendIP 属性
2025-10-28 16:01:28 +08:00
darthstren
c656877311 添加 APISendIP 属性 2025-10-28 15:53:54 +08:00
wyx2685
3deccaae00 fix: sing/hy2内核流量用户为空 2025-09-20 23:15:58 +09:00
wyx2685
9bbccf772b fix: xray内核删除用户时重复加锁导致卡死 2025-09-19 01:05:50 +09:00
wyx2685
9483526f3c fix: xray内核开启splice导致限速失效 2025-09-19 00:44:21 +09:00
wyx2685
65f2de55ea fix: 流量用户为null,xray无法断开失效用户连接 2025-09-18 20:39:18 +09:00
wyx2685
4ed6bc6d87 fix mux panic 2025-09-12 16:53:21 +09:00
wyx2685
af7b473c13 update hysteria2 v2.6.3 2025-09-12 14:28:02 +09:00
wyx2685
10f66b57ea test: Add vless encryption 2025-09-12 14:26:58 +09:00
wyx2685
0824bf7a4e update README: go1.25构建指令 2025-08-23 01:10:51 +09:00
wyx2685
6e8297c553 test: 尝试启用xray splice拷贝 2025-08-22 05:22:47 +09:00
wyx2685
7d52a8932d test: update go 1.25.0 2025-08-13 21:37:42 +09:00
wyx2685
06441afa79 fix: 流量判断阈值去除=号 2025-08-07 15:46:12 +09:00
33 changed files with 924 additions and 744 deletions

View File

@@ -109,7 +109,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.24.5' go-version: '1.25.0'
- name: Get project dependencies - name: Get project dependencies
run: | run: |
@@ -126,13 +126,13 @@ jobs:
run: | run: |
echo "version: $version" echo "version: $version"
mkdir -p build_assets mkdir -p build_assets
go build -v -o build_assets/V2bX -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" -trimpath -ldflags "-X 'github.com/InazumaV/V2bX/cmd.version=$version' -s -w -buildid=" GOEXPERIMENT=jsonv2 go build -v -o build_assets/V2bX -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" -trimpath -ldflags "-X 'github.com/InazumaV/V2bX/cmd.version=$version' -s -w -buildid="
- name: Build Mips softfloat V2bX - name: Build Mips softfloat V2bX
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle' if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
run: | run: |
echo "version: $version" echo "version: $version"
GOMIPS=softfloat go build -v -o build_assets/V2bX_softfloat -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" -trimpath -ldflags "-X 'github.com/InazumaV/V2bX/cmd.version=$version' -s -w -buildid=" GOEXPERIMENT=jsonv2 GOMIPS=softfloat go build -v -o build_assets/V2bX_softfloat -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" -trimpath -ldflags "-X 'github.com/InazumaV/V2bX/cmd.version=$version' -s -w -buildid="
- name: Rename Windows V2bX - name: Rename Windows V2bX
if: matrix.goos == 'windows' if: matrix.goos == 'windows'
run: | run: |

3
.gitignore vendored
View File

@@ -14,4 +14,5 @@ example/cert
./vscode ./vscode
output/* output/*
.idea/* .idea/*
newV2bX.sh newV2bX.sh
quic_singbox.sh

View File

@@ -1,10 +1,10 @@
# Build go # Build go
FROM golang:1.24.5-alpine AS builder FROM golang:1.25.0-alpine AS builder
WORKDIR /app WORKDIR /app
COPY . . COPY . .
ENV CGO_ENABLED=0 ENV CGO_ENABLED=0
RUN go mod download RUN GOEXPERIMENT=jsonv2 go mod download
RUN go build -v -o V2bX -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" RUN GOEXPERIMENT=jsonv2 go build -v -o V2bX -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor"
# Release # Release
FROM alpine FROM alpine

View File

@@ -40,7 +40,6 @@ A V2board node server based on multi core, modified from XrayR.
## TODO ## TODO
- [ ] 重新实现动态限速 - [ ] 重新实现动态限速
- [ ] 重新实现在线IP同步跨节点在线IP限制
- [ ] 完善使用文档 - [ ] 完善使用文档
## 软件安装 ## 软件安装
@@ -58,7 +57,7 @@ wget -N https://raw.githubusercontent.com/wyx2685/V2bX-script/master/install.sh
## 构建 ## 构建
``` bash ``` bash
# 通过-tags选项指定要编译的内核 可选 xray sing, hysteria2 # 通过-tags选项指定要编译的内核 可选 xray sing, hysteria2
go build -v -o ./V2bX -tags "xray sing hysteria2 with_quic with_grpc with_utls with_wireguard with_acme" -trimpath -ldflags "-s -w -buildid=" GOEXPERIMENT=jsonv2 go build -v -o build_assets/V2bX -tags "sing xray hysteria2 with_quic with_grpc with_utls with_wireguard with_acme with_gvisor" -trimpath -ldflags "-X 'github.com/InazumaV/V2bX/cmd.version=$version' -s -w -buildid="
``` ```
## 配置文件及详细使用教程 ## 配置文件及详细使用教程
@@ -72,6 +71,10 @@ go build -v -o ./V2bX -tags "xray sing hysteria2 with_quic with_grpc with_utls w
* 本人不对任何人使用本项目造成的任何后果承担责任。 * 本人不对任何人使用本项目造成的任何后果承担责任。
* 本人比较多变,因此本项目可能会随想法或思路的变动随性更改项目结构或大规模重构代码,若不能接受请勿使用。 * 本人比较多变,因此本项目可能会随想法或思路的变动随性更改项目结构或大规模重构代码,若不能接受请勿使用。
## 赞助
[赞助链接](https://v-50.me/)
## Thanks ## Thanks
* [Project X](https://github.com/XTLS/) * [Project X](https://github.com/XTLS/)

View File

@@ -9,7 +9,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/goccy/go-json" "encoding/json"
) )
// Security type // Security type
@@ -67,6 +67,8 @@ type VAllssNode struct {
Network string `json:"network"` Network string `json:"network"`
NetworkSettings json.RawMessage `json:"network_settings"` NetworkSettings json.RawMessage `json:"network_settings"`
NetworkSettingsBack json.RawMessage `json:"networkSettings"` NetworkSettingsBack json.RawMessage `json:"networkSettings"`
Encryption string `json:"encryption"`
EncryptionSettings EncSettings `json:"encryption_settings"`
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
// vless only // vless only
@@ -84,6 +86,13 @@ type TlsSettings struct {
Xver uint64 `json:"xver,string"` Xver uint64 `json:"xver,string"`
} }
type EncSettings struct {
Mode string `json:"mode"`
Ticket string `json:"ticket"`
ServerPadding string `json:"server_padding"`
PrivateKey string `json:"private_key"`
}
type RealityConfig struct { type RealityConfig struct {
Xver uint64 `json:"Xver"` Xver uint64 `json:"Xver"`
MinClientVer string `json:"MinClientVer"` MinClientVer string `json:"MinClientVer"`

View File

@@ -3,6 +3,7 @@ package panel
import ( import (
"errors" "errors"
"fmt" "fmt"
"net"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -18,6 +19,7 @@ import (
type Client struct { type Client struct {
client *resty.Client client *resty.Client
APIHost string APIHost string
APISendIP string
Token string Token string
NodeType string NodeType string
NodeId int NodeId int
@@ -29,7 +31,14 @@ type Client struct {
} }
func New(c *conf.ApiConfig) (*Client, error) { func New(c *conf.ApiConfig) (*Client, error) {
client := resty.New() var client *resty.Client
if c.APISendIP != "" {
client = resty.NewWithLocalAddr(&net.TCPAddr{
IP: net.ParseIP(c.APISendIP),
})
} else {
client = resty.New()
}
client.SetRetryCount(3) client.SetRetryCount(3)
if c.Timeout > 0 { if c.Timeout > 0 {
client.SetTimeout(time.Duration(c.Timeout) * time.Second) client.SetTimeout(time.Duration(c.Timeout) * time.Second)
@@ -69,12 +78,13 @@ func New(c *conf.ApiConfig) (*Client, error) {
"token": c.Key, "token": c.Key,
}) })
return &Client{ return &Client{
client: client, client: client,
Token: c.Key, Token: c.Key,
APIHost: c.APIHost, APIHost: c.APIHost,
NodeType: c.NodeType, APISendIP: c.APISendIP,
NodeId: c.NodeID, NodeType: c.NodeType,
UserList: &UserListBody{}, NodeId: c.NodeID,
AliveMap: &AliveMap{}, UserList: &UserListBody{},
AliveMap: &AliveMap{},
}, nil }, nil
} }

View File

@@ -2,10 +2,11 @@ package panel
import ( import (
"fmt" "fmt"
"io"
"strings" "strings"
"github.com/goccy/go-json" "encoding/json/jsontext"
"encoding/json/v2"
"github.com/vmihailenco/msgpack/v5" "github.com/vmihailenco/msgpack/v5"
) )
@@ -56,12 +57,33 @@ func (c *Client) GetUserList() ([]UserInfo, error) {
return nil, fmt.Errorf("decode user list error: %w", err) return nil, fmt.Errorf("decode user list error: %w", err)
} }
} else { } else {
bodyBytes, err := io.ReadAll(r.RawResponse.Body) dec := jsontext.NewDecoder(r.RawResponse.Body)
if err != nil { for {
return nil, fmt.Errorf("read response body error: %w", err) tok, err := dec.ReadToken()
if err != nil {
return nil, fmt.Errorf("decode user list error: %w", err)
}
if tok.Kind() == '"' && tok.String() == "users" {
break
}
} }
if err := json.Unmarshal(bodyBytes, userlist); err != nil { tok, err := dec.ReadToken()
return nil, fmt.Errorf("unmarshal user list error: %w", err) if err != nil {
return nil, fmt.Errorf("decode user list error: %w", err)
}
if tok.Kind() != '[' {
return nil, fmt.Errorf(`decode user list error: expected "users" array`)
}
for dec.PeekKind() != ']' {
val, err := dec.ReadValue()
if err != nil {
return nil, fmt.Errorf("decode user list error: read user object: %w", err)
}
var u UserInfo
if err := json.Unmarshal(val, &u); err != nil {
return nil, fmt.Errorf("decode user list error: unmarshal user error: %w", err)
}
userlist.Users = append(userlist.Users, u)
} }
} }
c.userEtag = r.Header().Get("ETag") c.userEtag = r.Header().Get("ETag")

View File

@@ -12,7 +12,6 @@ import (
"github.com/InazumaV/V2bX/node" "github.com/InazumaV/V2bX/node"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"gopkg.in/natefinch/lumberjack.v2"
) )
var ( var (
@@ -56,14 +55,11 @@ func serverHandle(_ *cobra.Command, _ []string) {
log.SetLevel(log.ErrorLevel) log.SetLevel(log.ErrorLevel)
} }
if c.LogConfig.Output != "" { if c.LogConfig.Output != "" {
w := &lumberjack.Logger{ f, err := os.OpenFile(c.LogConfig.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
Filename: c.LogConfig.Output, if err != nil {
MaxSize: 100, log.WithField("err", err).Error("Open log file failed, using stdout instead")
MaxBackups: 3,
MaxAge: 28,
Compress: true,
} }
log.SetOutput(w) log.SetOutput(f)
} }
limiter.Init() limiter.Init()
log.Info("Start V2bX...") log.Info("Start V2bX...")
@@ -125,7 +121,7 @@ func serverHandle(_ *cobra.Command, _ []string) {
// wait exit signal // wait exit signal
{ {
osSignals := make(chan os.Signal, 1) osSignals := make(chan os.Signal, 1)
signal.Notify(osSignals, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM) signal.Notify(osSignals, syscall.SIGINT, syscall.SIGTERM)
<-osSignals <-osSignals
} }
} }

View File

@@ -0,0 +1,25 @@
package counter
import (
"sync/atomic"
fstats "github.com/xtls/xray-core/features/stats"
)
var _ fstats.Counter = (*XrayTrafficCounter)(nil)
type XrayTrafficCounter struct {
V *atomic.Int64
}
func (c *XrayTrafficCounter) Value() int64 {
return c.V.Load()
}
func (c *XrayTrafficCounter) Set(newValue int64) int64 {
return c.V.Swap(newValue)
}
func (c *XrayTrafficCounter) Add(delta int64) int64 {
return c.V.Add(delta)
}

View File

@@ -19,37 +19,17 @@ type Conn struct {
} }
func (c *Conn) Read(b []byte) (n int, err error) { func (c *Conn) Read(b []byte) (n int, err error) {
c.limiter.Wait(int64(len(b))) n, err = c.Conn.Read(b)
return c.Conn.Read(b) if n > 0 {
c.limiter.Wait(int64(n))
}
return n, err
} }
func (c *Conn) Write(b []byte) (n int, err error) { func (c *Conn) Write(b []byte) (n int, err error) {
c.limiter.Wait(int64(len(b))) n, err = c.Conn.Write(b)
return c.Conn.Write(b) if n > 0 {
} c.limiter.Wait(int64(n))
/*
type PacketConnCounter struct {
network.PacketConn
limiter *ratelimit.Bucket
}
func NewPacketConnCounter(conn network.PacketConn, l *ratelimit.Bucket) network.PacketConn {
return &PacketConnCounter{
PacketConn: conn,
limiter: l,
} }
return n, err
} }
func (p *PacketConnCounter) ReadPacket(buff *buf.Buffer) (destination M.Socksaddr, err error) {
pLen := buff.Len()
destination, err = p.PacketConn.ReadPacket(buff)
p.limiter.Wait(int64(buff.Len() - pLen))
return destination, err
}
func (p *PacketConnCounter) WritePacket(buff *buf.Buffer, destination M.Socksaddr) (err error) {
p.limiter.Wait(int64(buff.Len()))
return p.PacketConn.WritePacket(buff, destination)
}
*/

View File

@@ -5,49 +5,14 @@ import (
"time" "time"
) )
// Task is a task that runs periodically.
type Task struct { type Task struct {
// Interval of the task being run
Interval time.Duration Interval time.Duration
// Execute is the task function Execute func() error
Execute func() error access sync.Mutex
running bool
access sync.Mutex stop chan struct{}
timer *time.Timer
running bool
} }
func (t *Task) hasClosed() bool {
t.access.Lock()
defer t.access.Unlock()
return !t.running
}
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(true)
})
return nil
}
// Start implements common.Runnable.
func (t *Task) Start(first bool) error { func (t *Task) Start(first bool) error {
t.access.Lock() t.access.Lock()
if t.running { if t.running {
@@ -55,24 +20,45 @@ func (t *Task) Start(first bool) error {
return nil return nil
} }
t.running = true t.running = true
t.stop = make(chan struct{})
t.access.Unlock() t.access.Unlock()
if err := t.checkedExecute(first); err != nil {
t.access.Lock() go func() {
t.running = false if first {
t.access.Unlock() if err := t.Execute(); err != nil {
return err t.access.Lock()
} t.running = false
close(t.stop)
t.access.Unlock()
return
}
}
for {
select {
case <-time.After(t.Interval):
case <-t.stop:
return
}
if err := t.Execute(); err != nil {
t.access.Lock()
t.running = false
close(t.stop)
t.access.Unlock()
return
}
}
}()
return nil return nil
} }
// Close implements common.Closable.
func (t *Task) Close() { func (t *Task) Close() {
t.access.Lock() t.access.Lock()
defer t.access.Unlock() if t.running {
t.running = false
t.running = false close(t.stop)
if t.timer != nil {
t.timer.Stop()
t.timer = nil
} }
} t.access.Unlock()
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/InazumaV/V2bX/common/json5" "github.com/InazumaV/V2bX/common/json5"
"github.com/goccy/go-json" "encoding/json/v2"
) )
type Conf struct { type Conf struct {

View File

@@ -7,8 +7,9 @@ import (
"os" "os"
"strings" "strings"
"encoding/json"
"github.com/InazumaV/V2bX/common/json5" "github.com/InazumaV/V2bX/common/json5"
"github.com/goccy/go-json"
) )
type NodeConfig struct { type NodeConfig struct {
@@ -24,6 +25,7 @@ type rawNodeConfig struct {
type ApiConfig struct { type ApiConfig struct {
APIHost string `json:"ApiHost"` APIHost string `json:"ApiHost"`
APISendIP string `json:"ApiSendIP"`
NodeID int `json:"NodeID"` NodeID int `json:"NodeID"`
Key string `json:"ApiKey"` Key string `json:"ApiKey"`
NodeType string `json:"NodeType"` NodeType string `json:"NodeType"`

View File

@@ -11,7 +11,7 @@ var (
) )
func NewCore(c []conf.CoreConfig) (Core, error) { func NewCore(c []conf.CoreConfig) (Core, error) {
if len(c) < 0 { if len(c) == 0 {
return nil, errors.New("no have vail core") return nil, errors.New("no have vail core")
} }
// multi core // multi core

View File

@@ -7,7 +7,6 @@ import (
"github.com/InazumaV/V2bX/common/format" "github.com/InazumaV/V2bX/common/format"
"github.com/InazumaV/V2bX/limiter" "github.com/InazumaV/V2bX/limiter"
"github.com/apernet/hysteria/core/v2/server" "github.com/apernet/hysteria/core/v2/server"
quic "github.com/apernet/quic-go"
"go.uber.org/zap" "go.uber.org/zap"
) )
@@ -20,10 +19,10 @@ type HookServer struct {
ReportMinTrafficBytes int64 ReportMinTrafficBytes int64
} }
func (h *HookServer) TraceStream(stream quic.Stream, stats *server.StreamStats) { func (h *HookServer) TraceStream(stream server.HyStream, stats *server.StreamStats) {
} }
func (h *HookServer) UntraceStream(stream quic.Stream) { func (h *HookServer) UntraceStream(stream server.HyStream) {
} }
func (h *HookServer) LogTraffic(id string, tx, rx uint64) (ok bool) { func (h *HookServer) LogTraffic(id string, tx, rx uint64) (ok bool) {

View File

@@ -45,6 +45,10 @@ func (h *Hysteria2) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeIn
var wg sync.WaitGroup var wg sync.WaitGroup
for _, user := range users { for _, user := range users {
wg.Add(1) wg.Add(1)
if v, ok := h.Hy2nodes[tag].TrafficLogger.(*HookServer).Counter.Load(tag); ok {
c := v.(*counter.TrafficCounter)
c.Delete(user.Uuid)
}
go func(u panel.UserInfo) { go func(u panel.UserInfo) {
defer wg.Done() defer wg.Done()
h.Auth.mutex.Lock() h.Auth.mutex.Lock()
@@ -71,11 +75,15 @@ func (h *Hysteria2) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTra
traffic := value.(*counter.TrafficStorage) traffic := value.(*counter.TrafficStorage)
up := traffic.UpCounter.Load() up := traffic.UpCounter.Load()
down := traffic.DownCounter.Load() down := traffic.DownCounter.Load()
if up+down >= hook.ReportMinTrafficBytes { if up+down > hook.ReportMinTrafficBytes {
if reset { if reset {
traffic.UpCounter.Store(0) traffic.UpCounter.Store(0)
traffic.DownCounter.Store(0) traffic.DownCounter.Store(0)
} }
if h.Auth.usersMap[uuid] == 0 {
c.Delete(uuid)
return true
}
trafficSlice = append(trafficSlice, panel.UserTraffic{ trafficSlice = append(trafficSlice, panel.UserTraffic{
UID: h.Auth.usersMap[uuid], UID: h.Auth.usersMap[uuid],
Upload: up, Upload: up,

View File

@@ -6,8 +6,6 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/hashicorp/go-multierror"
"github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"
) )
@@ -50,14 +48,13 @@ func (s *Selector) Start() error {
} }
func (s *Selector) Close() error { func (s *Selector) Close() error {
var errs error var errs []error
for i := range s.cores { for i := range s.cores {
err := s.cores[i].Close() if err := s.cores[i].Close(); err != nil {
if err != nil { errs = append(errs, err)
errs = multierror.Append(errs, err)
} }
} }
return errs return errors.Join(errs...)
} }
func isSupported(protocol string, protocols []string) bool { func isSupported(protocol string, protocols []string) bool {

View File

@@ -10,9 +10,10 @@ import (
"strings" "strings"
"time" "time"
"encoding/json"
"github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"
"github.com/goccy/go-json"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
F "github.com/sagernet/sing/common/format" F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/json/badoption" "github.com/sagernet/sing/common/json/badoption"

View File

@@ -146,11 +146,15 @@ func (b *Sing) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic,
traffic := value.(*counter.TrafficStorage) traffic := value.(*counter.TrafficStorage)
up := traffic.UpCounter.Load() up := traffic.UpCounter.Load()
down := traffic.DownCounter.Load() down := traffic.DownCounter.Load()
if up+down >= b.nodeReportMinTrafficBytes[tag] { if up+down > b.nodeReportMinTrafficBytes[tag] {
if reset { if reset {
traffic.UpCounter.Store(0) traffic.UpCounter.Store(0)
traffic.DownCounter.Store(0) traffic.DownCounter.Store(0)
} }
if b.users.uidMap[uuid] == 0 {
c.Delete(uuid)
return true
}
trafficSlice = append(trafficSlice, panel.UserTraffic{ trafficSlice = append(trafficSlice, panel.UserTraffic{
UID: b.users.uidMap[uuid], UID: b.users.uidMap[uuid],
Upload: up, Upload: up,
@@ -199,6 +203,10 @@ func (b *Sing) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo
b.users.mapLock.Lock() b.users.mapLock.Lock()
defer b.users.mapLock.Unlock() defer b.users.mapLock.Unlock()
for i := range users { for i := range users {
if v, ok := b.hookServer.counter.Load(tag); ok {
c := v.(*counter.TrafficCounter)
c.Delete(users[i].Uuid)
}
delete(b.users.uidMap, users[i].Uuid) delete(b.users.uidMap, users[i].Uuid)
uuids[i] = users[i].Uuid uuids[i] = users[i].Uuid
} }

View File

@@ -0,0 +1,37 @@
package dispatcher
import (
"sync/atomic"
"time"
"github.com/xtls/xray-core/common/buf"
)
var _ buf.TimeoutReader = (*CounterReader)(nil)
type CounterReader struct {
Reader buf.TimeoutReader
Counter *atomic.Int64
}
func (c *CounterReader) ReadMultiBufferTimeout(time.Duration) (buf.MultiBuffer, error) {
mb, err := c.Reader.ReadMultiBufferTimeout(time.Second)
if err != nil {
return nil, err
}
if mb.Len() > 0 {
c.Counter.Add(int64(mb.Len()))
}
return mb, nil
}
func (c *CounterReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
mb, err := c.Reader.ReadMultiBuffer()
if err != nil {
return nil, err
}
if mb.Len() > 0 {
c.Counter.Add(int64(mb.Len()))
}
return mb, nil
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/InazumaV/V2bX/common/rate" "github.com/InazumaV/V2bX/common/rate"
"github.com/InazumaV/V2bX/limiter" "github.com/InazumaV/V2bX/limiter"
"github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -36,7 +37,7 @@ var errSniffingTimeout = errors.New("timeout on sniffing")
type cachedReader struct { type cachedReader struct {
sync.Mutex sync.Mutex
reader *pipe.Reader reader buf.TimeoutReader
cache buf.MultiBuffer cache buf.MultiBuffer
} }
@@ -94,18 +95,20 @@ func (r *cachedReader) Interrupt() {
r.cache = buf.ReleaseMulti(r.cache) r.cache = buf.ReleaseMulti(r.cache)
} }
r.Unlock() r.Unlock()
r.reader.Interrupt() if p, ok := r.reader.(*pipe.Reader); ok {
p.Interrupt()
}
} }
// DefaultDispatcher is a default implementation of Dispatcher. // DefaultDispatcher is a default implementation of Dispatcher.
type DefaultDispatcher struct { type DefaultDispatcher struct {
ohm outbound.Manager ohm outbound.Manager
router routing.Router router routing.Router
policy policy.Manager policy policy.Manager
stats stats.Manager stats stats.Manager
fdns dns.FakeDNSEngine fdns dns.FakeDNSEngine
Wm *WriterManager Counter sync.Map
Counter sync.Map LinkManagers sync.Map // map[string]*LinkManager
} }
func init() { func init() {
@@ -129,9 +132,6 @@ func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router rou
d.router = router d.router = router
d.policy = pm d.policy = pm
d.stats = sm d.stats = sm
d.Wm = &WriterManager{
writers: make(map[string]map[*ManagedWriter]struct{}),
}
return nil return nil
} }
@@ -167,7 +167,6 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (*
var user *protocol.MemoryUser var user *protocol.MemoryUser
if sessionInbound != nil { if sessionInbound != nil {
user = sessionInbound.User user = sessionInbound.User
sessionInbound.CanSpliceCopy = 3
} }
var limit *limiter.Limiter var limit *limiter.Limiter
@@ -195,14 +194,23 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (*
common.Interrupt(inboundLink.Reader) common.Interrupt(inboundLink.Reader)
return nil, nil, nil, errors.New("Limited ", user.Email, " by conn or ip") return nil, nil, nil, errors.New("Limited ", user.Email, " by conn or ip")
} }
var lm *LinkManager
if lmloaded, ok := d.LinkManagers.Load(user.Email); !ok {
lm = &LinkManager{
links: make(map[*ManagedWriter]buf.Reader),
}
d.LinkManagers.Store(user.Email, lm)
} else {
lm = lmloaded.(*LinkManager)
}
managedWriter := &ManagedWriter{ managedWriter := &ManagedWriter{
writer: uplinkWriter, writer: uplinkWriter,
email: user.Email, manager: lm,
manager: d.Wm,
} }
d.Wm.AddWriter(managedWriter) lm.AddLink(managedWriter, outboundLink.Reader)
inboundLink.Writer = managedWriter inboundLink.Writer = managedWriter
if w != nil { if w != nil {
sessionInbound.CanSpliceCopy = 3
inboundLink.Writer = rate.NewRateLimitWriter(inboundLink.Writer, w) inboundLink.Writer = rate.NewRateLimitWriter(inboundLink.Writer, w)
outboundLink.Writer = rate.NewRateLimitWriter(outboundLink.Writer, w) outboundLink.Writer = rate.NewRateLimitWriter(outboundLink.Writer, w)
} }
@@ -214,13 +222,15 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (*
t = c.(*counter.TrafficCounter) t = c.(*counter.TrafficCounter)
} }
inboundLink.Writer = &UploadTrafficWriter{ ts := t.GetCounter(user.Email)
Counter: t.GetCounter(user.Email), upcounter := &counter.XrayTrafficCounter{V: &ts.UpCounter}
downcounter := &counter.XrayTrafficCounter{V: &ts.DownCounter}
inboundLink.Writer = &dispatcher.SizeStatWriter{
Counter: upcounter,
Writer: inboundLink.Writer, Writer: inboundLink.Writer,
} }
outboundLink.Writer = &dispatcher.SizeStatWriter{
outboundLink.Writer = &DownloadTrafficWriter{ Counter: downcounter,
Counter: t.GetCounter(user.Email),
Writer: outboundLink.Writer, Writer: outboundLink.Writer,
} }
} }
@@ -350,12 +360,79 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
content = new(session.Content) content = new(session.Content)
ctx = session.ContextWithContent(ctx, content) ctx = session.ContextWithContent(ctx, content)
} }
sessionInbound := session.InboundFromContext(ctx)
var user *protocol.MemoryUser
if sessionInbound != nil {
user = sessionInbound.User
}
var limit *limiter.Limiter
var err error
if user != nil && len(user.Email) > 0 {
limit, err = limiter.GetLimiter(sessionInbound.Tag)
if err != nil {
errors.LogInfo(ctx, "get limiter ", sessionInbound.Tag, " error: ", err)
common.Close(outbound.Writer)
common.Interrupt(outbound.Reader)
return errors.New("get limiter ", sessionInbound.Tag, " error: ", err)
}
// Speed Limit and Device Limit
w, reject := limit.CheckLimit(user.Email,
sessionInbound.Source.Address.IP().String(),
destination.Network == net.Network_TCP,
sessionInbound.Source.Network == net.Network_TCP)
if reject {
errors.LogInfo(ctx, "Limited ", user.Email, " by conn or ip")
common.Close(outbound.Writer)
common.Interrupt(outbound.Reader)
return errors.New("Limited ", user.Email, " by conn or ip")
}
var lm *LinkManager
if lmloaded, ok := d.LinkManagers.Load(user.Email); !ok {
lm = &LinkManager{
links: make(map[*ManagedWriter]buf.Reader),
}
d.LinkManagers.Store(user.Email, lm)
} else {
lm = lmloaded.(*LinkManager)
}
managedWriter := &ManagedWriter{
writer: outbound.Writer,
manager: lm,
}
outbound.Writer = managedWriter
if w != nil {
sessionInbound.CanSpliceCopy = 3
outbound.Writer = rate.NewRateLimitWriter(outbound.Writer, w)
}
var t *counter.TrafficCounter
if c, ok := d.Counter.Load(sessionInbound.Tag); !ok {
t = counter.NewTrafficCounter()
d.Counter.Store(sessionInbound.Tag, t)
} else {
t = c.(*counter.TrafficCounter)
}
ts := t.GetCounter(user.Email)
downcounter := &counter.XrayTrafficCounter{V: &ts.DownCounter}
outbound.Reader = &CounterReader{
Reader: &buf.TimeoutWrapperReader{Reader: outbound.Reader},
Counter: &ts.UpCounter,
}
lm.AddLink(managedWriter, outbound.Reader)
outbound.Writer = &dispatcher.SizeStatWriter{
Counter: downcounter,
Writer: outbound.Writer,
}
}
sniffingRequest := content.SniffingRequest sniffingRequest := content.SniffingRequest
if !sniffingRequest.Enabled { if !sniffingRequest.Enabled {
d.routedDispatch(ctx, outbound, destination, nil, "") d.routedDispatch(ctx, outbound, destination, limit, "")
} else { } else {
cReader := &cachedReader{ cReader := &cachedReader{
reader: outbound.Reader.(*pipe.Reader), reader: outbound.Reader.(buf.TimeoutReader),
} }
outbound.Reader = cReader outbound.Reader = cReader
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network) result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
@@ -380,7 +457,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
ob.Target = destination ob.Target = destination
} }
} }
d.routedDispatch(ctx, outbound, destination, nil, content.Protocol) d.routedDispatch(ctx, outbound, destination, limit, content.Protocol)
} }
return nil return nil
@@ -515,6 +592,9 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
handler = h handler = h
} else { } else {
errors.LogWarning(ctx, "non existing outTag: ", outTag) errors.LogWarning(ctx, "non existing outTag: ", outTag)
common.Close(link.Writer)
common.Interrupt(link.Reader)
return // DO NOT CHANGE: the traffic shouldn't be processed by default outbound if the specified outbound tag doesn't exist (yet), e.g., VLESS Reverse Proxy
} }
} else { } else {
errors.LogInfo(ctx, "default route for ", destination) errors.LogInfo(ctx, "default route for ", destination)

View File

@@ -7,48 +7,9 @@ import (
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
) )
type WriterManager struct {
writers map[string]map[*ManagedWriter]struct{}
mu sync.Mutex
}
func (m *WriterManager) AddWriter(writer *ManagedWriter) {
m.mu.Lock()
defer m.mu.Unlock()
if _, exists := m.writers[writer.email]; !exists {
m.writers[writer.email] = make(map[*ManagedWriter]struct{})
}
m.writers[writer.email][writer] = struct{}{}
}
func (m *WriterManager) RemoveWriter(writer *ManagedWriter) {
m.mu.Lock()
defer m.mu.Unlock()
if _, exists := m.writers[writer.email]; !exists {
return
}
delete(m.writers[writer.email], writer)
}
func (m *WriterManager) RemoveWritersForUser(email string) {
m.mu.Lock()
defer m.mu.Unlock()
if _, exists := m.writers[email]; !exists {
return
}
for writer := range m.writers[email] {
delete(m.writers[email], writer)
common.Close(writer.writer)
}
delete(m.writers, email)
}
type ManagedWriter struct { type ManagedWriter struct {
writer buf.Writer writer buf.Writer
email string manager *LinkManager
manager *WriterManager
} }
func (w *ManagedWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { func (w *ManagedWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
@@ -59,3 +20,27 @@ func (w *ManagedWriter) Close() error {
w.manager.RemoveWriter(w) w.manager.RemoveWriter(w)
return common.Close(w.writer) return common.Close(w.writer)
} }
type LinkManager struct {
links map[*ManagedWriter]buf.Reader
mu sync.Mutex
}
func (m *LinkManager) AddLink(writer *ManagedWriter, reader buf.Reader) {
m.mu.Lock()
defer m.mu.Unlock()
m.links[writer] = reader
}
func (m *LinkManager) RemoveWriter(writer *ManagedWriter) {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.links, writer)
}
func (m *LinkManager) CloseAll() {
for w, r := range m.links {
common.Close(w)
common.Interrupt(r)
}
}

View File

@@ -1,43 +0,0 @@
package dispatcher
import (
"github.com/InazumaV/V2bX/common/counter"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
)
type UploadTrafficWriter struct {
Counter *counter.TrafficStorage
Writer buf.Writer
}
type DownloadTrafficWriter struct {
Counter *counter.TrafficStorage
Writer buf.Writer
}
func (w *UploadTrafficWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
w.Counter.UpCounter.Add(int64(mb.Len()))
return w.Writer.WriteMultiBuffer(mb)
}
func (w *UploadTrafficWriter) Close() error {
return common.Close(w.Writer)
}
func (w *UploadTrafficWriter) Interrupt() {
common.Interrupt(w.Writer)
}
func (w *DownloadTrafficWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
w.Counter.DownCounter.Add(int64(mb.Len()))
return w.Writer.WriteMultiBuffer(mb)
}
func (w *DownloadTrafficWriter) Close() error {
return common.Close(w.Writer)
}
func (w *DownloadTrafficWriter) Interrupt() {
common.Interrupt(w.Writer)
}

View File

@@ -1,44 +0,0 @@
package dispatcher_test
import (
"testing"
. "github.com/xtls/xray-core/app/dispatcher"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
)
type TestCounter int64
func (c *TestCounter) Value() int64 {
return int64(*c)
}
func (c *TestCounter) Add(v int64) int64 {
x := int64(*c) + v
*c = TestCounter(x)
return x
}
func (c *TestCounter) Set(v int64) int64 {
*c = TestCounter(v)
return v
}
func TestStatsWriter(t *testing.T) {
var c TestCounter
writer := &SizeStatWriter{
Counter: &c,
Writer: buf.Discard,
}
mb := buf.MergeBytes(nil, []byte("abcd"))
common.Must(writer.WriteMultiBuffer(mb))
mb = buf.MergeBytes(nil, []byte("efg"))
common.Must(writer.WriteMultiBuffer(mb))
if c.Value() != 7 {
t.Fatal("unexpected counter value. want 7, but got ", c.Value())
}
}

View File

@@ -7,8 +7,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"encoding/json"
"github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/api/panel"
"github.com/goccy/go-json"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
coreConf "github.com/xtls/xray-core/infra/conf" coreConf "github.com/xtls/xray-core/infra/conf"
) )

View File

@@ -6,11 +6,13 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"strings"
"time" "time"
"encoding/json"
"github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"
"github.com/goccy/go-json"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
coreConf "github.com/xtls/xray-core/infra/conf" coreConf "github.com/xtls/xray-core/infra/conf"
@@ -170,8 +172,27 @@ func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreCon
inbound.Settings = (*json.RawMessage)(&s) inbound.Settings = (*json.RawMessage)(&s)
} else { } else {
var err error var err error
decryption := "none"
if nodeInfo.VAllss.Encryption != "" {
switch nodeInfo.VAllss.Encryption {
case "mlkem768x25519plus":
encSettings := nodeInfo.VAllss.EncryptionSettings
parts := []string{
"mlkem768x25519plus",
encSettings.Mode,
encSettings.Ticket,
}
if encSettings.ServerPadding != "" {
parts = append(parts, encSettings.ServerPadding)
}
parts = append(parts, encSettings.PrivateKey)
decryption = strings.Join(parts, ".")
default:
return fmt.Errorf("vless decryption method %s is not support", nodeInfo.VAllss.Encryption)
}
}
s, err := json.Marshal(&coreConf.VLessInboundConfig{ s, err := json.Marshal(&coreConf.VLessInboundConfig{
Decryption: "none", Decryption: decryption,
}) })
if err != nil { if err != nil {
return fmt.Errorf("marshal vless config error: %s", err) return fmt.Errorf("marshal vless config error: %s", err)

View File

@@ -3,8 +3,9 @@ package xray
import ( import (
"fmt" "fmt"
"encoding/json"
conf2 "github.com/InazumaV/V2bX/conf" conf2 "github.com/InazumaV/V2bX/conf"
"github.com/goccy/go-json"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf" "github.com/xtls/xray-core/infra/conf"
) )

View File

@@ -8,6 +8,7 @@ import (
"github.com/InazumaV/V2bX/common/counter" "github.com/InazumaV/V2bX/common/counter"
"github.com/InazumaV/V2bX/common/format" "github.com/InazumaV/V2bX/common/format"
vCore "github.com/InazumaV/V2bX/core" vCore "github.com/InazumaV/V2bX/core"
"github.com/InazumaV/V2bX/core/xray/app/dispatcher"
"github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/proxy"
) )
@@ -43,8 +44,15 @@ func (c *Xray) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeInfo) e
return err return err
} }
delete(c.users.uidMap, user) delete(c.users.uidMap, user)
c.dispatcher.Counter.Delete(user) if v, ok := c.dispatcher.Counter.Load(tag); ok {
c.dispatcher.Wm.RemoveWritersForUser(user) tc := v.(*counter.TrafficCounter)
tc.Delete(user)
}
if v, ok := c.dispatcher.LinkManagers.Load(user); ok {
lm := v.(*dispatcher.LinkManager)
lm.CloseAll()
c.dispatcher.LinkManagers.Delete(user)
}
} }
return nil return nil
} }
@@ -60,11 +68,15 @@ func (x *Xray) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic,
traffic := value.(*counter.TrafficStorage) traffic := value.(*counter.TrafficStorage)
up := traffic.UpCounter.Load() up := traffic.UpCounter.Load()
down := traffic.DownCounter.Load() down := traffic.DownCounter.Load()
if up+down >= x.nodeReportMinTrafficBytes[tag] { if up+down > x.nodeReportMinTrafficBytes[tag] {
if reset { if reset {
traffic.UpCounter.Store(0) traffic.UpCounter.Store(0)
traffic.DownCounter.Store(0) traffic.DownCounter.Store(0)
} }
if x.users.uidMap[email] == 0 {
c.Delete(email)
return true
}
trafficSlice = append(trafficSlice, panel.UserTraffic{ trafficSlice = append(trafficSlice, panel.UserTraffic{
UID: x.users.uidMap[email], UID: x.users.uidMap[email],
Upload: up, Upload: up,

View File

@@ -5,11 +5,12 @@ import (
"os" "os"
"sync" "sync"
"encoding/json/v2"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"
vCore "github.com/InazumaV/V2bX/core" vCore "github.com/InazumaV/V2bX/core"
"github.com/InazumaV/V2bX/core/xray/app/dispatcher" "github.com/InazumaV/V2bX/core/xray/app/dispatcher"
_ "github.com/InazumaV/V2bX/core/xray/distro/all" _ "github.com/InazumaV/V2bX/core/xray/distro/all"
"github.com/goccy/go-json"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/app/stats" "github.com/xtls/xray-core/app/stats"
@@ -18,7 +19,6 @@ import (
"github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/inbound"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
statsFeature "github.com/xtls/xray-core/features/stats"
coreConf "github.com/xtls/xray-core/infra/conf" coreConf "github.com/xtls/xray-core/infra/conf"
) )
@@ -34,7 +34,6 @@ type Xray struct {
Server *core.Instance Server *core.Instance
ihm inbound.Manager ihm inbound.Manager
ohm outbound.Manager ohm outbound.Manager
shm statsFeature.Manager
dispatcher *dispatcher.DefaultDispatcher dispatcher *dispatcher.DefaultDispatcher
users *UserMap users *UserMap
nodeReportMinTrafficBytes map[string]int64 nodeReportMinTrafficBytes map[string]int64
@@ -187,7 +186,6 @@ func (c *Xray) Start() error {
if err := c.Server.Start(); err != nil { if err := c.Server.Start(); err != nil {
return err return err
} }
c.shm = c.Server.GetFeature(statsFeature.ManagerType()).(statsFeature.Manager)
c.ihm = c.Server.GetFeature(inbound.ManagerType()).(inbound.Manager) c.ihm = c.Server.GetFeature(inbound.ManagerType()).(inbound.Manager)
c.ohm = c.Server.GetFeature(outbound.ManagerType()).(outbound.Manager) c.ohm = c.Server.GetFeature(outbound.ManagerType()).(outbound.Manager)
c.dispatcher = c.Server.GetFeature(routing.DispatcherType()).(*dispatcher.DefaultDispatcher) c.dispatcher = c.Server.GetFeature(routing.DispatcherType()).(*dispatcher.DefaultDispatcher)
@@ -200,7 +198,6 @@ func (c *Xray) Close() error {
defer c.access.Unlock() defer c.access.Unlock()
c.ihm = nil c.ihm = nil
c.ohm = nil c.ohm = nil
c.shm = nil
c.dispatcher = nil c.dispatcher = nil
err := c.Server.Close() err := c.Server.Close()
if err != nil { if err != nil {

283
go.mod
View File

@@ -1,174 +1,174 @@
module github.com/InazumaV/V2bX module github.com/InazumaV/V2bX
go 1.24 go 1.25
toolchain go1.24.5 toolchain go1.25.0
require ( require (
github.com/apernet/hysteria/core/v2 v2.6.2 github.com/apernet/hysteria/core/v2 v2.6.4
github.com/apernet/hysteria/extras/v2 v2.6.2 github.com/apernet/hysteria/extras/v2 v2.6.4
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431
github.com/beevik/ntp v1.4.4-0.20240716062501-06ef196b89ec github.com/beevik/ntp v1.4.4-0.20240716062501-06ef196b89ec
github.com/fsnotify/fsnotify v1.8.0 github.com/fsnotify/fsnotify v1.9.0
github.com/go-acme/lego/v4 v4.21.1-0.20241220151055-ee7a9e4fa04f github.com/go-acme/lego/v4 v4.25.2
github.com/go-resty/resty/v2 v2.16.2 github.com/go-resty/resty/v2 v2.16.5
github.com/goccy/go-json v0.10.4
github.com/hashicorp/go-multierror v1.1.2-0.20241119060415-613124da9385
github.com/juju/ratelimit v1.0.2 github.com/juju/ratelimit v1.0.2
github.com/sagernet/sing v0.7.0-beta.2 github.com/sagernet/sing v0.8.0-beta.6
github.com/sagernet/sing-box v1.12.0 github.com/sagernet/sing-box v1.13.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0 github.com/spf13/viper v1.19.0
github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/vmihailenco/msgpack/v5 v5.4.1
github.com/xtls/xray-core v1.250803.0 github.com/xtls/xray-core v1.251202.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/crypto v0.40.0 golang.org/x/crypto v0.44.0
golang.org/x/sys v0.34.0 golang.org/x/sys v0.38.0
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.10
gopkg.in/natefinch/lumberjack.v2 v2.2.1
) )
require ( require (
cloud.google.com/go/auth v0.13.0 // indirect cloud.google.com/go/auth v0.16.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.7.0 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect github.com/Azure/go-autorest/autorest v0.11.30 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/Azure/go-autorest/autorest/to v0.4.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
github.com/akutz/memconn v0.1.0 // indirect github.com/akutz/memconn v0.1.0 // indirect
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.63.72 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.8 // indirect
github.com/alibabacloud-go/debug v1.0.1 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
github.com/alibabacloud-go/tea v1.3.9 // indirect
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
github.com/aliyun/credentials-go v1.4.6 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/anytls/sing-anytls v0.0.9-0.20250508103614-8bc6dd599731 // indirect github.com/anthropics/anthropic-sdk-go v1.14.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.7 // indirect github.com/anytls/sing-anytls v0.0.11 // indirect
github.com/aws/aws-sdk-go-v2/config v1.28.7 // indirect github.com/apernet/quic-go v0.54.1-0.20250907230547-eb32f8aec5e2 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.48 // indirect github.com/aws/aws-sdk-go-v2 v1.36.6 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 // indirect github.com/aws/aws-sdk-go-v2/config v1.29.18 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.8 // indirect github.com/aws/aws-sdk-go-v2/service/lightsail v1.43.5 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.53.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect
github.com/aws/smithy-go v1.22.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect
github.com/aws/smithy-go v1.22.4 // indirect
github.com/aziontech/azionapi-go-sdk v0.142.0 // indirect
github.com/baidubce/bce-sdk-go v0.9.235 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/caddyserver/certmagic v0.23.0 // indirect github.com/caddyserver/certmagic v0.23.0 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/civo/civogo v0.3.11 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudflare/circl v1.6.1 // indirect
github.com/cloudflare/cloudflare-go v0.112.0 // indirect
github.com/coder/websocket v1.8.13 // indirect github.com/coder/websocket v1.8.13 // indirect
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cretz/bine v0.2.0 // indirect github.com/cretz/bine v0.2.0 // indirect
github.com/database64128/netx-go v0.0.0-20240905055117-62795b8b054a // indirect github.com/database64128/netx-go v0.1.1 // indirect
github.com/database64128/tfo-go/v2 v2.2.2 // indirect github.com/database64128/tfo-go/v2 v2.3.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v1.7.0 // indirect github.com/dnsimple/dnsimple-go/v4 v4.0.0 // indirect
github.com/exoscale/egoscale/v3 v3.1.7 // indirect github.com/exoscale/egoscale/v3 v3.1.24 // indirect
github.com/fatih/structs v1.1.0 // indirect github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gaissmai/bart v0.11.1 // indirect github.com/gaissmai/bart v0.18.0 // indirect
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect
github.com/go-acme/alidns-20150109/v4 v4.5.10 // indirect
github.com/go-acme/tencentclouddnspod v1.0.1208 // indirect
github.com/go-chi/chi/v5 v5.2.2 // indirect github.com/go-chi/chi/v5 v5.2.2 // indirect
github.com/go-chi/render v1.0.3 // indirect github.com/go-chi/render v1.0.3 // indirect
github.com/go-errors/errors v1.0.1 // indirect github.com/go-errors/errors v1.0.1 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // indirect github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.16.0 // indirect github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/pool v0.2.1 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
github.com/gofrs/flock v0.12.1 // indirect github.com/gofrs/flock v0.12.1 // indirect
github.com/gofrs/uuid/v5 v5.3.2 // indirect github.com/gofrs/uuid/v5 v5.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect github.com/google/s2a-go v0.1.9 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/gophercloud/gophercloud v1.14.1 // indirect github.com/gophercloud/gophercloud v1.14.1 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect github.com/hashicorp/yamux v0.1.2 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.128 // indirect github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.159 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/illarion/gonotify/v2 v2.0.3 // indirect github.com/illarion/gonotify/v3 v3.0.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f // indirect github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.0 // indirect github.com/jsimonetti/rtnetlink v1.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/keybase/go-keychain v0.0.1 // indirect
github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
github.com/kylelemons/godebug v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect github.com/labbsr0x/goh v1.0.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/libdns/alidns v1.0.5-libdns.v1.beta1 // indirect github.com/libdns/alidns v1.0.5-libdns.v1.beta1 // indirect
github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6 // indirect github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6 // indirect
github.com/libdns/libdns v1.1.0 // indirect github.com/libdns/libdns v1.1.0 // indirect
github.com/linode/linodego v1.44.0 // indirect github.com/linode/linodego v1.53.0 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
@@ -178,32 +178,31 @@ require (
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
github.com/mdlayher/sdnotify v1.0.0 // indirect github.com/mdlayher/sdnotify v1.0.0 // indirect
github.com/mdlayher/socket v0.5.1 // indirect github.com/mdlayher/socket v0.5.1 // indirect
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 // indirect github.com/metacubex/utls v1.8.3 // indirect
github.com/metacubex/utls v1.8.0 // indirect
github.com/mholt/acmez/v3 v3.1.2 // indirect github.com/mholt/acmez/v3 v3.1.2 // indirect
github.com/miekg/dns v1.1.67 // indirect github.com/miekg/dns v1.1.68 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect github.com/namedotcom/go/v4 v4.0.2 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/bunny-go v0.0.0-20240207213615-dde5bf4577a3 // indirect github.com/nrdcg/bunny-go v0.0.0-20250327222614-988a091fc7ea // indirect
github.com/nrdcg/desec v0.10.0 // indirect github.com/nrdcg/desec v0.11.0 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.3.0 // indirect github.com/nrdcg/freemyip v0.3.0 // indirect
github.com/nrdcg/goinwx v0.10.0 // indirect github.com/nrdcg/goacmedns v0.2.0 // indirect
github.com/nrdcg/goinwx v0.11.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/oci-go-sdk/common/v1065 v1065.95.2 // indirect
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.95.2 // indirect
github.com/nrdcg/porkbun v0.4.0 // indirect github.com/nrdcg/porkbun v0.4.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/ovh/go-ovh v1.9.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oracle/oci-go-sdk/v65 v65.81.1 // indirect
github.com/ovh/go-ovh v1.6.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/peterhellberg/link v1.2.0 // indirect github.com/peterhellberg/link v1.2.0 // indirect
@@ -212,64 +211,67 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pquerna/otp v1.4.0 // indirect github.com/pquerna/otp v1.5.0 // indirect
github.com/prometheus-community/pro-bing v0.4.0 // indirect github.com/prometheus-community/pro-bing v0.4.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect github.com/quic-go/quic-go v0.56.0 // indirect
github.com/refraction-networking/utls v1.8.0 // indirect github.com/refraction-networking/utls v1.8.1 // indirect
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sacloud/api-client-go v0.2.10 // indirect github.com/sacloud/api-client-go v0.3.2 // indirect
github.com/sacloud/go-http v0.1.8 // indirect github.com/sacloud/go-http v0.1.9 // indirect
github.com/sacloud/iaas-api-go v1.14.0 // indirect github.com/sacloud/iaas-api-go v1.16.1 // indirect
github.com/sacloud/packages-go v0.0.10 // indirect github.com/sacloud/packages-go v0.0.11 // indirect
github.com/safchain/ethtool v0.3.0 // indirect github.com/safchain/ethtool v0.3.0 // indirect
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
github.com/sagernet/cors v1.2.1 // indirect github.com/sagernet/cors v1.2.1 // indirect
github.com/sagernet/fswatch v0.1.1 // indirect github.com/sagernet/fswatch v0.1.1 // indirect
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb // indirect github.com/sagernet/gvisor v0.0.0-20250811-sing-box-mod.1 // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect
github.com/sagernet/quic-go v0.52.0-beta.1 // indirect github.com/sagernet/quic-go v0.55.0-sing-box-mod.2 // indirect
github.com/sagernet/sing-mux v0.3.2 // indirect github.com/sagernet/sing-mux v0.3.3 // indirect
github.com/sagernet/sing-quic v0.5.0-beta.3 // indirect github.com/sagernet/sing-quic v0.6.0-beta.4 // indirect
github.com/sagernet/sing-shadowsocks v0.2.8 // indirect github.com/sagernet/sing-shadowsocks v0.2.8 // indirect
github.com/sagernet/sing-shadowsocks2 v0.2.1 // indirect github.com/sagernet/sing-shadowsocks2 v0.2.1 // indirect
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 // indirect github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 // indirect
github.com/sagernet/sing-tun v0.7.0-beta.1 // indirect github.com/sagernet/sing-tun v0.8.0-beta.11 // indirect
github.com/sagernet/sing-vmess v0.2.6 // indirect github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 // indirect
github.com/sagernet/smux v1.5.34-mod.2 // indirect github.com/sagernet/smux v1.5.34-mod.2 // indirect
github.com/sagernet/tailscale v1.80.3-mod.5 // indirect github.com/sagernet/tailscale v1.86.5-sing-box-1.13-mod.4 // indirect
github.com/sagernet/wireguard-go v0.0.1-beta.7 // indirect github.com/sagernet/wireguard-go v0.0.2-beta.1.0.20250917110311-16510ac47288 // indirect
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 // indirect github.com/scaleway/scaleway-sdk-go v1.0.0-beta.34 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/selectel/domains-go v1.1.0 // indirect github.com/selectel/domains-go v1.1.0 // indirect
github.com/selectel/go-selvpcclient/v3 v3.2.1 // indirect github.com/selectel/go-selvpcclient/v4 v4.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect github.com/shopspring/decimal v1.4.0 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.1.7 // indirect github.com/softlayer/softlayer-go v1.1.7 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/sony/gobreaker v0.5.0 // indirect github.com/sony/gobreaker v1.0.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.11.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
github.com/tailscale/golang-x-crypto v0.0.0-20240604161659-3fde5e568aa4 // indirect
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1065 // indirect github.com/tailscale/wireguard-go v0.0.0-20250716170648-1d0488a3d7da // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1065 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1210 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/transip/gotransip/v6 v6.26.0 // indirect github.com/transip/gotransip/v6 v6.26.0 // indirect
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
@@ -281,52 +283,53 @@ require (
github.com/vishvananda/netlink v1.3.1 // indirect github.com/vishvananda/netlink v1.3.1 // indirect
github.com/vishvananda/netns v0.0.5 // indirect github.com/vishvananda/netns v0.0.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/volcengine/volc-sdk-golang v1.0.189 // indirect github.com/volcengine/volc-sdk-golang v1.0.216 // indirect
github.com/vultr/govultr/v3 v3.9.1 // indirect github.com/vultr/govultr/v3 v3.21.1 // indirect
github.com/wyx2685/sing-vmess v0.0.0-20250723121437-95d5ab59ff92 // indirect github.com/wyx2685/sing-vmess v0.0.0-20250723121437-95d5ab59ff92 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7 // indirect github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20241220122821-aeb3b05efd1c // indirect github.com/yandex-cloud/go-genproto v0.14.0 // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20241220131134-2393e243c134 // indirect github.com/yandex-cloud/go-sdk/services/dns v0.0.3 // indirect
github.com/yandex-cloud/go-sdk/v2 v2.0.8 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect github.com/zeebo/blake3 v0.2.4 // indirect
go.mongodb.org/mongo-driver v1.12.0 // indirect go.mongodb.org/mongo-driver v1.13.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.5.2 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect
go.uber.org/zap/exp v0.3.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
golang.org/x/mod v0.26.0 // indirect golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/sync v0.16.0 // indirect golang.org/x/sync v0.18.0 // indirect
golang.org/x/term v0.33.0 // indirect golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.27.0 // indirect golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.9.0 // indirect golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.34.0 // indirect golang.org/x/tools v0.38.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
google.golang.org/api v0.214.0 // indirect google.golang.org/api v0.242.0 // indirect
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/grpc v1.77.0 // indirect
google.golang.org/grpc v1.74.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.13.0 // indirect gopkg.in/ns1/ns1-go.v2 v2.14.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 // indirect gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 // indirect
lukechampine.com/blake3 v1.4.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect
) )
//replace github.com/sagernet/sing-box v1.12.0 => ../sing-box_mod replace github.com/sagernet/sing-box v1.13.0 => github.com/wyx2685/sing-box_mod v1.13.0-alpha.5.0.20251202212447-8d054dcd8bfe
replace github.com/sagernet/sing-box v1.12.0 => github.com/wyx2685/sing-box_mod v1.12.0 replace github.com/xtls/xray-core v1.251202.0 => github.com/wyx2685/xray-core v0.0.0-20251202200223-63db1dc9e9e2

694
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -13,11 +13,12 @@ import (
"strings" "strings"
"time" "time"
"encoding/json"
"github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01" "github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/providers/dns" "github.com/go-acme/lego/v4/providers/dns"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
"github.com/goccy/go-json"
"github.com/InazumaV/V2bX/common/file" "github.com/InazumaV/V2bX/common/file"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"

View File

@@ -8,7 +8,7 @@ import (
) )
func (c *Controller) reportUserTrafficTask() (err error) { func (c *Controller) reportUserTrafficTask() (err error) {
userTraffic, err := c.server.GetUserTrafficSlice(c.tag, true) userTraffic, _ := c.server.GetUserTrafficSlice(c.tag, true)
if len(userTraffic) > 0 { if len(userTraffic) > 0 {
err = c.apiClient.ReportUserTraffic(userTraffic) err = c.apiClient.ReportUserTraffic(userTraffic)
if err != nil { if err != nil {
@@ -18,6 +18,7 @@ func (c *Controller) reportUserTrafficTask() (err error) {
}).Info("Report user traffic failed") }).Info("Report user traffic failed")
} else { } else {
log.WithField("tag", c.tag).Infof("Report %d users traffic", len(userTraffic)) log.WithField("tag", c.tag).Infof("Report %d users traffic", len(userTraffic))
log.WithField("tag", c.tag).Debugf("User traffic: %+v", userTraffic)
} }
} }
@@ -50,6 +51,7 @@ func (c *Controller) reportUserTrafficTask() (err error) {
}).Info("Report online users failed") }).Info("Report online users failed")
} else { } else {
log.WithField("tag", c.tag).Infof("Total %d online users, %d Reported", len(*onlineDevice), len(result)) log.WithField("tag", c.tag).Infof("Total %d online users, %d Reported", len(*onlineDevice), len(result))
log.WithField("tag", c.tag).Debugf("Online users: %+v", data)
} }
} }