sing内核支持面板rule规则
Some checks failed
Build and Release / build (386, freebsd) (push) Has been cancelled
Build and Release / build (386, linux) (push) Has been cancelled
Build and Release / build (386, windows) (push) Has been cancelled
Build and Release / build (amd64, darwin) (push) Has been cancelled
Build and Release / build (amd64, freebsd) (push) Has been cancelled
Build and Release / build (amd64, linux) (push) Has been cancelled
Build and Release / build (amd64, windows) (push) Has been cancelled
Build and Release / build (arm, 5, linux) (push) Has been cancelled
Build and Release / build (arm, 6, linux) (push) Has been cancelled
Build and Release / build (arm, 7, freebsd) (push) Has been cancelled
Build and Release / build (arm, 7, linux) (push) Has been cancelled
Build and Release / build (arm64, android) (push) Has been cancelled
Build and Release / build (arm64, darwin) (push) Has been cancelled
Build and Release / build (arm64, freebsd) (push) Has been cancelled
Build and Release / build (arm64, linux) (push) Has been cancelled
Build and Release / build (mips, linux) (push) Has been cancelled
Build and Release / build (mips64, linux) (push) Has been cancelled
Build and Release / build (mips64le, linux) (push) Has been cancelled
Build and Release / build (mipsle, linux) (push) Has been cancelled
Build and Release / build (ppc64, linux) (push) Has been cancelled
Build and Release / build (ppc64le, linux) (push) Has been cancelled
Build and Release / build (riscv64, linux) (push) Has been cancelled
Build and Release / build (s390x, linux) (push) Has been cancelled

This commit is contained in:
wyx2685 2025-01-10 16:33:05 +09:00
parent c755e9800b
commit 2f1362067b
No known key found for this signature in database
GPG Key ID: 8827A30FF1DB1379
10 changed files with 74 additions and 93 deletions

View File

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

View File

@ -41,7 +41,7 @@ func (h *Hysteria2) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
return len(p.Users), nil 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 var wg sync.WaitGroup
for _, user := range users { for _, user := range users {
wg.Add(1) wg.Add(1)

View File

@ -18,7 +18,7 @@ type Core interface {
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) 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 Protocols() []string
Type() string Type() string
} }

View File

@ -3,10 +3,11 @@ package core
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/hashicorp/go-multierror"
"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"
) )
@ -135,12 +136,12 @@ func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down
return t.(Core).GetUserTraffic(tag, uuid, reset) 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) t, e := s.nodes.Load(tag)
if !e { if !e {
return errors.New("the node is not have") 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 { func (s *Selector) Protocols() []string {

View File

@ -2,7 +2,7 @@ package sing
import ( import (
"context" "context"
"io" "fmt"
"net" "net"
"sync" "sync"
@ -20,47 +20,16 @@ import (
var _ adapter.ConnectionTracker = (*HookServer)(nil) var _ adapter.ConnectionTracker = (*HookServer)(nil)
type HookServer struct { type HookServer struct {
EnableConnClear bool
counter sync.Map 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()
}
} }
func (h *HookServer) ModeList() []string { func (h *HookServer) ModeList() []string {
return nil return nil
} }
func NewHookServer(enableClear bool) *HookServer { func NewHookServer() *HookServer {
server := &HookServer{ server := &HookServer{
EnableConnClear: enableClear,
counter: sync.Map{}, counter: sync.Map{},
connClears: sync.Map{},
} }
return server return server
} }
@ -79,14 +48,26 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte
} else if b != nil { } else if b != nil {
conn = rate.NewConnRateLimiter(conn, b) conn = rate.NewConnRateLimiter(conn, b)
} }
if h.EnableConnClear { if l != nil {
cc := &ConnClear{ destStr := m.Destination.AddrString()
conns: map[int]io.Closer{ protocol := m.Destination.Network()
0: conn, if l.CheckDomainRule(destStr) {
}, log.Error(fmt.Sprintf(
"User %s access domain %s reject by rule",
m.User,
destStr))
conn.Close()
return conn
}
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 v, ok := h.connClears.LoadOrStore(m.Inbound+m.User, cc); ok {
cc = v.(*ConnClear)
} }
} }
if c, ok := h.counter.Load(m.Inbound); ok { 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 { } else if b != nil {
//conn = rate.NewPacketConnCounter(conn, b) //conn = rate.NewPacketConnCounter(conn, b)
} }
if h.EnableConnClear { if l != nil {
cc := &ConnClear{ destStr := m.Destination.AddrString()
conns: map[int]io.Closer{ protocol := m.Destination.Network()
0: conn, if l.CheckDomainRule(destStr) {
}, log.Error(fmt.Sprintf(
"User %s access domain %s reject by rule",
m.User,
destStr))
conn.Close()
return conn
}
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 v, ok := h.connClears.LoadOrStore(m.Inbound+m.User, cc); ok {
cc = v.(*ConnClear)
} }
} }
if c, ok := h.counter.Load(m.Inbound); ok { 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)) 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)
}
}

View File

@ -71,7 +71,7 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
hs := NewHookServer(c.SingConfig.EnableConnClear) hs := NewHookServer()
b.Router().SetTracker(hs) b.Router().SetTracker(hs)
return &Sing{ return &Sing{
ctx: b.Router().GetCtx(), ctx: b.Router().GetCtx(),

View File

@ -22,8 +22,7 @@ func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) {
return 0, errors.New("the inbound not found") return 0, errors.New("the inbound not found")
} }
switch p.NodeInfo.Type { switch p.NodeInfo.Type {
case "vmess", "vless": case "vless":
if p.NodeInfo.Type == "vless" {
us := make([]option.VLESSUser, len(p.Users)) us := make([]option.VLESSUser, len(p.Users))
for i := range p.Users { for i := range p.Users {
us[i] = option.VLESSUser{ us[i] = option.VLESSUser{
@ -33,7 +32,7 @@ func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) {
} }
} }
err = in.(*vless.Inbound).AddUsers(us) err = in.(*vless.Inbound).AddUsers(us)
} else { case "vmess":
us := make([]option.VMessUser, len(p.Users)) us := make([]option.VMessUser, len(p.Users))
for i := range p.Users { for i := range p.Users {
us[i] = option.VMessUser{ us[i] = option.VMessUser{
@ -42,7 +41,6 @@ func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) {
} }
} }
err = in.(*vmess.Inbound).AddUsers(us) err = in.(*vmess.Inbound).AddUsers(us)
}
case "shadowsocks": case "shadowsocks":
us := make([]option.ShadowsocksUser, len(p.Users)) us := make([]option.ShadowsocksUser, len(p.Users))
for i := range p.Users { for i := range p.Users {
@ -112,10 +110,10 @@ type UserDeleter interface {
DelUsers(uuid []string) error 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 var del UserDeleter
if i, found := b.box.Inbound().Get(tag); found { if i, found := b.box.Inbound().Get(tag); found {
switch i.Type() { switch info.Type {
case "vmess": case "vmess":
del = i.(*vmess.Inbound) del = i.(*vmess.Inbound)
case "vless": case "vless":
@ -134,7 +132,6 @@ func (b *Sing) DelUsers(users []panel.UserInfo, tag string) error {
} }
uuids := make([]string, len(users)) uuids := make([]string, len(users))
for i := range users { for i := range users {
b.hookServer.ClearConn(tag, users[i].Uuid)
uuids[i] = users[i].Uuid uuids[i] = users[i].Uuid
} }
err := del.DelUsers(uuids) err := del.DelUsers(uuids)

View File

@ -27,7 +27,7 @@ func (c *Xray) GetUserManager(tag string) (proxy.UserManager, error) {
return userManager, nil 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) userManager, err := c.GetUserManager(tag)
if err != nil { if err != nil {
return fmt.Errorf("get user manager error: %s", err) return fmt.Errorf("get user manager error: %s", err)

View File

@ -28,9 +28,7 @@
}, },
"DnsConfigPath": "/etc/V2bX/dns.json", "DnsConfigPath": "/etc/V2bX/dns.json",
// SingBoxSingBox // SingBoxSingBox
"OriginalPath": "/etc/V2bX/sing_origin.json", "OriginalPath": "/etc/V2bX/sing_origin.json"
//
"EnableConnClear": false,
}, },
{ {
"Type": "sing", "Type": "sing",

View File

@ -178,7 +178,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
deleted, added := compareUserList(c.userList, newU) deleted, added := compareUserList(c.userList, newU)
if len(deleted) > 0 { if len(deleted) > 0 {
// have deleted users // have deleted users
err = c.server.DelUsers(deleted, c.tag) err = c.server.DelUsers(deleted, c.tag, c.info)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"tag": c.tag, "tag": c.tag,