mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-02-02 06:48:14 -05:00
only record tcp connecting ip on real time
This commit is contained in:
parent
49cdbbbaa4
commit
bc14e406c9
@ -237,7 +237,9 @@ func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sn
|
|||||||
return nil, nil, nil, newError("Get limit info error: ", err)
|
return nil, nil, nil, newError("Get limit info error: ", err)
|
||||||
}
|
}
|
||||||
// Speed Limit and Device Limit
|
// Speed Limit and Device Limit
|
||||||
w, reject := limit.CheckLimit(user.Email, sessionInbound.Source.Address.IP().String())
|
w, reject := limit.CheckLimit(user.Email,
|
||||||
|
sessionInbound.Source.Address.IP().String(),
|
||||||
|
network == net.Network_TCP)
|
||||||
if reject {
|
if reject {
|
||||||
newError("Limited ", user.Email, " by conn or ip").AtWarning().WriteToLog()
|
newError("Limited ", user.Email, " by conn or ip").AtWarning().WriteToLog()
|
||||||
common.Close(outboundLink.Writer)
|
common.Close(outboundLink.Writer)
|
||||||
@ -473,7 +475,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
common.Interrupt(link.Reader)
|
common.Interrupt(link.Reader)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else if destination.Network == net.Network_TCP {
|
||||||
defer func() {
|
defer func() {
|
||||||
l.ConnLimiter.DelConnCount(sessionInbound.User.Email, sessionInbound.Source.Address.IP().String())
|
l.ConnLimiter.DelConnCount(sessionInbound.User.Email, sessionInbound.Source.Address.IP().String())
|
||||||
}()
|
}()
|
||||||
|
14
limiter/clear.go
Normal file
14
limiter/clear.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package limiter
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
func ClearPacketOnlineIP() error {
|
||||||
|
log.Println("Limiter: Clear packet online ip...")
|
||||||
|
limitLock.RLock()
|
||||||
|
for _, l := range limiter {
|
||||||
|
l.ConnLimiter.ClearPacketOnlineIP()
|
||||||
|
}
|
||||||
|
limitLock.RUnlock()
|
||||||
|
log.Println("Limiter: Clear packet online ip done")
|
||||||
|
return nil
|
||||||
|
}
|
@ -5,10 +5,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ConnLimiter struct {
|
type ConnLimiter struct {
|
||||||
|
realTime bool
|
||||||
ipLimit int
|
ipLimit int
|
||||||
connLimit int
|
connLimit int
|
||||||
count sync.Map //map[string]int
|
count sync.Map // map[string]int
|
||||||
ip sync.Map //map[string]map[string]*sync.Map
|
ip sync.Map // map[string]map[string]int or map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnLimiter(conn int, ip int) *ConnLimiter {
|
func NewConnLimiter(conn int, ip int) *ConnLimiter {
|
||||||
@ -20,29 +21,45 @@ func NewConnLimiter(conn int, ip int) *ConnLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConnLimiter) AddConnCount(user string, ip string) (limit bool) {
|
func (c *ConnLimiter) AddConnCount(user string, ip string, isTcp bool) (limit bool) {
|
||||||
if c.connLimit != 0 {
|
if c.connLimit != 0 {
|
||||||
if v, ok := c.count.Load(user); ok {
|
if v, ok := c.count.Load(user); ok {
|
||||||
if v.(int) >= c.connLimit {
|
if v.(int) >= c.connLimit {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else if isTcp { // tcp protocol
|
||||||
c.count.Store(user, v.(int)+1)
|
c.count.Store(user, v.(int)+1)
|
||||||
}
|
}
|
||||||
} else {
|
} else if isTcp { // tcp protocol
|
||||||
c.count.Store(user, 1)
|
c.count.Store(user, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.ipLimit == 0 {
|
if c.ipLimit == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// default user map
|
||||||
ipMap := new(sync.Map)
|
ipMap := new(sync.Map)
|
||||||
ipMap.Store(ip, 1)
|
if isTcp {
|
||||||
|
ipMap.Store(ip, 2)
|
||||||
|
} else {
|
||||||
|
ipMap.Store(ip, 1)
|
||||||
|
}
|
||||||
|
// check user online ip
|
||||||
if v, ok := c.ip.LoadOrStore(user, ipMap); ok {
|
if v, ok := c.ip.LoadOrStore(user, ipMap); ok {
|
||||||
// have online ip
|
// have user
|
||||||
ips := v.(*sync.Map)
|
ips := v.(*sync.Map)
|
||||||
cn := 0
|
cn := 0
|
||||||
if online, ok := ips.Load(ip); !ok {
|
if online, ok := ips.Load(ip); ok {
|
||||||
ips.Range(func(key, value interface{}) bool {
|
// online ip
|
||||||
|
if isTcp {
|
||||||
|
// count add
|
||||||
|
ips.Store(ip, online.(int)+2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not online ip for tcp
|
||||||
|
if _, ok = ips.Load(ip + "o"); ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ips.Range(func(_, _ interface{}) bool {
|
||||||
cn++
|
cn++
|
||||||
if cn >= c.ipLimit {
|
if cn >= c.ipLimit {
|
||||||
limit = true
|
limit = true
|
||||||
@ -53,15 +70,17 @@ func (c *ConnLimiter) AddConnCount(user string, ip string) (limit bool) {
|
|||||||
if limit {
|
if limit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ips.Store(ip, 1)
|
if isTcp {
|
||||||
} else {
|
ips.Store(ip, 2)
|
||||||
// have this ip
|
} else {
|
||||||
ips.Store(ip, online.(int)+1)
|
ips.Store(ip, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelConnCount Delete tcp connection count, no tcp do not use
|
||||||
func (c *ConnLimiter) DelConnCount(user string, ip string) {
|
func (c *ConnLimiter) DelConnCount(user string, ip string) {
|
||||||
if c.connLimit != 0 {
|
if c.connLimit != 0 {
|
||||||
if v, ok := c.count.Load(user); ok {
|
if v, ok := c.count.Load(user); ok {
|
||||||
@ -78,10 +97,10 @@ func (c *ConnLimiter) DelConnCount(user string, ip string) {
|
|||||||
if i, ok := c.ip.Load(user); ok {
|
if i, ok := c.ip.Load(user); ok {
|
||||||
is := i.(*sync.Map)
|
is := i.(*sync.Map)
|
||||||
if i, ok := is.Load(ip); ok {
|
if i, ok := is.Load(ip); ok {
|
||||||
if i.(int) == 1 {
|
if i.(int) == 2 {
|
||||||
is.Delete(ip)
|
is.Delete(ip)
|
||||||
} else {
|
} else {
|
||||||
is.Store(user, i.(int)-1)
|
is.Store(user, i.(int)-2)
|
||||||
}
|
}
|
||||||
notDel := false
|
notDel := false
|
||||||
c.ip.Range(func(_, _ any) bool {
|
c.ip.Range(func(_, _ any) bool {
|
||||||
@ -94,3 +113,17 @@ func (c *ConnLimiter) DelConnCount(user string, ip string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearPacketOnlineIP Clear udp,icmp and other packet protocol online ip
|
||||||
|
func (c *ConnLimiter) ClearPacketOnlineIP() {
|
||||||
|
c.ip.Range(func(_, v any) bool {
|
||||||
|
userIp := v.(*sync.Map)
|
||||||
|
userIp.Range(func(ip, v any) bool {
|
||||||
|
if v.(int) == 1 {
|
||||||
|
userIp.Delete(ip)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -12,15 +12,24 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConnLimiter_AddConnCount(t *testing.T) {
|
func TestConnLimiter_AddConnCount(t *testing.T) {
|
||||||
t.Log(c.AddConnCount("1", "1"))
|
t.Log(c.AddConnCount("1", "1", true))
|
||||||
t.Log(c.AddConnCount("1", "2"))
|
t.Log(c.AddConnCount("1", "2", true))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConnLimiter_DelConnCount(t *testing.T) {
|
func TestConnLimiter_DelConnCount(t *testing.T) {
|
||||||
t.Log(c.AddConnCount("1", "1"))
|
t.Log(c.AddConnCount("1", "1", true))
|
||||||
t.Log(c.AddConnCount("1", "2"))
|
t.Log(c.AddConnCount("1", "2", true))
|
||||||
c.DelConnCount("1", "1")
|
c.DelConnCount("1", "1")
|
||||||
t.Log(c.AddConnCount("1", "2"))
|
t.Log(c.AddConnCount("1", "2", true))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConnLimiter_ClearPacketOnlineIP(t *testing.T) {
|
||||||
|
t.Log(c.AddConnCount("1", "1", false))
|
||||||
|
t.Log(c.AddConnCount("1", "2", false))
|
||||||
|
c.ClearPacketOnlineIP()
|
||||||
|
t.Log(c.AddConnCount("1", "2", true))
|
||||||
|
c.DelConnCount("1", "2")
|
||||||
|
t.Log(c.AddConnCount("1", "1", false))
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConnLimiter(b *testing.B) {
|
func BenchmarkConnLimiter(b *testing.B) {
|
||||||
@ -28,7 +37,7 @@ func BenchmarkConnLimiter(b *testing.B) {
|
|||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
c.AddConnCount("1", "2")
|
c.AddConnCount("1", "2", true)
|
||||||
c.DelConnCount("1", "2")
|
c.DelConnCount("1", "2")
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Yuzuki616/V2bX/api/panel"
|
"github.com/Yuzuki616/V2bX/api/panel"
|
||||||
"github.com/juju/ratelimit"
|
"github.com/juju/ratelimit"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -14,6 +16,15 @@ var limiter map[string]*Limiter
|
|||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
limiter = map[string]*Limiter{}
|
limiter = map[string]*Limiter{}
|
||||||
|
c := task.Periodic{
|
||||||
|
Interval: time.Minute * 2,
|
||||||
|
Execute: ClearPacketOnlineIP,
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
log.Println("Limiter: ClearPacketOnlineIP started")
|
||||||
|
time.Sleep(time.Minute * 2)
|
||||||
|
c.Start()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Limiter struct {
|
type Limiter struct {
|
||||||
@ -104,9 +115,9 @@ func DeleteLimiter(tag string) {
|
|||||||
limitLock.Unlock()
|
limitLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Limiter) CheckLimit(email string, ip string) (Bucket *ratelimit.Bucket, Reject bool) {
|
func (l *Limiter) CheckLimit(email string, ip string, isTcp bool) (Bucket *ratelimit.Bucket, Reject bool) {
|
||||||
// ip and conn limiter
|
// ip and conn limiter
|
||||||
if l.ConnLimiter.AddConnCount(email, ip) {
|
if l.ConnLimiter.AddConnCount(email, ip, isTcp) {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
// check and gen speed limit Bucket
|
// check and gen speed limit Bucket
|
||||||
|
@ -1 +0,0 @@
|
|||||||
package limiter
|
|
Loading…
Reference in New Issue
Block a user