mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-07-01 20:42:07 +00:00
Removed ipLimit from the panel, changed the code to work with fail2ban (#580)
* Logging for fail2ban service Removed limitDevice and other unnecessary functions * Logging for fail2ban service Removed limitDevice and other unnecessary functions * fixed shouldCleanLog * last fix * reduced ip limit detection frequency to 30 sec (less logging, more precise) changed maxretry in fail2ban jail config to 2 to fit above * fixed check delay * added 5 seconds delay before cleaning logs
This commit is contained in:
parent
d40e61fc45
commit
4e89c71095
2 changed files with 28 additions and 126 deletions
|
@ -10,12 +10,9 @@ import (
|
|||
"x-ui/web/service"
|
||||
"x-ui/xray"
|
||||
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-cmd/cmd"
|
||||
)
|
||||
|
||||
type CheckClientIpJob struct {
|
||||
|
@ -88,6 +85,7 @@ func processLogFile() {
|
|||
|
||||
}
|
||||
disAllowedIps = []string{}
|
||||
shouldCleanLog := false
|
||||
|
||||
for clientEmail, ips := range InboundClientIps {
|
||||
inboundClientIps, err := GetInboundClientIps(clientEmail)
|
||||
|
@ -96,23 +94,19 @@ func processLogFile() {
|
|||
addInboundClientIps(clientEmail, ips)
|
||||
|
||||
} else {
|
||||
shouldCleanLog := updateInboundClientIps(inboundClientIps, clientEmail, ips)
|
||||
if shouldCleanLog {
|
||||
// clean log
|
||||
if err := os.Truncate(GetAccessLogPath(), 0); err != nil {
|
||||
checkError(err)
|
||||
}
|
||||
}
|
||||
shouldCleanLog = updateInboundClientIps(inboundClientIps, clientEmail, ips)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check if inbound connection is more than limited ip and drop connection
|
||||
LimitDevice := func() { LimitDevice() }
|
||||
|
||||
stop := schedule(LimitDevice, 1000*time.Millisecond)
|
||||
time.Sleep(10 * time.Second)
|
||||
stop <- true
|
||||
time.Sleep(time.Second * 5)
|
||||
//added 5 seconds delay before cleaning logs to reduce chance of logging IP that already has been banned
|
||||
if shouldCleanLog {
|
||||
// clean log
|
||||
if err := os.Truncate(GetAccessLogPath(), 0); err != nil {
|
||||
checkError(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func GetAccessLogPath() string {
|
||||
|
@ -203,16 +197,24 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmai
|
|||
settings := map[string][]model.Client{}
|
||||
json.Unmarshal([]byte(inbound.Settings), &settings)
|
||||
clients := settings["clients"]
|
||||
shouldCleanLog := false
|
||||
|
||||
for _, client := range clients {
|
||||
if client.Email == clientEmail {
|
||||
|
||||
limitIp := client.LimitIP
|
||||
|
||||
if limitIp < len(ips) && limitIp != 0 && inbound.Enable {
|
||||
if limitIp != 0 {
|
||||
|
||||
disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
|
||||
return true
|
||||
shouldCleanLog = true
|
||||
|
||||
if limitIp < len(ips) && inbound.Enable {
|
||||
|
||||
disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
|
||||
for i:=limitIp; i < len(ips); i++ {
|
||||
logger.Info("[LIMIT_IP] Email=", clientEmail, " SRC=", ips[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,9 +224,9 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmai
|
|||
db := database.GetDB()
|
||||
err = db.Save(inboundClientIps).Error
|
||||
if err != nil {
|
||||
return false
|
||||
return shouldCleanLog
|
||||
}
|
||||
return false
|
||||
return shouldCleanLog
|
||||
}
|
||||
|
||||
func DisableInbound(id int) error {
|
||||
|
@ -251,103 +253,3 @@ func GetInboundByEmail(clientEmail string) (*model.Inbound, error) {
|
|||
}
|
||||
return inbounds, nil
|
||||
}
|
||||
|
||||
func LimitDevice() {
|
||||
|
||||
localIp, err := LocalIP()
|
||||
checkError(err)
|
||||
|
||||
c := cmd.NewCmd("bash", "-c", "ss --tcp | grep -E '"+IPsToRegex(localIp)+"'| awk '{if($1==\"ESTAB\") print $4,$5;}'", "| sort | uniq -c | sort -nr | head")
|
||||
|
||||
<-c.Start()
|
||||
if len(c.Status().Stdout) > 0 {
|
||||
ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
|
||||
portRegx, _ := regexp.Compile(`(?:(:))([0-9]..[^.][0-9]+)`)
|
||||
|
||||
for _, row := range c.Status().Stdout {
|
||||
|
||||
data := strings.Split(row, " ")
|
||||
|
||||
destIp, destPort, srcIp, srcPort := "", "", "", ""
|
||||
|
||||
destIp = string(ipRegx.FindString(data[0]))
|
||||
|
||||
destPort = portRegx.FindString(data[0])
|
||||
destPort = strings.Replace(destPort, ":", "", -1)
|
||||
|
||||
srcIp = string(ipRegx.FindString(data[1]))
|
||||
|
||||
srcPort = portRegx.FindString(data[1])
|
||||
srcPort = strings.Replace(srcPort, ":", "", -1)
|
||||
|
||||
if contains(disAllowedIps, srcIp) {
|
||||
dropCmd := cmd.NewCmd("bash", "-c", "ss -K dport = "+srcPort)
|
||||
dropCmd.Start()
|
||||
|
||||
logger.Debug("request droped : ", srcIp, srcPort, "to", destIp, destPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func LocalIP() ([]string, error) {
|
||||
// get machine ips
|
||||
|
||||
ifaces, err := net.Interfaces()
|
||||
ips := []string{}
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
for _, i := range ifaces {
|
||||
addrs, err := i.Addrs()
|
||||
if err != nil {
|
||||
return ips, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
var ip net.IP
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP
|
||||
case *net.IPAddr:
|
||||
ip = v.IP
|
||||
}
|
||||
|
||||
ips = append(ips, ip.String())
|
||||
|
||||
}
|
||||
}
|
||||
logger.Debug("System IPs : ", ips)
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func IPsToRegex(ips []string) string {
|
||||
|
||||
regx := ""
|
||||
for _, ip := range ips {
|
||||
regx += "(" + strings.Replace(ip, ".", "\\.", -1) + ")"
|
||||
|
||||
}
|
||||
regx = "(" + strings.Replace(regx, ")(", ")|(.", -1) + ")"
|
||||
|
||||
return regx
|
||||
}
|
||||
|
||||
func schedule(LimitDevice func(), delay time.Duration) chan bool {
|
||||
stop := make(chan bool)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
LimitDevice()
|
||||
select {
|
||||
case <-time.After(delay):
|
||||
case <-stop:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return stop
|
||||
}
|
||||
|
|
|
@ -250,8 +250,8 @@ func (s *Server) startTask() {
|
|||
// Check the inbound traffic every 30 seconds that the traffic exceeds and expires
|
||||
s.cron.AddJob("@every 30s", job.NewCheckInboundJob())
|
||||
|
||||
// check client ips from log file every 10 sec
|
||||
s.cron.AddJob("@every 10s", job.NewCheckClientIpJob())
|
||||
// check client ips from log file every 30 sec
|
||||
s.cron.AddJob("@every 30s", job.NewCheckClientIpJob())
|
||||
|
||||
// Make a traffic condition every day, 8:30
|
||||
var entry cron.EntryID
|
||||
|
|
Loading…
Reference in a new issue