From 2f1362067b9df4b91003d34c2de1ccd9703d5e1d Mon Sep 17 00:00:00 2001 From: wyx2685 Date: Fri, 10 Jan 2025 16:33:05 +0900 Subject: [PATCH] =?UTF-8?q?sing=E5=86=85=E6=A0=B8=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=9D=A2=E6=9D=BFrule=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/sing.go | 7 ++- core/hy2/user.go | 2 +- core/interface.go | 2 +- core/selector.go | 7 +-- core/sing/hook.go | 98 +++++++++++++++++----------------------- core/sing/sing.go | 2 +- core/sing/user.go | 41 ++++++++--------- core/xray/user.go | 2 +- example/config_full.json | 4 +- node/task.go | 2 +- 10 files changed, 74 insertions(+), 93 deletions(-) diff --git a/conf/sing.go b/conf/sing.go index 0ae8e17..eb9be75 100644 --- a/conf/sing.go +++ b/conf/sing.go @@ -5,10 +5,9 @@ import ( ) type SingConfig struct { - LogConfig SingLogConfig `json:"Log"` - NtpConfig SingNtpConfig `json:"NTP"` - EnableConnClear bool `json:"EnableConnClear"` - OriginalPath string `json:"OriginalPath"` + LogConfig SingLogConfig `json:"Log"` + NtpConfig SingNtpConfig `json:"NTP"` + OriginalPath string `json:"OriginalPath"` } type SingLogConfig struct { diff --git a/core/hy2/user.go b/core/hy2/user.go index b599e1e..226cf4b 100644 --- a/core/hy2/user.go +++ b/core/hy2/user.go @@ -41,7 +41,7 @@ func (h *Hysteria2) AddUsers(p *vCore.AddUsersParams) (added int, err error) { return len(p.Users), nil } -func (h *Hysteria2) DelUsers(users []panel.UserInfo, tag string) error { +func (h *Hysteria2) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeInfo) error { var wg sync.WaitGroup for _, user := range users { wg.Add(1) diff --git a/core/interface.go b/core/interface.go index 464baa0..1a5c763 100644 --- a/core/interface.go +++ b/core/interface.go @@ -18,7 +18,7 @@ type Core interface { DelNode(tag string) error AddUsers(p *AddUsersParams) (added int, err error) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) - DelUsers(users []panel.UserInfo, tag string) error + DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error Protocols() []string Type() string } diff --git a/core/selector.go b/core/selector.go index 063cbc1..de73dc6 100644 --- a/core/selector.go +++ b/core/selector.go @@ -3,10 +3,11 @@ package core import ( "errors" "fmt" - "github.com/hashicorp/go-multierror" "strings" "sync" + "github.com/hashicorp/go-multierror" + "github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/conf" ) @@ -135,12 +136,12 @@ func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down return t.(Core).GetUserTraffic(tag, uuid, reset) } -func (s *Selector) DelUsers(users []panel.UserInfo, tag string) error { +func (s *Selector) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error { t, e := s.nodes.Load(tag) if !e { return errors.New("the node is not have") } - return t.(Core).DelUsers(users, tag) + return t.(Core).DelUsers(users, tag, info) } func (s *Selector) Protocols() []string { diff --git a/core/sing/hook.go b/core/sing/hook.go index 9401992..9bce059 100644 --- a/core/sing/hook.go +++ b/core/sing/hook.go @@ -2,7 +2,7 @@ package sing import ( "context" - "io" + "fmt" "net" "sync" @@ -20,47 +20,16 @@ import ( var _ adapter.ConnectionTracker = (*HookServer)(nil) type HookServer struct { - EnableConnClear bool - counter sync.Map - connClears sync.Map -} - -type ConnClear struct { - lock sync.RWMutex - conns map[int]io.Closer -} - -func (c *ConnClear) AddConn(cn io.Closer) (key int) { - c.lock.Lock() - defer c.lock.Unlock() - key = len(c.conns) - c.conns[key] = cn - return -} - -func (c *ConnClear) DelConn(key int) { - c.lock.Lock() - defer c.lock.Unlock() - delete(c.conns, key) -} - -func (c *ConnClear) ClearConn() { - c.lock.Lock() - defer c.lock.Unlock() - for _, c := range c.conns { - c.Close() - } + counter sync.Map } func (h *HookServer) ModeList() []string { return nil } -func NewHookServer(enableClear bool) *HookServer { +func NewHookServer() *HookServer { server := &HookServer{ - EnableConnClear: enableClear, - counter: sync.Map{}, - connClears: sync.Map{}, + counter: sync.Map{}, } return server } @@ -79,14 +48,26 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte } else if b != nil { conn = rate.NewConnRateLimiter(conn, b) } - if h.EnableConnClear { - cc := &ConnClear{ - conns: map[int]io.Closer{ - 0: conn, - }, + if l != nil { + destStr := m.Destination.AddrString() + protocol := m.Destination.Network() + if l.CheckDomainRule(destStr) { + log.Error(fmt.Sprintf( + "User %s access domain %s reject by rule", + m.User, + destStr)) + conn.Close() + return conn } - if v, ok := h.connClears.LoadOrStore(m.Inbound+m.User, cc); ok { - cc = v.(*ConnClear) + if len(protocol) != 0 { + if l.CheckProtocolRule(protocol) { + log.Error(fmt.Sprintf( + "User %s access protocol %s reject by rule", + m.User, + protocol)) + conn.Close() + return conn + } } } if c, ok := h.counter.Load(m.Inbound); ok { @@ -112,14 +93,26 @@ func (h *HookServer) RoutedPacketConnection(_ context.Context, conn N.PacketConn } else if b != nil { //conn = rate.NewPacketConnCounter(conn, b) } - if h.EnableConnClear { - cc := &ConnClear{ - conns: map[int]io.Closer{ - 0: conn, - }, + if l != nil { + destStr := m.Destination.AddrString() + protocol := m.Destination.Network() + if l.CheckDomainRule(destStr) { + log.Error(fmt.Sprintf( + "User %s access domain %s reject by rule", + m.User, + destStr)) + conn.Close() + return conn } - if v, ok := h.connClears.LoadOrStore(m.Inbound+m.User, cc); ok { - cc = v.(*ConnClear) + if len(protocol) != 0 { + if l.CheckProtocolRule(protocol) { + log.Error(fmt.Sprintf( + "User %s access protocol %s reject by rule", + m.User, + protocol)) + conn.Close() + return conn + } } } if c, ok := h.counter.Load(m.Inbound); ok { @@ -130,10 +123,3 @@ func (h *HookServer) RoutedPacketConnection(_ context.Context, conn N.PacketConn return counter.NewPacketConnCounter(conn, c.GetCounter(m.User)) } } - -func (h *HookServer) ClearConn(inbound string, user string) { - if v, ok := h.connClears.Load(inbound + user); ok { - v.(*ConnClear).ClearConn() - h.connClears.Delete(inbound + user) - } -} diff --git a/core/sing/sing.go b/core/sing/sing.go index 3a333ae..02cee82 100644 --- a/core/sing/sing.go +++ b/core/sing/sing.go @@ -71,7 +71,7 @@ func New(c *conf.CoreConfig) (vCore.Core, error) { if err != nil { return nil, err } - hs := NewHookServer(c.SingConfig.EnableConnClear) + hs := NewHookServer() b.Router().SetTracker(hs) return &Sing{ ctx: b.Router().GetCtx(), diff --git a/core/sing/user.go b/core/sing/user.go index f098e44..7668c8e 100644 --- a/core/sing/user.go +++ b/core/sing/user.go @@ -22,27 +22,25 @@ func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) { return 0, errors.New("the inbound not found") } switch p.NodeInfo.Type { - case "vmess", "vless": - if p.NodeInfo.Type == "vless" { - us := make([]option.VLESSUser, len(p.Users)) - for i := range p.Users { - us[i] = option.VLESSUser{ - Name: p.Users[i].Uuid, - Flow: p.VAllss.Flow, - UUID: p.Users[i].Uuid, - } + case "vless": + us := make([]option.VLESSUser, len(p.Users)) + for i := range p.Users { + us[i] = option.VLESSUser{ + Name: p.Users[i].Uuid, + Flow: p.VAllss.Flow, + UUID: p.Users[i].Uuid, } - err = in.(*vless.Inbound).AddUsers(us) - } else { - us := make([]option.VMessUser, len(p.Users)) - for i := range p.Users { - us[i] = option.VMessUser{ - Name: p.Users[i].Uuid, - UUID: p.Users[i].Uuid, - } - } - err = in.(*vmess.Inbound).AddUsers(us) } + err = in.(*vless.Inbound).AddUsers(us) + case "vmess": + us := make([]option.VMessUser, len(p.Users)) + for i := range p.Users { + us[i] = option.VMessUser{ + Name: p.Users[i].Uuid, + UUID: p.Users[i].Uuid, + } + } + err = in.(*vmess.Inbound).AddUsers(us) case "shadowsocks": us := make([]option.ShadowsocksUser, len(p.Users)) for i := range p.Users { @@ -112,10 +110,10 @@ type UserDeleter interface { DelUsers(uuid []string) error } -func (b *Sing) DelUsers(users []panel.UserInfo, tag string) error { +func (b *Sing) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error { var del UserDeleter if i, found := b.box.Inbound().Get(tag); found { - switch i.Type() { + switch info.Type { case "vmess": del = i.(*vmess.Inbound) case "vless": @@ -134,7 +132,6 @@ func (b *Sing) DelUsers(users []panel.UserInfo, tag string) error { } uuids := make([]string, len(users)) for i := range users { - b.hookServer.ClearConn(tag, users[i].Uuid) uuids[i] = users[i].Uuid } err := del.DelUsers(uuids) diff --git a/core/xray/user.go b/core/xray/user.go index 81ff7ef..b98e84b 100644 --- a/core/xray/user.go +++ b/core/xray/user.go @@ -27,7 +27,7 @@ func (c *Xray) GetUserManager(tag string) (proxy.UserManager, error) { return userManager, nil } -func (c *Xray) DelUsers(users []panel.UserInfo, tag string) error { +func (c *Xray) DelUsers(users []panel.UserInfo, tag string, _ *panel.NodeInfo) error { userManager, err := c.GetUserManager(tag) if err != nil { return fmt.Errorf("get user manager error: %s", err) diff --git a/example/config_full.json b/example/config_full.json index 44b4769..a188bd7 100644 --- a/example/config_full.json +++ b/example/config_full.json @@ -28,9 +28,7 @@ }, "DnsConfigPath": "/etc/V2bX/dns.json", // SingBox源配置文件目录,用于引用标准SingBox配置文件 - "OriginalPath": "/etc/V2bX/sing_origin.json", - // 在删除用户时清理已建立的连接 - "EnableConnClear": false, + "OriginalPath": "/etc/V2bX/sing_origin.json" }, { "Type": "sing", diff --git a/node/task.go b/node/task.go index adaf0fc..f70ccb1 100644 --- a/node/task.go +++ b/node/task.go @@ -178,7 +178,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { deleted, added := compareUserList(c.userList, newU) if len(deleted) > 0 { // have deleted users - err = c.server.DelUsers(deleted, c.tag) + err = c.server.DelUsers(deleted, c.tag, c.info) if err != nil { log.WithFields(log.Fields{ "tag": c.tag,