Compare commits

...

12 Commits

Author SHA1 Message Date
wyx2685
e81d47321b xray-core 1.8.19 2024-07-17 23:26:09 +09:00
wyx2685
4d82eff518 update Xray-core 1.8.18 2024-07-17 09:21:57 +09:00
wyx2685
b96545649b Fix:修复无法使用Sing-box内核urltest出口的问题 2024-07-15 00:33:54 +09:00
wyx2685
8757b955a6 修复hy2内核设备数统计错误的BUG 2024-07-08 20:32:52 +09:00
wyx2685
33d9ab4b0a 适应xray1.8.16更改 2024-07-08 18:12:09 +09:00
wyx2685
a7637d436f 更新所有内核 2024-07-08 17:44:22 +09:00
wyx2685
4dda65a636 Fix:修复Xray内核VMess/VLess的Websocket传输方式参数设置错误 2024-06-24 18:55:04 +09:00
wyx2685
6c725b424f 更新文档链接 2024-06-24 04:48:15 +09:00
wyx2685
a052a1f1e8 升级Xray内核,完善singbox内核自定义配置 2024-06-24 04:41:56 +09:00
wyx2685
85ad40d098 升级全部内核 2024-06-13 00:06:22 +09:00
wyx2685
206af0216c 修复xray内核vless协议bug,升级xray/sing内核 2024-03-13 22:15:04 +09:00
wyx2685
ed5edda28a 修复Sing内核trojan用户列表BUG、修复用户设备限制不生效 2024-03-04 22:25:06 +09:00
24 changed files with 775 additions and 515 deletions

View File

@@ -52,17 +52,17 @@ wget -N https://raw.githubusercontent.com/wyx2685/V2bX-script/master/install.sh
### 手动安装
[手动安装教程(过时待更新)](https://yuzuki-1.gitbook.io/v2bx-doc/xrayr-xia-zai-he-an-zhuang/install/manual)
[手动安装教程](https://v2bx.v-50.me/v2bx/v2bx-xia-zai-he-an-zhuang/install/manual)
## 构建
``` bash
# 通过-tags选项指定要编译的内核 可选 xray sing
go build -o V2bX -ldflags '-s -w' -gcflags="all=-trimpath=${PWD}" -asmflags="all=-trimpath=${PWD} -tags "xray sing"
go build -v -o ./V2bX -tags "sing hysteria2 with_reality_server with_quic with_grpc with_utls with_wireguard with_acme" -trimpath -ldflags "-s -w -buildid="
```
## 配置文件及详细使用教程
[详细使用教程](https://yuzuki-1.gitbook.io/v2bx-doc/)
[详细使用教程](https://v2bx.v-50.me/)
## 免责声明
@@ -82,4 +82,4 @@ go build -o V2bX -ldflags '-s -w' -gcflags="all=-trimpath=${PWD}" -asmflags="all
## Stars 增长记录
[![Stargazers over time](https://starchart.cc/InazumaV/V2bX.svg)](https://starchart.cc/InazumaV/V2bX)
[![Stargazers over time](https://starchart.cc/wyx2685/V2bX.svg)](https://starchart.cc/wyx2685/V2bX)

View File

@@ -80,7 +80,7 @@ type TlsSettings struct {
ServerPort string `json:"server_port"`
ShortId string `json:"short_id"`
PrivateKey string `json:"private_key"`
Xver uint8 `json:"xver,string"`
Xver uint64 `json:"xver,string"`
}
type RealityConfig struct {

View File

@@ -57,7 +57,7 @@ func (c *Client) GetUserList() (UserList []UserInfo, err error) {
c.userEtag = r.Header().Get("ETag")
var userinfos []UserInfo
var localDeviceLimit int = 0
var deviceLimit, localDeviceLimit int = 0, 0
for _, user := range userList.Users {
// If there is still device available, add the user
if user.DeviceLimit > 0 && user.AliveIp > 0 {
@@ -68,13 +68,14 @@ func (c *Client) GetUserList() (UserList []UserInfo, err error) {
// If there are any available device.
localDeviceLimit = user.DeviceLimit - user.AliveIp + lastOnline
if localDeviceLimit > 0 {
deviceLimit = localDeviceLimit
} else if lastOnline > 0 {
deviceLimit = lastOnline
} else {
continue
}
}
user.DeviceLimit = deviceLimit
userinfos = append(userinfos, user)
}

View File

@@ -8,7 +8,6 @@ type SingConfig struct {
LogConfig SingLogConfig `json:"Log"`
NtpConfig SingNtpConfig `json:"NTP"`
EnableConnClear bool `json:"EnableConnClear"`
DnsConfigPath string `json:"DnsConfigPath"`
OriginalPath string `json:"OriginalPath"`
}

View File

@@ -13,11 +13,11 @@ import (
"github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf"
"github.com/apernet/hysteria/core/server"
"github.com/apernet/hysteria/extras/correctnet"
"github.com/apernet/hysteria/extras/masq"
"github.com/apernet/hysteria/extras/obfs"
"github.com/apernet/hysteria/extras/outbounds"
"github.com/apernet/hysteria/core/v2/server"
"github.com/apernet/hysteria/extras/v2/correctnet"
"github.com/apernet/hysteria/extras/v2/masq"
"github.com/apernet/hysteria/extras/v2/obfs"
"github.com/apernet/hysteria/extras/v2/outbounds"
"go.uber.org/zap"
)
@@ -49,7 +49,7 @@ const (
defaultStreamReceiveWindow = 8388608 // 8MB
defaultConnReceiveWindow = defaultStreamReceiveWindow * 5 / 2 // 20MB
defaultMaxIdleTimeout = 30 * time.Second
defaultMaxIncomingStreams = 1024
defaultMaxIncomingStreams = 4096
defaultUDPIdleTimeout = 60 * time.Second
)
@@ -268,7 +268,7 @@ func (n *Hysteria2node) getOutboundConfig(c *serverConfig) (server.Outbound, err
return Outbound, nil
}
func (n *Hysteria2node) getMasqHandler(tlsconfig *server.TLSConfig, conn net.PacketConn, info *panel.NodeInfo, c *serverConfig) (http.Handler, error) {
func (n *Hysteria2node) getMasqHandler(tlsconfig *server.TLSConfig, conn net.PacketConn, c *serverConfig) (http.Handler, error) {
var handler http.Handler
switch strings.ToLower(c.Masquerade.Type) {
case "", "404":
@@ -347,7 +347,7 @@ func (n *Hysteria2node) getMasqHandler(tlsconfig *server.TLSConfig, conn net.Pac
return MasqHandler, nil
}
func (n *Hysteria2node) getHyConfig(tag string, info *panel.NodeInfo, config *conf.Options, c *serverConfig) (*server.Config, error) {
func (n *Hysteria2node) getHyConfig(info *panel.NodeInfo, config *conf.Options, c *serverConfig) (*server.Config, error) {
tls, err := n.getTLSConfig(config)
if err != nil {
return nil, err
@@ -364,7 +364,7 @@ func (n *Hysteria2node) getHyConfig(tag string, info *panel.NodeInfo, config *co
if err != nil {
return nil, err
}
Masq, err := n.getMasqHandler(tls, conn, info, c)
Masq, err := n.getMasqHandler(tls, conn, c)
if err != nil {
return nil, err
}

View File

@@ -7,8 +7,8 @@ import (
"os"
"time"
"github.com/apernet/hysteria/extras/outbounds/acl"
"github.com/apernet/hysteria/extras/outbounds/acl/v2geo"
"github.com/apernet/hysteria/extras/v2/outbounds/acl"
"github.com/apernet/hysteria/extras/v2/outbounds/acl/v2geo"
"go.uber.org/zap"
)

View File

@@ -4,17 +4,36 @@ import (
"sync"
"github.com/InazumaV/V2bX/common/counter"
"github.com/InazumaV/V2bX/common/format"
"github.com/InazumaV/V2bX/limiter"
"go.uber.org/zap"
)
type HookServer struct {
Tag string
logger *zap.Logger
Counter sync.Map
}
func (h *HookServer) Log(id string, tx, rx uint64) (ok bool) {
func (h *HookServer) LogTraffic(id string, tx, rx uint64) (ok bool) {
var c interface{}
var exists bool
limiterinfo, err := limiter.GetLimiter(h.Tag)
if err != nil {
h.logger.Error("Get limiter error", zap.String("tag", h.Tag), zap.Error(err))
return false
}
userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(h.Tag, id))
if ok {
userlimitInfo := userLimit.(*limiter.UserLimitInfo)
if userlimitInfo.OverLimit {
userlimitInfo.OverLimit = false
return false
}
}
if c, exists = h.Counter.Load(h.Tag); !exists {
c = counter.NewTrafficCounter()
h.Counter.Store(h.Tag, c)
@@ -28,3 +47,6 @@ func (h *HookServer) Log(id string, tx, rx uint64) (ok bool) {
return false
}
func (s *HookServer) LogOnlineState(id string, online bool) {
}

View File

@@ -5,6 +5,7 @@ import (
"net"
"strings"
"github.com/InazumaV/V2bX/common/format"
"github.com/InazumaV/V2bX/limiter"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
@@ -46,12 +47,18 @@ var logFormatMap = map[string]zapcore.EncoderConfig{
}
func (l *serverLogger) Connect(addr net.Addr, uuid string, tx uint64) {
limiter, err := limiter.GetLimiter(l.Tag)
limiterinfo, err := limiter.GetLimiter(l.Tag)
if err != nil {
l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err))
}
if _, r := limiter.CheckLimit(uuid, extractIPFromAddr(addr), addr.Network() == "tcp"); r {
l.logger.Warn("Need Reject", zap.String("addr", addr.String()), zap.String("uuid", uuid))
if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = true
}
} else {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = false
}
}
l.logger.Info("client connected", zap.String("addr", addr.String()), zap.String("uuid", uuid), zap.Uint64("tx", tx))
}
@@ -61,12 +68,18 @@ func (l *serverLogger) Disconnect(addr net.Addr, uuid string, err error) {
}
func (l *serverLogger) TCPRequest(addr net.Addr, uuid, reqAddr string) {
limiter, err := limiter.GetLimiter(l.Tag)
limiterinfo, err := limiter.GetLimiter(l.Tag)
if err != nil {
l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err))
}
if _, r := limiter.CheckLimit(uuid, extractIPFromAddr(addr), addr.Network() == "tcp"); r {
l.logger.Warn("Need Reject", zap.String("addr", addr.String()), zap.String("uuid", uuid))
if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = true
}
} else {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = false
}
}
l.logger.Debug("TCP request", zap.String("addr", addr.String()), zap.String("uuid", uuid), zap.String("reqAddr", reqAddr))
}
@@ -80,12 +93,18 @@ func (l *serverLogger) TCPError(addr net.Addr, uuid, reqAddr string, err error)
}
func (l *serverLogger) UDPRequest(addr net.Addr, uuid string, sessionId uint32, reqAddr string) {
limiter, err := limiter.GetLimiter(l.Tag)
limiterinfo, err := limiter.GetLimiter(l.Tag)
if err != nil {
l.logger.Panic("Get limiter error", zap.String("tag", l.Tag), zap.Error(err))
}
if _, r := limiter.CheckLimit(uuid, extractIPFromAddr(addr), addr.Network() == "tcp"); r {
l.logger.Warn("Need Reject", zap.String("addr", addr.String()), zap.String("uuid", uuid))
if _, r := limiterinfo.CheckLimit(format.UserTag(l.Tag, uuid), extractIPFromAddr(addr), addr.Network() == "tcp"); r {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = true
}
} else {
if userLimit, ok := limiterinfo.UserLimitInfo.Load(format.UserTag(l.Tag, uuid)); ok {
userLimit.(*limiter.UserLimitInfo).OverLimit = false
}
}
l.logger.Debug("UDP request", zap.String("addr", addr.String()), zap.String("uuid", uuid), zap.Uint32("sessionId", sessionId), zap.String("reqAddr", reqAddr))
}

View File

@@ -1,11 +1,9 @@
package hy2
import (
"fmt"
"github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf"
"github.com/apernet/hysteria/core/server"
"github.com/apernet/hysteria/core/v2/server"
"github.com/spf13/viper"
"go.uber.org/zap"
)
@@ -31,8 +29,6 @@ func (h *Hysteria2) AddNode(tag string, info *panel.NodeInfo, config *conf.Optio
if err := v.Unmarshal(&c); err != nil {
h.Logger.Fatal("failed to parse server config", zap.Error(err))
}
h.Logger.Debug("loaded server config:")
fmt.Printf("%+v", c)
}
n := Hysteria2node{
Tag: tag,
@@ -42,11 +38,12 @@ func (h *Hysteria2) AddNode(tag string, info *panel.NodeInfo, config *conf.Optio
logger: h.Logger,
},
TrafficLogger: &HookServer{
Tag: tag,
Tag: tag,
logger: h.Logger,
},
}
hyconfig, err = n.getHyConfig(tag, info, config, &c)
hyconfig, err = n.getHyConfig(info, config, &c)
if err != nil {
return err
}

View File

@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/apernet/hysteria/extras/outbounds"
"github.com/apernet/hysteria/extras/v2/outbounds"
)
type serverConfig struct {

View File

@@ -7,7 +7,7 @@ import (
"github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/common/counter"
vCore "github.com/InazumaV/V2bX/core"
"github.com/apernet/hysteria/core/server"
"github.com/apernet/hysteria/core/v2/server"
)
var _ server.Authenticator = &V2bX{}

View File

@@ -8,6 +8,7 @@ import (
"github.com/sagernet/sing-box/common/urltest"
"github.com/InazumaV/V2bX/common/format"
"github.com/InazumaV/V2bX/common/rate"
"github.com/InazumaV/V2bX/limiter"
@@ -16,9 +17,14 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
)
var _ adapter.ClashServer = (*HookServer)(nil)
type HookServer struct {
ctx context.Context
urlTestHistory *urltest.HistoryStorage
EnableConnClear bool
counter sync.Map
connClears sync.Map
@@ -55,12 +61,18 @@ func (h *HookServer) ModeList() []string {
return nil
}
func NewHookServer(enableClear bool) *HookServer {
return &HookServer{
func NewHookServer(ctx context.Context, enableClear bool) *HookServer {
server := &HookServer{
ctx: ctx,
EnableConnClear: enableClear,
counter: sync.Map{},
connClears: sync.Map{},
}
server.urlTestHistory = service.PtrFromContext[urltest.HistoryStorage](ctx)
if server.urlTestHistory == nil {
server.urlTestHistory = urltest.NewHistoryStorage()
}
return server
}
func (h *HookServer) Start() error {
@@ -68,6 +80,7 @@ func (h *HookServer) Start() error {
}
func (h *HookServer) Close() error {
h.urlTestHistory.Close()
return nil
}
@@ -95,7 +108,7 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte
return conn, t
}
ip := m.Source.Addr.String()
if b, r := l.CheckLimit(m.User, ip, true); r {
if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true); r {
conn.Close()
log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
return conn, t
@@ -149,7 +162,7 @@ func (h *HookServer) RoutedPacketConnection(_ context.Context, conn N.PacketConn
return conn, t
}
ip := m.Source.Addr.String()
if b, r := l.CheckLimit(m.User, ip, true); r {
if b, r := l.CheckLimit(format.UserTag(m.Inbound, m.User), ip, true); r {
conn.Close()
log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
return conn, t
@@ -192,7 +205,7 @@ func (h *HookServer) CacheFile() adapter.CacheFile {
return nil
}
func (h *HookServer) HistoryStorage() *urltest.HistoryStorage {
return nil
return h.urlTestHistory
}
func (h *HookServer) StoreFakeIP() bool {

View File

@@ -40,6 +40,15 @@ type WsNetworkConfig struct {
Headers map[string]string `json:"headers"`
}
type GrpcNetworkConfig struct {
ServiceName string `json:"serviceName"`
}
type HttpupgradeNetworkConfig struct {
Path string `json:"path"`
Host string `json:"host"`
}
func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (option.Inbound, error) {
addr, err := netip.ParseAddr(c.ListenIP)
if err != nil {
@@ -91,7 +100,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
Enabled: true,
ShortID: []string{v.TlsSettings.ShortId},
PrivateKey: v.TlsSettings.PrivateKey,
Xver: v.TlsSettings.Xver,
Xver: uint8(v.TlsSettings.Xver),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: dest,
@@ -170,12 +179,28 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
Headers: headers,
}
case "grpc":
network := GrpcNetworkConfig{}
if len(n.NetworkSettings) != 0 {
err := json.Unmarshal(n.NetworkSettings, &t.GRPCOptions)
err := json.Unmarshal(n.NetworkSettings, &network)
if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
}
}
t.GRPCOptions = option.V2RayGRPCOptions{
ServiceName: network.ServiceName,
}
case "httpupgrade":
network := HttpupgradeNetworkConfig{}
if len(n.NetworkSettings) != 0 {
err := json.Unmarshal(n.NetworkSettings, &network)
if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
}
}
t.HTTPUpgradeOptions = option.V2RayHTTPUpgradeOptions{
Path: network.Path,
Host: network.Host,
}
}
if info.Type == "vless" {
in.Type = "vless"
@@ -203,7 +228,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
switch n.Cipher {
case "2022-blake3-aes-128-gcm":
keyLength = 16
case "2022-blake3-aes-256-gcm":
case "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305":
keyLength = 32
default:
keyLength = 16
@@ -263,12 +288,16 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
Headers: headers,
}
case "grpc":
network := GrpcNetworkConfig{}
if len(n.NetworkSettings) != 0 {
err := json.Unmarshal(n.NetworkSettings, &t.GRPCOptions)
err := json.Unmarshal(n.NetworkSettings, &network)
if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
}
}
t.GRPCOptions = option.V2RayGRPCOptions{
ServiceName: network.ServiceName,
}
default:
t.Type = ""
}
@@ -348,6 +377,7 @@ func (b *Sing) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) e
b.ctx,
b.box.Router(),
b.logFactory.NewLogger(F.ToString("inbound/", c.Type, "[", tag, "]")),
tag,
c,
nil,
)

View File

@@ -3,7 +3,6 @@ package sing
import (
"context"
"fmt"
"io"
"os"
"github.com/sagernet/sing-box/log"
@@ -57,33 +56,12 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
options.NTP = &option.NTPOptions{
Enabled: c.SingConfig.NtpConfig.Enable,
WriteToSystem: true,
Server: c.SingConfig.NtpConfig.Server,
ServerPort: c.SingConfig.NtpConfig.ServerPort,
ServerOptions: option.ServerOptions{
Server: c.SingConfig.NtpConfig.Server,
ServerPort: c.SingConfig.NtpConfig.ServerPort,
},
}
os.Setenv("SING_DNS_PATH", "")
options.DNS = &option.DNSOptions{}
if c.SingConfig.DnsConfigPath != "" {
f, err := os.OpenFile(c.SingConfig.DnsConfigPath, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
return nil, fmt.Errorf("failed to open or create sing dns config file: %s", err)
}
defer f.Close()
data, err := io.ReadAll(f)
if err != nil {
log.Warn(fmt.Sprintf(
"Failed to read sing dns config from file '%v': %v. Using default DNS options",
f.Name(), err))
options.DNS = &option.DNSOptions{}
} else {
if err := json.Unmarshal(data, options.DNS); err != nil {
log.Warn(fmt.Sprintf(
"Failed to unmarshal sing dns config from file '%v': %v. Using default DNS options",
f.Name(), err))
options.DNS = &option.DNSOptions{}
}
}
os.Setenv("SING_DNS_PATH", c.SingConfig.DnsConfigPath)
}
b, err := box.New(box.Options{
Context: context.Background(),
Options: options,
@@ -91,7 +69,7 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
if err != nil {
return nil, err
}
hs := NewHookServer(c.SingConfig.EnableConnClear)
hs := NewHookServer(b.Router().GetCtx(), c.SingConfig.EnableConnClear)
b.Router().SetClashServer(hs)
return &Sing{
ctx: b.Router().GetCtx(),

View File

@@ -5,6 +5,7 @@ package dispatcher
import (
"context"
"fmt"
"regexp"
"strings"
"sync"
"time"
@@ -14,6 +15,7 @@ import (
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
@@ -29,7 +31,7 @@ import (
"github.com/xtls/xray-core/transport/pipe"
)
var errSniffingTimeout = newError("timeout on sniffing")
var errSniffingTimeout = errors.New("timeout on sniffing")
type cachedReader struct {
sync.Mutex
@@ -157,6 +159,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (*
var user *protocol.MemoryUser
if sessionInbound != nil {
user = sessionInbound.User
sessionInbound.CanSpliceCopy = 3
}
var limit *limiter.Limiter
@@ -164,24 +167,24 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network) (*
if user != nil && len(user.Email) > 0 {
limit, err = limiter.GetLimiter(sessionInbound.Tag)
if err != nil {
newError("get limiter ", sessionInbound.Tag, " error: ", err).AtError().WriteToLog()
errors.LogInfo(ctx, "get limiter ", sessionInbound.Tag, " error: ", err)
common.Close(outboundLink.Writer)
common.Close(inboundLink.Writer)
common.Interrupt(outboundLink.Reader)
common.Interrupt(inboundLink.Reader)
return nil, nil, nil, newError("get limiter ", sessionInbound.Tag, " error: ", err)
return nil, nil, nil, errors.New("get limiter ", sessionInbound.Tag, " error: ", err)
}
// Speed Limit and Device Limit
w, reject := limit.CheckLimit(user.Email,
sessionInbound.Source.Address.IP().String(),
network == net.Network_TCP)
if reject {
newError("Limited ", user.Email, " by conn or ip").AtWarning().WriteToLog()
errors.LogInfo(ctx, "Limited ", user.Email, " by conn or ip")
common.Close(outboundLink.Writer)
common.Close(inboundLink.Writer)
common.Interrupt(outboundLink.Reader)
common.Interrupt(inboundLink.Reader)
return nil, nil, nil, newError("Limited ", user.Email, " by conn or ip")
return nil, nil, nil, errors.New("Limited ", user.Email, " by conn or ip")
}
if w != nil {
inboundLink.Writer = rate.NewRateLimitWriter(inboundLink.Writer, w)
@@ -217,8 +220,20 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
return false
}
for _, d := range request.ExcludeForDomain {
if strings.ToLower(domain) == d {
return false
if strings.HasPrefix(d, "regexp:") {
pattern := d[7:]
re, err := regexp.Compile(pattern)
if err != nil {
errors.LogInfo(ctx, "Unable to compile regex")
continue
}
if re.MatchString(domain) {
return false
}
} else {
if strings.ToLower(domain) == d {
return false
}
}
}
protocolString := result.Protocol()
@@ -231,7 +246,7 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
}
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
destination.Address.Family().IsIP() && fkr0.IsIPInIPPool(destination.Address) {
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "Using sniffer ", protocolString, " since the fake DNS missed")
return true
}
if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
@@ -249,11 +264,14 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
if !destination.IsValid() {
panic("Dispatcher: Invalid destination.")
}
ob := &session.Outbound{
OriginalTarget: destination,
Target: destination,
outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 {
outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
}
ctx = session.ContextWithOutbound(ctx, ob)
ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination
ob.Target = destination
content := session.ContentFromContext(ctx)
if content == nil {
content = new(session.Content)
@@ -278,7 +296,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
}
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain)
protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok {
@@ -303,13 +321,16 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
// DispatchLink implements routing.Dispatcher.
func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error {
if !destination.IsValid() {
return newError("Dispatcher: Invalid destination.")
return errors.New("Dispatcher: Invalid destination.")
}
ob := &session.Outbound{
OriginalTarget: destination,
Target: destination,
outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 {
outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
}
ctx = session.ContextWithOutbound(ctx, ob)
ob := outbounds[len(outbounds)-1]
ob.OriginalTarget = destination
ob.Target = destination
content := session.ContentFromContext(ctx)
if content == nil {
content = new(session.Content)
@@ -329,7 +350,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
}
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "sniffed domain: ", domain)
destination.Address = net.ParseAddress(domain)
protocol := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok {
@@ -399,7 +420,8 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
}
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination, l *limiter.Limiter, protocol string) {
ob := session.OutboundFromContext(ctx)
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
proxied := hosts.LookupHosts(ob.Target.String())
if proxied != nil {
@@ -426,7 +448,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
var err error
l, err = limiter.GetLimiter(sessionInbound.Tag)
if err != nil {
newError("get limiter ", sessionInbound.Tag, " error: ", err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
errors.LogError(ctx, "get limiter ", sessionInbound.Tag, " error: ", err)
}
}
if l != nil {
@@ -437,20 +459,20 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
destStr = destination.Address.IP().String()
}
if l.CheckDomainRule(destStr) {
newError(fmt.Sprintf(
errors.LogError(ctx, fmt.Sprintf(
"User %s access domain %s reject by rule",
sessionInbound.User.Email,
destStr)).AtWarning().WriteToLog(session.ExportIDToError(ctx))
destStr))
common.Close(link.Writer)
common.Interrupt(link.Reader)
return
}
if len(protocol) != 0 {
if l.CheckProtocolRule(protocol) {
newError(fmt.Sprintf(
errors.LogError(ctx, fmt.Sprintf(
"User %s access protocol %s reject by rule",
sessionInbound.User.Email,
protocol)).AtWarning().WriteToLog(session.ExportIDToError(ctx))
protocol))
common.Close(link.Writer)
common.Interrupt(link.Reader)
return
@@ -468,10 +490,10 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
ctx = session.SetForcedOutboundTagToContext(ctx, "")
if h := d.ohm.GetHandler(forcedOutboundTag); h != nil {
isPickRoute = 1
newError("taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]")
handler = h
} else {
newError("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx))
errors.LogError(ctx, "non existing tag for platform initialized detour: ", forcedOutboundTag)
common.Close(link.Writer)
common.Interrupt(link.Reader)
return
@@ -481,13 +503,13 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
outTag := route.GetOutboundTag()
if h := d.ohm.GetHandler(outTag); h != nil {
isPickRoute = 2
newError("taking detour [", outTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
handler = h
} else {
newError("non existing outTag: ", outTag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
errors.LogWarning(ctx, "non existing outTag: ", outTag)
}
} else {
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "default route for ", destination)
}
}
@@ -500,7 +522,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
}
if handler == nil {
newError("default outbound handler not exist").WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "default outbound handler not exist")
common.Close(link.Writer)
common.Interrupt(link.Reader)
return

View File

@@ -1,9 +0,0 @@
package dispatcher
import "github.com/xtls/xray-core/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View File

@@ -5,6 +5,7 @@ import (
"strings"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core"
@@ -22,15 +23,16 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
}
if fakeDNSEngine == nil {
errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
return protocolSnifferWithMetadata{}, errNotInit
}
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
Target := session.OutboundFromContext(ctx).Target
if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP {
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address)
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
if domainFromFakeDNS != "" {
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
errors.LogInfo(ctx, "fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String())
return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
}
}
@@ -38,7 +40,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil {
ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt)
if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
inPool := fkr0.IsIPInIPPool(Target.Address)
inPool := fkr0.IsIPInIPPool(ob.Target.Address)
ipAddressInRangeValue.addressInRange = &inPool
}
}
@@ -108,10 +110,10 @@ func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWit
}
return nil, common.ErrNoClue
}
newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog()
errors.LogDebug(ctx, "ip address not in fake dns range, return as is")
return nil, common.ErrNoClue
}
newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog()
errors.LogWarning(ctx, "fake dns sniffer did not set address in range option, assume false.")
return nil, common.ErrNoClue
},
metadataSniffer: false,

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/bittorrent"
"github.com/xtls/xray-core/common/protocol/http"
@@ -52,7 +53,7 @@ func NewSniffer(ctx context.Context) *Sniffer {
return ret
}
var errUnknownContent = newError("unknown content")
var errUnknownContent = errors.New("unknown content")
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
var pendingSniffer []protocolSnifferWithMetadata

View File

@@ -26,8 +26,12 @@ func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*
err = buildV2ray(option, nodeInfo, in)
network = nodeInfo.VAllss.Network
case "trojan":
err = buildTrojan(option, in)
network = "tcp"
err = buildTrojan(option, nodeInfo, in)
if nodeInfo.Trojan.Network != "" {
network = nodeInfo.Trojan.Network
} else {
network = "tcp"
}
case "shadowsocks":
err = buildShadowsocks(option, nodeInfo, in)
network = "tcp"
@@ -69,8 +73,13 @@ func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*
in.StreamSetting.TCPSettings = tcpSetting
}
case "ws":
in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol} //Enable proxy protocol
if in.StreamSetting.WSSettings != nil {
in.StreamSetting.WSSettings.AcceptProxyProtocol = option.XrayOptions.EnableProxyProtocol
} else {
in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
} //Enable proxy protocol
}
default:
socketConfig := &coreConf.SocketConfig{
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
@@ -105,9 +114,17 @@ func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*
// Reality
in.StreamSetting.Security = "reality"
v := nodeInfo.VAllss
dest := v.TlsSettings.Dest
if dest == "" {
dest = v.TlsSettings.ServerName
}
xver := v.TlsSettings.Xver
if xver == 0 {
xver = v.RealityConfig.Xver
}
d, err := json.Marshal(fmt.Sprintf(
"%s:%s",
v.TlsSettings.ServerName,
dest,
v.TlsSettings.ServerPort))
if err != nil {
return nil, fmt.Errorf("marshal reality dest error: %s", err)
@@ -115,7 +132,7 @@ func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*
mtd, _ := time.ParseDuration(v.RealityConfig.MaxTimeDiff)
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
Dest: d,
Xver: v.RealityConfig.Xver,
Xver: xver,
ServerNames: []string{v.TlsSettings.ServerName},
PrivateKey: v.TlsSettings.PrivateKey,
MinClientVer: v.RealityConfig.MinClientVer,
@@ -123,6 +140,7 @@ func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*
MaxTimeDiff: uint64(mtd.Microseconds()),
ShortIds: []string{v.TlsSettings.ShortId},
}
default:
break
}
in.Tag = tag
@@ -190,14 +208,35 @@ func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreCon
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
case "http":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.HTTPSettings)
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
case "quic":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.QUICSettings)
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
case "httpupgrade":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.HTTPUPGRADESettings)
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
case "splithttp":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.SplitHTTPSettings)
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
default:
return errors.New("the network type is not vail")
}
return nil
}
func buildTrojan(config *conf.Options, inbound *coreConf.InboundDetourConfig) error {
func buildTrojan(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
inbound.Protocol = "trojan"
v := nodeInfo.Trojan
if config.XrayOptions.EnableFallback {
// Set fallback
fallbackConfigs, err := buildTrojanFallbacks(config.XrayOptions.FallBackConfigs)
@@ -215,8 +254,31 @@ func buildTrojan(config *conf.Options, inbound *coreConf.InboundDetourConfig) er
s := []byte("{}")
inbound.Settings = (*json.RawMessage)(&s)
}
t := coreConf.TransportProtocol("tcp")
network := v.Network
if network == "" {
network = "tcp"
}
t := coreConf.TransportProtocol(network)
inbound.StreamSetting = &coreConf.StreamConfig{Network: &t}
switch network {
case "tcp":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.TCPSettings)
if err != nil {
return fmt.Errorf("unmarshal tcp settings error: %s", err)
}
case "ws":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.WSSettings)
if err != nil {
return fmt.Errorf("unmarshal ws settings error: %s", err)
}
case "grpc":
err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.GRPCConfig)
if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err)
}
default:
return errors.New("the network type is not vail")
}
return nil
}

View File

@@ -5,7 +5,6 @@ import (
conf2 "github.com/InazumaV/V2bX/conf"
"github.com/goccy/go-json"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/infra/conf"
)
@@ -18,8 +17,7 @@ func buildOutbound(config *conf2.Options, tag string) (*core.OutboundHandlerConf
// Build Send IP address
if config.SendIP != "" {
ipAddress := net.ParseAddress(config.SendIP)
outboundDetourConfig.SendThrough = &conf.Address{Address: ipAddress}
outboundDetourConfig.SendThrough = &config.SendIP
}
// Freedom Protocol setting

250
go.mod
View File

@@ -2,105 +2,125 @@ module github.com/InazumaV/V2bX
go 1.22
toolchain go1.22.0
toolchain go1.22.5
require (
github.com/apernet/hysteria/core v1.3.5-0.20240201034858-bb99579bb92c
github.com/apernet/hysteria/extras v0.0.0-20240201034858-bb99579bb92c
github.com/apernet/hysteria/core/v2 v2.5.1-0.20240710201643-b563f3981fc6
github.com/apernet/hysteria/extras/v2 v2.5.1-0.20240710201643-b563f3981fc6
github.com/beevik/ntp v1.2.0
github.com/fsnotify/fsnotify v1.7.0
github.com/go-acme/lego/v4 v4.13.2
github.com/go-resty/resty/v2 v2.7.0
github.com/goccy/go-json v0.10.2
github.com/go-acme/lego/v4 v4.17.4
github.com/go-resty/resty/v2 v2.13.1
github.com/goccy/go-json v0.10.3
github.com/hashicorp/go-multierror v1.1.1
github.com/juju/ratelimit v1.0.2
github.com/sagernet/sing v0.3.2
github.com/sagernet/sing-box v1.9.0
github.com/sagernet/sing v0.5.0-alpha.12
github.com/sagernet/sing-box v1.10.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.15.0
github.com/xtls/xray-core v1.8.8
go.uber.org/zap v1.26.0
golang.org/x/crypto v0.19.0
golang.org/x/sys v0.17.0
google.golang.org/protobuf v1.32.0
github.com/xtls/xray-core v1.8.19
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.25.0
golang.org/x/sys v0.22.0
google.golang.org/protobuf v1.34.2
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)
require (
berty.tech/go-libtor v1.0.385 // indirect
cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/compute/metadata v0.3.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/sdk/azcore v1.6.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.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.2.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/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // 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/cli v0.4.6 // 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/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1755 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.62.712 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f // indirect
github.com/aws/aws-sdk-go v1.39.0 // indirect
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e // indirect
github.com/aws/aws-sdk-go-v2 v1.27.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.18 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.38.3 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect
github.com/aws/smithy-go v1.20.2 // indirect
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/caddyserver/certmagic v0.20.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cloudflare/cloudflare-go v0.70.0 // indirect
github.com/cloudflare/circl v1.3.9 // indirect
github.com/cloudflare/cloudflare-go v0.97.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cretz/bine v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v1.2.0 // indirect
github.com/exoscale/egoscale v0.100.1 // indirect
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
github.com/exoscale/egoscale v0.102.3 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect
github.com/go-chi/chi/v5 v5.0.11 // indirect
github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gofrs/uuid/v5 v5.0.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gofrs/uuid/v5 v5.2.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20240225044709-fd706174c886 // indirect
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gophercloud/gophercloud v1.0.0 // indirect
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/gophercloud/gophercloud v1.12.0 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
@@ -108,28 +128,28 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/libdns/alidns v1.0.3 // indirect
github.com/libdns/cloudflare v0.1.0 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/linode/linodego v1.17.2 // indirect
github.com/liquidweb/go-lwApi v0.0.5 // indirect
github.com/libdns/cloudflare v0.1.1 // indirect
github.com/libdns/libdns v0.2.2 // indirect
github.com/linode/linodego v1.28.0 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.3 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.58 // indirect
github.com/miekg/dns v1.1.61 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -137,113 +157,121 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/desec v0.7.0 // indirect
github.com/nrdcg/bunny-go v0.0.0-20240207213615-dde5bf4577a3 // indirect
github.com/nrdcg/desec v0.8.0 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.2.0 // indirect
github.com/nrdcg/goinwx v0.8.2 // indirect
github.com/nrdcg/goinwx v0.10.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/porkbun v0.2.0 // indirect
github.com/nrdcg/porkbun v0.3.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/ooni/go-libtor v1.1.8 // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oracle/oci-go-sdk/v65 v65.63.1 // indirect
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/ovh/go-ovh v1.4.1 // indirect
github.com/ovh/go-ovh v1.5.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/otp v1.4.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/quic-go/quic-go v0.41.0 // indirect
github.com/refraction-networking/utls v1.6.3 // indirect
github.com/quic-go/quic-go v0.45.1 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/sacloud/api-client-go v0.2.8 // indirect
github.com/sacloud/go-http v0.1.6 // indirect
github.com/sacloud/iaas-api-go v1.11.1 // indirect
github.com/sacloud/packages-go v0.0.9 // indirect
github.com/sacloud/api-client-go v0.2.10 // indirect
github.com/sacloud/go-http v0.1.8 // indirect
github.com/sacloud/iaas-api-go v1.12.0 // indirect
github.com/sacloud/packages-go v0.0.10 // indirect
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect
github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/sagernet/quic-go v0.41.0-beta.2 // indirect
github.com/sagernet/sing-dns v0.2.0-beta.6 // indirect
github.com/sagernet/fswatch v0.1.1 // indirect
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
github.com/sagernet/quic-go v0.45.1-beta.2 // indirect
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
github.com/sagernet/sing-dns v0.3.0-beta.10 // indirect
github.com/sagernet/sing-mux v0.2.0 // indirect
github.com/sagernet/sing-quic v0.1.9-beta.1 // indirect
github.com/sagernet/sing-shadowsocks v0.2.6 // indirect
github.com/sagernet/sing-quic v0.2.0-beta.12 // indirect
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
github.com/sagernet/sing-tun v0.2.2-beta.3 // indirect
github.com/sagernet/sing-vmess v0.1.8 // indirect
github.com/sagernet/sing-tun v0.4.0-beta.13.0.20240703164908-1f043289199d // indirect
github.com/sagernet/sing-vmess v0.1.12 // indirect
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 // indirect
github.com/sagernet/utls v1.5.4 // indirect
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17 // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
github.com/simplesurance/bunny-go v0.0.0-20221115111006-e11d9dc91f04 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/selectel/domains-go v1.1.0 // indirect
github.com/selectel/go-selvpcclient/v3 v3.1.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.1.2 // indirect
github.com/softlayer/softlayer-go v1.1.5 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.490 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.490 // indirect
github.com/transip/gotransip/v6 v6.20.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.898 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.898 // indirect
github.com/transip/gotransip/v6 v6.23.0 // indirect
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 // indirect
github.com/ultradns/ultradns-go-sdk v1.5.0-20230427130837-23c9b0c // indirect
github.com/ultradns/ultradns-go-sdk v1.6.1-20231103022937-8589b6a // indirect
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/vultr/govultr/v2 v2.17.2 // indirect
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20220805142335-27b56ddae16f // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20220805164847-cf028e604997 // indirect
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20240318083951-4fe6125f286e // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20240318084659-dfa50323a0b4 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
go.uber.org/ratelimit v0.3.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.18.0 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
google.golang.org/api v0.162.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect
google.golang.org/grpc v1.62.0 // indirect
google.golang.org/api v0.172.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/grpc v1.65.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.7.6 // indirect
gopkg.in/ns1/ns1-go.v2 v2.7.13 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b // indirect
lukechampine.com/blake3 v1.2.1 // indirect
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
lukechampine.com/blake3 v1.3.0 // indirect
)
//github.com/apernet/hysteria/core v1.3.5-0.20240201034858-bb99579bb92c => /root/hysteria/core
replace github.com/sagernet/sing-box v1.9.0 => github.com/wyx2685/sing-box_mod v0.0.4
replace github.com/sagernet/sing-box v1.10.0 => github.com/wyx2685/sing-box_mod v0.0.9

576
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,10 @@ type Limiter struct {
type UserLimitInfo struct {
UID int
SpeedLimit int
DeviceLimit int
DynamicSpeedLimit int
ExpireTime int64
OverLimit bool
}
func AddLimiter(tag string, l *conf.LimitConfig, users []panel.UserInfo) *Limiter {
@@ -60,13 +62,16 @@ func AddLimiter(tag string, l *conf.LimitConfig, users []panel.UserInfo) *Limite
uuidmap := make(map[string]int)
for i := range users {
uuidmap[users[i].Uuid] = users[i].Id
userLimit := &UserLimitInfo{}
userLimit.UID = users[i].Id
if users[i].SpeedLimit != 0 {
userLimit := &UserLimitInfo{
UID: users[i].Id,
SpeedLimit: users[i].SpeedLimit,
}
info.UserLimitInfo.Store(format.UserTag(tag, users[i].Uuid), userLimit)
userLimit.SpeedLimit = users[i].SpeedLimit
}
if users[i].DeviceLimit != 0 {
userLimit.DeviceLimit = users[i].DeviceLimit
}
userLimit.OverLimit = false
info.UserLimitInfo.Store(format.UserTag(tag, users[i].Uuid), userLimit)
}
info.UUIDtoUID = uuidmap
limitLock.Lock()
@@ -97,14 +102,18 @@ func (l *Limiter) UpdateUser(tag string, added []panel.UserInfo, deleted []panel
delete(l.UUIDtoUID, deleted[i].Uuid)
}
for i := range added {
if added[i].SpeedLimit != 0 {
userLimit := &UserLimitInfo{
UID: added[i].Id,
SpeedLimit: added[i].SpeedLimit,
ExpireTime: 0,
}
l.UserLimitInfo.Store(format.UserTag(tag, added[i].Uuid), userLimit)
userLimit := &UserLimitInfo{
UID: added[i].Id,
}
if added[i].SpeedLimit != 0 {
userLimit.SpeedLimit = added[i].SpeedLimit
userLimit.ExpireTime = 0
}
if added[i].DeviceLimit != 0 {
userLimit.DeviceLimit = added[i].DeviceLimit
}
userLimit.OverLimit = false
l.UserLimitInfo.Store(format.UserTag(tag, added[i].Uuid), userLimit)
l.UUIDtoUID[added[i].Uuid] = added[i].Id
}
}
@@ -120,23 +129,27 @@ func (l *Limiter) UpdateDynamicSpeedLimit(tag, uuid string, limit int, expire ti
return nil
}
func (l *Limiter) CheckLimit(uuid string, ip string, isTcp bool) (Bucket *ratelimit.Bucket, Reject bool) {
func (l *Limiter) CheckLimit(taguuid string, ip string, isTcp bool) (Bucket *ratelimit.Bucket, Reject bool) {
// ip and conn limiter
if l.ConnLimiter.AddConnCount(uuid, ip, isTcp) {
if l.ConnLimiter.AddConnCount(taguuid, ip, isTcp) {
return nil, true
}
// check and gen speed limit Bucket
nodeLimit := l.SpeedLimit
userLimit := 0
if v, ok := l.UserLimitInfo.Load(uuid); ok {
deviceLimit := 0
var uid int
if v, ok := l.UserLimitInfo.Load(taguuid); ok {
u := v.(*UserLimitInfo)
deviceLimit = u.DeviceLimit
uid = u.UID
if u.ExpireTime < time.Now().Unix() && u.ExpireTime != 0 {
if u.SpeedLimit != 0 {
userLimit = u.SpeedLimit
u.DynamicSpeedLimit = 0
u.ExpireTime = 0
} else {
l.UserLimitInfo.Delete(uuid)
l.UserLimitInfo.Delete(taguuid)
}
} else {
userLimit = determineSpeedLimit(u.SpeedLimit, u.DynamicSpeedLimit)
@@ -145,10 +158,9 @@ func (l *Limiter) CheckLimit(uuid string, ip string, isTcp bool) (Bucket *rateli
// Store online user for device limit
ipMap := new(sync.Map)
uid := l.UUIDtoUID[uuid]
ipMap.Store(ip, uid)
// If any device is online
if v, ok := l.UserOnlineIP.LoadOrStore(uuid, ipMap); ok {
if v, ok := l.UserOnlineIP.LoadOrStore(taguuid, ipMap); ok {
ipMap := v.(*sync.Map)
// If this is a new ip
if _, ok := ipMap.LoadOrStore(ip, uid); !ok {
@@ -157,16 +169,20 @@ func (l *Limiter) CheckLimit(uuid string, ip string, isTcp bool) (Bucket *rateli
counter++
return true
})
if counter > deviceLimit && deviceLimit > 0 {
ipMap.Delete(ip)
return nil, true
}
}
}
limit := int64(determineSpeedLimit(nodeLimit, userLimit)) * 1000000 / 8 // If you need the Speed limit
if limit > 0 {
Bucket = ratelimit.NewBucketWithQuantum(time.Second, limit, limit) // Byte/s
if v, ok := l.SpeedLimiter.LoadOrStore(uuid, Bucket); ok {
if v, ok := l.SpeedLimiter.LoadOrStore(taguuid, Bucket); ok {
return v.(*ratelimit.Bucket), false
} else {
l.SpeedLimiter.Store(uuid, Bucket)
l.SpeedLimiter.Store(taguuid, Bucket)
return Bucket, false
}
} else {

View File

@@ -1,7 +1,6 @@
package node
import (
"fmt"
"strconv"
"github.com/InazumaV/V2bX/api/panel"
@@ -60,7 +59,7 @@ func (c *Controller) reportUserTrafficTask() (err error) {
data := make(map[int][]string)
for _, onlineuser := range result {
// json structure: { UID1:["ip1","ip2"],UID2:["ip3","ip4"] }
data[onlineuser.UID] = append(data[onlineuser.UID], fmt.Sprintf("%s_%d", onlineuser.IP, c.info.Id))
data[onlineuser.UID] = append(data[onlineuser.UID], onlineuser.IP)
if _, ok := reportOnline[onlineuser.UID]; ok {
reportOnline[onlineuser.UID]++
} else {