update example, add realtime option, fix ip limit bug for packet protocol

This commit is contained in:
yuzuki999
2023-05-17 09:46:52 +08:00
parent c6658c2ce1
commit 48da83fc3d
9 changed files with 114 additions and 100 deletions

View File

@@ -2,13 +2,13 @@ package limiter
import "log"
func ClearPacketOnlineIP() error {
log.Println("Limiter: Clear packet online ip...")
func ClearOnlineIP() error {
log.Println("Limiter: Clear online ip...")
limitLock.RLock()
for _, l := range limiter {
l.ConnLimiter.ClearPacketOnlineIP()
l.ConnLimiter.ClearOnlineIP()
}
limitLock.RUnlock()
log.Println("Limiter: Clear packet online ip done")
log.Println("Limiter: Clear online ip done")
return nil
}

View File

@@ -5,15 +5,16 @@ import (
)
type ConnLimiter struct {
realTime bool
realtime bool
ipLimit int
connLimit int
count sync.Map // map[string]int
ip sync.Map // map[string]map[string]int
}
func NewConnLimiter(conn int, ip int) *ConnLimiter {
func NewConnLimiter(conn int, ip int, realtime bool) *ConnLimiter {
return &ConnLimiter{
realtime: realtime,
connLimit: conn,
ipLimit: ip,
count: sync.Map{},
@@ -38,10 +39,14 @@ func (c *ConnLimiter) AddConnCount(user string, ip string, isTcp bool) (limit bo
}
// default user map
ipMap := new(sync.Map)
if isTcp {
ipMap.Store(ip, 2)
if c.realtime {
if isTcp {
ipMap.Store(ip, 2)
} else {
ipMap.Store(ip, 1)
}
} else {
ipMap.Store(ip, 1)
ipMap.Store(ip, struct{}{})
}
// check user online ip
if v, ok := c.ip.LoadOrStore(user, ipMap); ok {
@@ -50,9 +55,11 @@ func (c *ConnLimiter) AddConnCount(user string, ip string, isTcp bool) (limit bo
cn := 0
if online, ok := ips.Load(ip); ok {
// online ip
if isTcp {
// count add
ips.Store(ip, online.(int)+2)
if c.realtime {
if online.(int)%2 == 0 && isTcp {
// count add
ips.Store(ip, online.(int)+2)
}
}
} else {
// not online ip
@@ -67,10 +74,14 @@ func (c *ConnLimiter) AddConnCount(user string, ip string, isTcp bool) (limit bo
if limit {
return
}
if isTcp {
ips.Store(ip, 2)
if c.realtime {
if isTcp {
ips.Store(ip, 2)
} else {
ips.Store(ip, 1)
}
} else {
ips.Store(ip, 1)
ips.Store(ip, struct{}{})
}
}
}
@@ -79,6 +90,9 @@ func (c *ConnLimiter) AddConnCount(user string, ip string, isTcp bool) (limit bo
// DelConnCount Delete tcp connection count, no tcp do not use
func (c *ConnLimiter) DelConnCount(user string, ip string) {
if !c.realtime {
return
}
if c.connLimit != 0 {
if v, ok := c.count.Load(user); ok {
if v.(int) == 1 {
@@ -111,12 +125,18 @@ func (c *ConnLimiter) DelConnCount(user string, ip string) {
}
}
// ClearPacketOnlineIP Clear udp,icmp and other packet protocol online ip
func (c *ConnLimiter) ClearPacketOnlineIP() {
// ClearOnlineIP Clear udp,icmp and other packet protocol online ip
func (c *ConnLimiter) ClearOnlineIP() {
c.ip.Range(func(_, v any) bool {
userIp := v.(*sync.Map)
userIp.Range(func(ip, v any) bool {
if c.realtime {
// clear not realtime ip
userIp.Delete(ip)
return true
}
if v.(int) == 1 {
// clear packet ip for realtime
userIp.Delete(ip)
}
return true

View File

@@ -26,7 +26,7 @@ func TestConnLimiter_DelConnCount(t *testing.T) {
func TestConnLimiter_ClearPacketOnlineIP(t *testing.T) {
t.Log(c.AddConnCount("1", "1", false))
t.Log(c.AddConnCount("1", "2", false))
c.ClearPacketOnlineIP()
c.ClearOnlineIP()
t.Log(c.AddConnCount("1", "2", true))
c.DelConnCount("1", "2")
t.Log(c.AddConnCount("1", "1", false))

View File

@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"github.com/Yuzuki616/V2bX/api/panel"
"github.com/Yuzuki616/V2bX/conf"
"github.com/juju/ratelimit"
"github.com/xtls/xray-core/common/task"
"log"
@@ -18,10 +19,10 @@ func Init() {
limiter = map[string]*Limiter{}
c := task.Periodic{
Interval: time.Minute * 2,
Execute: ClearPacketOnlineIP,
Execute: ClearOnlineIP,
}
go func() {
log.Println("Limiter: ClearPacketOnlineIP started")
log.Println("Limiter: ClearOnlineIP started")
time.Sleep(time.Minute * 2)
c.Start()
}()
@@ -43,17 +44,11 @@ type UserLimitInfo struct {
ExpireTime int64
}
type LimitConfig struct {
SpeedLimit int
IpLimit int
ConnLimit int
}
func AddLimiter(tag string, l *LimitConfig, users []panel.UserInfo) *Limiter {
func AddLimiter(tag string, l *conf.LimitConfig, users []panel.UserInfo) *Limiter {
info := &Limiter{
SpeedLimit: l.SpeedLimit,
UserLimitInfo: new(sync.Map),
ConnLimiter: NewConnLimiter(l.ConnLimit, l.IpLimit),
ConnLimiter: NewConnLimiter(l.ConnLimit, l.IPLimit, l.EnableRealtime),
SpeedLimiter: new(sync.Map),
}
for i := range users {