mirror of
https://github.com/wyx2685/V2bX.git
synced 2026-02-04 12:40:11 +00:00
Compare commits
13 Commits
v0.2.9_tem
...
v0.3.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bbccf772b | ||
|
|
9483526f3c | ||
|
|
65f2de55ea | ||
|
|
4ed6bc6d87 | ||
|
|
af7b473c13 | ||
|
|
10f66b57ea | ||
|
|
0824bf7a4e | ||
|
|
6e8297c553 | ||
|
|
7d52a8932d | ||
|
|
06441afa79 | ||
|
|
f7b588fb45 | ||
|
|
9be082ede6 | ||
|
|
dce3ec1079 |
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -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: |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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/)
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type TrafficCounter struct {
|
type TrafficCounter struct {
|
||||||
counters sync.Map
|
Counters sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
type TrafficStorage struct {
|
type TrafficStorage struct {
|
||||||
@@ -18,26 +18,26 @@ func NewTrafficCounter() *TrafficCounter {
|
|||||||
return &TrafficCounter{}
|
return &TrafficCounter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) GetCounter(id string) *TrafficStorage {
|
func (c *TrafficCounter) GetCounter(uuid string) *TrafficStorage {
|
||||||
if cts, ok := c.counters.Load(id); ok {
|
if cts, ok := c.Counters.Load(uuid); ok {
|
||||||
return cts.(*TrafficStorage)
|
return cts.(*TrafficStorage)
|
||||||
}
|
}
|
||||||
newStorage := &TrafficStorage{}
|
newStorage := &TrafficStorage{}
|
||||||
if cts, loaded := c.counters.LoadOrStore(id, newStorage); loaded {
|
if cts, loaded := c.Counters.LoadOrStore(uuid, newStorage); loaded {
|
||||||
return cts.(*TrafficStorage)
|
return cts.(*TrafficStorage)
|
||||||
}
|
}
|
||||||
return newStorage
|
return newStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) GetUpCount(id string) int64 {
|
func (c *TrafficCounter) GetUpCount(uuid string) int64 {
|
||||||
if cts, ok := c.counters.Load(id); ok {
|
if cts, ok := c.Counters.Load(uuid); ok {
|
||||||
return cts.(*TrafficStorage).UpCounter.Load()
|
return cts.(*TrafficStorage).UpCounter.Load()
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) GetDownCount(id string) int64 {
|
func (c *TrafficCounter) GetDownCount(uuid string) int64 {
|
||||||
if cts, ok := c.counters.Load(id); ok {
|
if cts, ok := c.Counters.Load(uuid); ok {
|
||||||
return cts.(*TrafficStorage).DownCounter.Load()
|
return cts.(*TrafficStorage).DownCounter.Load()
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@@ -45,30 +45,30 @@ func (c *TrafficCounter) GetDownCount(id string) int64 {
|
|||||||
|
|
||||||
func (c *TrafficCounter) Len() int {
|
func (c *TrafficCounter) Len() int {
|
||||||
length := 0
|
length := 0
|
||||||
c.counters.Range(func(_, _ interface{}) bool {
|
c.Counters.Range(func(_, _ interface{}) bool {
|
||||||
length++
|
length++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return length
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) Reset(id string) {
|
func (c *TrafficCounter) Reset(uuid string) {
|
||||||
if cts, ok := c.counters.Load(id); ok {
|
if cts, ok := c.Counters.Load(uuid); ok {
|
||||||
cts.(*TrafficStorage).UpCounter.Store(0)
|
cts.(*TrafficStorage).UpCounter.Store(0)
|
||||||
cts.(*TrafficStorage).DownCounter.Store(0)
|
cts.(*TrafficStorage).DownCounter.Store(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) Delete(id string) {
|
func (c *TrafficCounter) Delete(uuid string) {
|
||||||
c.counters.Delete(id)
|
c.Counters.Delete(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) Rx(id string, n int) {
|
func (c *TrafficCounter) Rx(uuid string, n int) {
|
||||||
cts := c.GetCounter(id)
|
cts := c.GetCounter(uuid)
|
||||||
cts.DownCounter.Add(int64(n))
|
cts.DownCounter.Add(int64(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) Tx(id string, n int) {
|
func (c *TrafficCounter) Tx(uuid string, n int) {
|
||||||
cts := c.GetCounter(id)
|
cts := c.GetCounter(uuid)
|
||||||
cts.UpCounter.Add(int64(n))
|
cts.UpCounter.Add(int64(n))
|
||||||
}
|
}
|
||||||
|
|||||||
25
common/counter/xraytraffic.go
Normal file
25
common/counter/xraytraffic.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -109,6 +110,7 @@ type Options struct {
|
|||||||
ListenIP string `json:"ListenIP"`
|
ListenIP string `json:"ListenIP"`
|
||||||
SendIP string `json:"SendIP"`
|
SendIP string `json:"SendIP"`
|
||||||
DeviceOnlineMinTraffic int64 `json:"DeviceOnlineMinTraffic"`
|
DeviceOnlineMinTraffic int64 `json:"DeviceOnlineMinTraffic"`
|
||||||
|
ReportMinTraffic int64 `json:"ReportMinTraffic"`
|
||||||
LimitConfig LimitConfig `json:"LimitConfig"`
|
LimitConfig LimitConfig `json:"LimitConfig"`
|
||||||
RawOptions json.RawMessage `json:"RawOptions"`
|
RawOptions json.RawMessage `json:"RawOptions"`
|
||||||
XrayOptions *XrayOptions `json:"XrayOptions"`
|
XrayOptions *XrayOptions `json:"XrayOptions"`
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ import (
|
|||||||
var _ server.TrafficLogger = (*HookServer)(nil)
|
var _ server.TrafficLogger = (*HookServer)(nil)
|
||||||
|
|
||||||
type HookServer struct {
|
type HookServer struct {
|
||||||
Tag string
|
Tag string
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
Counter sync.Map
|
Counter sync.Map
|
||||||
|
ReportMinTrafficBytes int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HookServer) TraceStream(stream quic.Stream, stats *server.StreamStats) {
|
func (h *HookServer) TraceStream(stream quic.Stream, stats *server.StreamStats) {
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ func (h *Hysteria2) AddNode(tag string, info *panel.NodeInfo, config *conf.Optio
|
|||||||
logger: h.Logger,
|
logger: h.Logger,
|
||||||
},
|
},
|
||||||
TrafficLogger: &HookServer{
|
TrafficLogger: &HookServer{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
logger: h.Logger,
|
logger: h.Logger,
|
||||||
|
ReportMinTrafficBytes: config.ReportMinTraffic * 1024,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ var _ server.Authenticator = &V2bX{}
|
|||||||
|
|
||||||
type V2bX struct {
|
type V2bX struct {
|
||||||
usersMap map[string]int
|
usersMap map[string]int
|
||||||
mutex sync.Mutex
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *V2bX) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
|
func (v *V2bX) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
|
||||||
v.mutex.Lock()
|
v.mutex.RLock()
|
||||||
defer v.mutex.Unlock()
|
defer v.mutex.RUnlock()
|
||||||
if _, exists := v.usersMap[auth]; exists {
|
if _, exists := v.usersMap[auth]; exists {
|
||||||
return true, auth
|
return true, auth
|
||||||
}
|
}
|
||||||
@@ -56,15 +56,38 @@ func (h *Hysteria2) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeIn
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hysteria2) GetUserTraffic(tag string, uuid string, reset bool) (up int64, down int64) {
|
func (h *Hysteria2) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error) {
|
||||||
if v, ok := h.Hy2nodes[tag].TrafficLogger.(*HookServer).Counter.Load(tag); ok {
|
trafficSlice := make([]panel.UserTraffic, 0)
|
||||||
c := v.(*counter.TrafficCounter)
|
h.Auth.mutex.RLock()
|
||||||
up = c.GetUpCount(uuid)
|
defer h.Auth.mutex.RUnlock()
|
||||||
down = c.GetDownCount(uuid)
|
if _, ok := h.Hy2nodes[tag]; !ok {
|
||||||
if reset {
|
return nil, nil
|
||||||
c.Reset(uuid)
|
|
||||||
}
|
|
||||||
return up, down
|
|
||||||
}
|
}
|
||||||
return 0, 0
|
hook := h.Hy2nodes[tag].TrafficLogger.(*HookServer)
|
||||||
|
if v, ok := hook.Counter.Load(tag); ok {
|
||||||
|
c := v.(*counter.TrafficCounter)
|
||||||
|
c.Counters.Range(func(key, value interface{}) bool {
|
||||||
|
uuid := key.(string)
|
||||||
|
traffic := value.(*counter.TrafficStorage)
|
||||||
|
up := traffic.UpCounter.Load()
|
||||||
|
down := traffic.DownCounter.Load()
|
||||||
|
if up+down > hook.ReportMinTrafficBytes {
|
||||||
|
if reset {
|
||||||
|
traffic.UpCounter.Store(0)
|
||||||
|
traffic.DownCounter.Store(0)
|
||||||
|
}
|
||||||
|
trafficSlice = append(trafficSlice, panel.UserTraffic{
|
||||||
|
UID: h.Auth.usersMap[uuid],
|
||||||
|
Upload: up,
|
||||||
|
Download: down,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if len(trafficSlice) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return trafficSlice, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type Core interface {
|
|||||||
AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error
|
AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error
|
||||||
DelNode(tag string) error
|
DelNode(tag string) error
|
||||||
AddUsers(p *AddUsersParams) (added int, err error)
|
AddUsers(p *AddUsersParams) (added int, err error)
|
||||||
GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64)
|
GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error)
|
||||||
DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error
|
DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error
|
||||||
Protocols() []string
|
Protocols() []string
|
||||||
Type() string
|
Type() string
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -128,12 +125,12 @@ func (s *Selector) AddUsers(p *AddUsersParams) (added int, err error) {
|
|||||||
return t.(Core).AddUsers(p)
|
return t.(Core).AddUsers(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
func (s *Selector) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error) {
|
||||||
t, e := s.nodes.Load(tag)
|
t, e := s.nodes.Load(tag)
|
||||||
if !e {
|
if !e {
|
||||||
return 0, 0
|
return nil, errors.New("the node is not have")
|
||||||
}
|
}
|
||||||
return t.(Core).GetUserTraffic(tag, uuid, reset)
|
return t.(Core).GetUserTrafficSlice(tag, reset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Selector) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error {
|
func (s *Selector) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error {
|
||||||
|
|||||||
@@ -27,13 +27,6 @@ func (h *HookServer) ModeList() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHookServer() *HookServer {
|
|
||||||
server := &HookServer{
|
|
||||||
counter: sync.Map{},
|
|
||||||
}
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapter.InboundContext, _ adapter.Rule, _ adapter.Outbound) net.Conn {
|
func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapter.InboundContext, _ adapter.Rule, _ adapter.Outbound) net.Conn {
|
||||||
l, err := limiter.GetLimiter(m.Inbound)
|
l, err := limiter.GetLimiter(m.Inbound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -394,6 +395,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Sing) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
func (b *Sing) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||||
|
b.nodeReportMinTrafficBytes[tag] = config.ReportMinTraffic * 1024
|
||||||
c, err := getInboundOptions(tag, info, config)
|
c, err := getInboundOptions(tag, info, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/include"
|
"github.com/sagernet/sing-box/include"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
@@ -24,11 +25,18 @@ type DNSConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Sing struct {
|
type Sing struct {
|
||||||
box *box.Box
|
box *box.Box
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
hookServer *HookServer
|
hookServer *HookServer
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
logFactory log.Factory
|
logFactory log.Factory
|
||||||
|
users *UserMap
|
||||||
|
nodeReportMinTrafficBytes map[string]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserMap struct {
|
||||||
|
uidMap map[string]int
|
||||||
|
mapLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -71,7 +79,9 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hs := NewHookServer()
|
hs := &HookServer{
|
||||||
|
counter: sync.Map{},
|
||||||
|
}
|
||||||
b.Router().AppendTracker(hs)
|
b.Router().AppendTracker(hs)
|
||||||
return &Sing{
|
return &Sing{
|
||||||
ctx: b.Router().GetCtx(),
|
ctx: b.Router().GetCtx(),
|
||||||
@@ -79,6 +89,10 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
|
|||||||
hookServer: hs,
|
hookServer: hs,
|
||||||
router: b.Router(),
|
router: b.Router(),
|
||||||
logFactory: b.LogFactory(),
|
logFactory: b.LogFactory(),
|
||||||
|
users: &UserMap{
|
||||||
|
uidMap: make(map[string]int),
|
||||||
|
},
|
||||||
|
nodeReportMinTrafficBytes: make(map[string]int64),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
|||||||
if !found {
|
if !found {
|
||||||
return 0, errors.New("the inbound not found")
|
return 0, errors.New("the inbound not found")
|
||||||
}
|
}
|
||||||
|
b.users.mapLock.Lock()
|
||||||
|
defer b.users.mapLock.Unlock()
|
||||||
|
for i := range p.Users {
|
||||||
|
b.users.uidMap[p.Users[i].Uuid] = p.Users[i].Id
|
||||||
|
}
|
||||||
switch p.NodeInfo.Type {
|
switch p.NodeInfo.Type {
|
||||||
case "vless":
|
case "vless":
|
||||||
us := make([]option.VLESSUser, len(p.Users))
|
us := make([]option.VLESSUser, len(p.Users))
|
||||||
@@ -129,6 +134,39 @@ func (b *Sing) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int6
|
|||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Sing) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error) {
|
||||||
|
trafficSlice := make([]panel.UserTraffic, 0)
|
||||||
|
hook := b.hookServer
|
||||||
|
b.users.mapLock.RLock()
|
||||||
|
defer b.users.mapLock.RUnlock()
|
||||||
|
if v, ok := hook.counter.Load(tag); ok {
|
||||||
|
c := v.(*counter.TrafficCounter)
|
||||||
|
c.Counters.Range(func(key, value interface{}) bool {
|
||||||
|
uuid := key.(string)
|
||||||
|
traffic := value.(*counter.TrafficStorage)
|
||||||
|
up := traffic.UpCounter.Load()
|
||||||
|
down := traffic.DownCounter.Load()
|
||||||
|
if up+down > b.nodeReportMinTrafficBytes[tag] {
|
||||||
|
if reset {
|
||||||
|
traffic.UpCounter.Store(0)
|
||||||
|
traffic.DownCounter.Store(0)
|
||||||
|
}
|
||||||
|
trafficSlice = append(trafficSlice, panel.UserTraffic{
|
||||||
|
UID: b.users.uidMap[uuid],
|
||||||
|
Upload: up,
|
||||||
|
Download: down,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if len(trafficSlice) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return trafficSlice, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
type UserDeleter interface {
|
type UserDeleter interface {
|
||||||
DelUsers(uuid []string) error
|
DelUsers(uuid []string) error
|
||||||
}
|
}
|
||||||
@@ -158,7 +196,10 @@ func (b *Sing) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo
|
|||||||
return errors.New("the inbound not found")
|
return errors.New("the inbound not found")
|
||||||
}
|
}
|
||||||
uuids := make([]string, len(users))
|
uuids := make([]string, len(users))
|
||||||
|
b.users.mapLock.Lock()
|
||||||
|
defer b.users.mapLock.Unlock()
|
||||||
for i := range users {
|
for i := range users {
|
||||||
|
delete(b.users.uidMap, users[i].Uuid)
|
||||||
uuids[i] = users[i].Uuid
|
uuids[i] = users[i].Uuid
|
||||||
}
|
}
|
||||||
err := del.DelUsers(uuids)
|
err := del.DelUsers(uuids)
|
||||||
|
|||||||
37
core/xray/app/dispatcher/countreader.go
Normal file
37
core/xray/app/dispatcher/countreader.go
Normal 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
|
||||||
|
}
|
||||||
@@ -10,9 +10,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/InazumaV/V2bX/common/counter"
|
||||||
"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"
|
||||||
@@ -35,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,17 +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
|
||||||
|
LinkManagers sync.Map // map[string]*LinkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -127,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,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
|
||||||
@@ -193,35 +194,44 @@ 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)
|
||||||
}
|
}
|
||||||
p := d.policy.ForLevel(user.Level)
|
var t *counter.TrafficCounter
|
||||||
if p.Stats.UserUplink {
|
if c, ok := d.Counter.Load(sessionInbound.Tag); !ok {
|
||||||
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
|
t = counter.NewTrafficCounter()
|
||||||
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
|
d.Counter.Store(sessionInbound.Tag, t)
|
||||||
inboundLink.Writer = &SizeStatWriter{
|
} else {
|
||||||
Counter: c,
|
t = c.(*counter.TrafficCounter)
|
||||||
Writer: inboundLink.Writer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if p.Stats.UserDownlink {
|
|
||||||
name := "user>>>" + user.Email + ">>>traffic>>>downlink"
|
ts := t.GetCounter(user.Email)
|
||||||
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
|
upcounter := &counter.XrayTrafficCounter{V: &ts.UpCounter}
|
||||||
outboundLink.Writer = &SizeStatWriter{
|
downcounter := &counter.XrayTrafficCounter{V: &ts.DownCounter}
|
||||||
Counter: c,
|
inboundLink.Writer = &dispatcher.SizeStatWriter{
|
||||||
Writer: outboundLink.Writer,
|
Counter: upcounter,
|
||||||
}
|
Writer: inboundLink.Writer,
|
||||||
}
|
}
|
||||||
|
outboundLink.Writer = &dispatcher.SizeStatWriter{
|
||||||
|
Counter: downcounter,
|
||||||
|
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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package dispatcher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/features/stats"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SizeStatWriter struct {
|
|
||||||
Counter stats.Counter
|
|
||||||
Writer buf.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *SizeStatWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|
||||||
w.Counter.Add(int64(mb.Len()))
|
|
||||||
return w.Writer.WriteMultiBuffer(mb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *SizeStatWriter) Close() error {
|
|
||||||
return common.Close(w.Writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *SizeStatWriter) Interrupt() {
|
|
||||||
common.Interrupt(w.Writer)
|
|
||||||
}
|
|
||||||
@@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type DNSConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Xray) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
func (c *Xray) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||||
|
c.nodeReportMinTrafficBytes[tag] = config.ReportMinTraffic * 1024
|
||||||
err := updateDNSConfig(info)
|
err := updateDNSConfig(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("build dns error: %s", err)
|
return fmt.Errorf("build dns error: %s", err)
|
||||||
|
|||||||
@@ -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"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/InazumaV/V2bX/api/panel"
|
"github.com/InazumaV/V2bX/api/panel"
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
@@ -32,47 +34,68 @@ func (c *Xray) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeInfo) e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get user manager error: %s", err)
|
return fmt.Errorf("get user manager error: %s", err)
|
||||||
}
|
}
|
||||||
var up, down, user string
|
var user string
|
||||||
|
c.users.mapLock.Lock()
|
||||||
|
defer c.users.mapLock.Unlock()
|
||||||
for i := range users {
|
for i := range users {
|
||||||
user = format.UserTag(tag, users[i].Uuid)
|
user = format.UserTag(tag, users[i].Uuid)
|
||||||
err = userManager.RemoveUser(context.Background(), user)
|
err = userManager.RemoveUser(context.Background(), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
up = "user>>>" + user + ">>>traffic>>>uplink"
|
delete(c.users.uidMap, user)
|
||||||
down = "user>>>" + user + ">>>traffic>>>downlink"
|
if v, ok := c.dispatcher.Counter.Load(tag); ok {
|
||||||
c.shm.UnregisterCounter(up)
|
tc := v.(*counter.TrafficCounter)
|
||||||
c.shm.UnregisterCounter(down)
|
tc.Delete(user)
|
||||||
c.dispatcher.Wm.RemoveWritersForUser(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
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Xray) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
func (x *Xray) GetUserTrafficSlice(tag string, reset bool) ([]panel.UserTraffic, error) {
|
||||||
upName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>uplink"
|
trafficSlice := make([]panel.UserTraffic, 0)
|
||||||
downName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>downlink"
|
x.users.mapLock.RLock()
|
||||||
upCounter := c.shm.GetCounter(upName)
|
defer x.users.mapLock.RUnlock()
|
||||||
downCounter := c.shm.GetCounter(downName)
|
if v, ok := x.dispatcher.Counter.Load(tag); ok {
|
||||||
if reset {
|
c := v.(*counter.TrafficCounter)
|
||||||
if upCounter != nil {
|
c.Counters.Range(func(key, value interface{}) bool {
|
||||||
up = upCounter.Set(0)
|
email := key.(string)
|
||||||
}
|
traffic := value.(*counter.TrafficStorage)
|
||||||
if downCounter != nil {
|
up := traffic.UpCounter.Load()
|
||||||
down = downCounter.Set(0)
|
down := traffic.DownCounter.Load()
|
||||||
}
|
if up+down > x.nodeReportMinTrafficBytes[tag] {
|
||||||
} else {
|
if reset {
|
||||||
if upCounter != nil {
|
traffic.UpCounter.Store(0)
|
||||||
up = upCounter.Value()
|
traffic.DownCounter.Store(0)
|
||||||
}
|
}
|
||||||
if downCounter != nil {
|
trafficSlice = append(trafficSlice, panel.UserTraffic{
|
||||||
down = downCounter.Value()
|
UID: x.users.uidMap[email],
|
||||||
|
Upload: up,
|
||||||
|
Download: down,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if len(trafficSlice) == 0 {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
return trafficSlice, nil
|
||||||
}
|
}
|
||||||
return up, down
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Xray) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
func (c *Xray) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
||||||
users := make([]*protocol.User, 0, len(p.Users))
|
c.users.mapLock.Lock()
|
||||||
|
defer c.users.mapLock.Unlock()
|
||||||
|
for i := range p.Users {
|
||||||
|
c.users.uidMap[format.UserTag(p.Tag, p.Users[i].Uuid)] = p.Users[i].Id
|
||||||
|
}
|
||||||
|
var users []*protocol.User
|
||||||
switch p.NodeInfo.Type {
|
switch p.NodeInfo.Type {
|
||||||
case "vmess":
|
case "vmess":
|
||||||
users = buildVmessUsers(p.Tag, p.Users)
|
users = buildVmessUsers(p.Tag, p.Users)
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -30,16 +31,29 @@ func init() {
|
|||||||
|
|
||||||
// Xray Structure
|
// Xray Structure
|
||||||
type Xray struct {
|
type Xray struct {
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
Server *core.Instance
|
Server *core.Instance
|
||||||
ihm inbound.Manager
|
ihm inbound.Manager
|
||||||
ohm outbound.Manager
|
ohm outbound.Manager
|
||||||
shm statsFeature.Manager
|
shm statsFeature.Manager
|
||||||
dispatcher *dispatcher.DefaultDispatcher
|
dispatcher *dispatcher.DefaultDispatcher
|
||||||
|
users *UserMap
|
||||||
|
nodeReportMinTrafficBytes map[string]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserMap struct {
|
||||||
|
uidMap map[string]int
|
||||||
|
mapLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(c *conf.CoreConfig) (vCore.Core, error) {
|
func New(c *conf.CoreConfig) (vCore.Core, error) {
|
||||||
return &Xray{Server: getCore(c.XrayConfig)}, nil
|
return &Xray{
|
||||||
|
Server: getCore(c.XrayConfig),
|
||||||
|
users: &UserMap{
|
||||||
|
uidMap: make(map[string]int),
|
||||||
|
},
|
||||||
|
nodeReportMinTrafficBytes: make(map[string]int64),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConnectionConfig(c *conf.XrayConnectionConfig) (policy *coreConf.Policy) {
|
func parseConnectionConfig(c *conf.XrayConnectionConfig) (policy *coreConf.Policy) {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
"ListenIP": "0.0.0.0",
|
"ListenIP": "0.0.0.0",
|
||||||
"SendIP": "0.0.0.0",
|
"SendIP": "0.0.0.0",
|
||||||
"DeviceOnlineMinTraffic": 200,
|
"DeviceOnlineMinTraffic": 200,
|
||||||
|
"MinReportTraffic": 0,
|
||||||
"TCPFastOpen": false,
|
"TCPFastOpen": false,
|
||||||
"SniffEnabled": true,
|
"SniffEnabled": true,
|
||||||
"CertConfig": {
|
"CertConfig": {
|
||||||
|
|||||||
237
go.mod
237
go.mod
@@ -1,93 +1,96 @@
|
|||||||
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.3
|
||||||
github.com/apernet/hysteria/extras/v2 v2.6.2
|
github.com/apernet/hysteria/extras/v2 v2.6.3
|
||||||
github.com/apernet/quic-go v0.52.1-0.20250607183305-9320c9d14431
|
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.1.0.20250722151551-64142925accb
|
github.com/sagernet/sing v0.7.6-0.20250815070458-d33ece7a184f
|
||||||
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.250608.1-0.20250723105259-dbd912568602
|
github.com/xtls/xray-core v1.250911.1-0.20250911134820-83c5370eec69
|
||||||
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.42.0
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.36.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.9
|
||||||
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.7.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/anytls/sing-anytls v0.0.9-0.20250508103614-8bc6dd599731 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.7 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.36.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.28.7 // indirect
|
github.com/aws/aws-sdk-go-v2/config v1.29.18 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.48 // indirect
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.71 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.33 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.37 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.37 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.18 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.8 // indirect
|
github.com/aws/aws-sdk-go-v2/service/lightsail v1.43.5 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.4 // indirect
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.53.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.8 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.6 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 // indirect
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.4 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.34.1 // indirect
|
||||||
github.com/aws/smithy-go v1.22.1 // indirect
|
github.com/aws/smithy-go v1.22.4 // indirect
|
||||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // 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/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.0.0-20240905055117-62795b8b054a // indirect
|
||||||
github.com/database64128/tfo-go/v2 v2.2.2 // indirect
|
github.com/database64128/tfo-go/v2 v2.2.2 // indirect
|
||||||
@@ -96,64 +99,65 @@ require (
|
|||||||
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.11.1 // 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.1 // indirect
|
||||||
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // indirect
|
github.com/go-json-experiment/json v0.0.0-20250103232110-6a9a0fde9288 // 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-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // 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/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
||||||
github.com/google/s2a-go v0.1.8 // indirect
|
github.com/google/s2a-go v0.1.9 // 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/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // 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/v2 v2.0.3 // 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
|
||||||
@@ -164,11 +168,11 @@ require (
|
|||||||
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 +182,33 @@ 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/tfo-go v0.0.0-20250516165257-e29c16ae41d4 // indirect
|
||||||
github.com/metacubex/utls v1.8.0 // 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/onsi/ginkgo/v2 v2.20.1 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/ovh/go-ovh v1.9.0 // 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,17 +217,17 @@ 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.54.0 // indirect
|
||||||
github.com/refraction-networking/utls v1.8.0 // indirect
|
github.com/refraction-networking/utls v1.8.0 // 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
|
||||||
@@ -231,34 +236,34 @@ require (
|
|||||||
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.52.0-beta.1 // 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.5.0 // 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.6.10-0.20250721014417-ebbe32588cfb // indirect
|
github.com/sagernet/sing-tun v0.7.0-beta.1 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.2.4 // indirect
|
github.com/sagernet/sing-vmess v0.2.7 // 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.80.3-mod.5 // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.7 // indirect
|
github.com/sagernet/wireguard-go v0.0.1-beta.7 // 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
|
||||||
@@ -268,8 +273,7 @@ require (
|
|||||||
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/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1210 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1065 // 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,54 +285,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-20250723121014-c6320729d93b // indirect
|
github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c // 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.1.0 // 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.37.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
go.opentelemetry.io/otel/trace v1.37.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.0 // 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-20250506013437-ce4c2cf36ca6 // indirect
|
||||||
golang.org/x/mod v0.26.0 // indirect
|
golang.org/x/mod v0.27.0 // indirect
|
||||||
golang.org/x/net v0.42.0 // indirect
|
golang.org/x/net v0.44.0 // indirect
|
||||||
golang.org/x/oauth2 v0.30.0 // indirect
|
golang.org/x/oauth2 v0.30.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
golang.org/x/term v0.33.0 // indirect
|
golang.org/x/term v0.35.0 // indirect
|
||||||
golang.org/x/text v0.27.0 // indirect
|
golang.org/x/text v0.29.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.36.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-20250707201910-8d1bb00bc6a7 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
google.golang.org/grpc v1.75.1 // 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
|
||||||
|
|
||||||
replace github.com/sagernet/sing-box v1.12.0 => github.com/wyx2685/sing-box_mod v1.12.0-rc.2.1
|
replace github.com/xtls/xray-core v1.250911.1-0.20250911134820-83c5370eec69 => github.com/wyx2685/xray-core v0.0.0-20250912060919-a74bf884128d
|
||||||
|
|
||||||
replace github.com/xtls/xray-core v1.250608.1-0.20250723105259-dbd912568602 => github.com/wyx2685/xray-core v0.0.0-20250723170258-d07df9f8e259
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
17
node/user.go
17
node/user.go
@@ -8,20 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Controller) reportUserTrafficTask() (err error) {
|
func (c *Controller) reportUserTrafficTask() (err error) {
|
||||||
// Get User traffic
|
userTraffic, _ := c.server.GetUserTrafficSlice(c.tag, true)
|
||||||
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.traffic[c.userList[i].Uuid] += up + down
|
|
||||||
}
|
|
||||||
userTraffic = append(userTraffic, panel.UserTraffic{
|
|
||||||
UID: (c.userList)[i].Id,
|
|
||||||
Upload: up,
|
|
||||||
Download: down})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(userTraffic) > 0 {
|
if len(userTraffic) > 0 {
|
||||||
err = c.apiClient.ReportUserTraffic(userTraffic)
|
err = c.apiClient.ReportUserTraffic(userTraffic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -31,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user