Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormhsanaei <ho3ein.sanaei@gmail.com>2024-10-28 22:13:42 +0300
committermhsanaei <ho3ein.sanaei@gmail.com>2024-10-28 22:13:42 +0300
commit569d99512cda4cb537c6603cf0a96ed9913c226f (patch)
treebf2da99750c400d76d36f71794ef83c4cad180e6
parentac84553a684e7ee721bbf88814c05c2e1720daf1 (diff)
iplimit - accept all email format
-rw-r--r--web/job/check_client_ip_job.go101
1 files changed, 46 insertions, 55 deletions
diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go
index c38550b7..08899010 100644
--- a/web/job/check_client_ip_job.go
+++ b/web/job/check_client_ip_job.go
@@ -9,7 +9,6 @@ import (
"os/exec"
"regexp"
"sort"
- "strings"
"time"
"x-ui/database"
@@ -37,11 +36,17 @@ func (j *CheckClientIpJob) Run() {
shouldClearAccessLog := false
iplimitActive := j.hasLimitIp()
- f2bInstalled := j.checkFail2BanInstalled(iplimitActive)
+ f2bInstalled := j.checkFail2BanInstalled()
isAccessLogAvailable := j.checkAccessLogAvailable(iplimitActive)
- if iplimitActive && f2bInstalled && isAccessLogAvailable {
- shouldClearAccessLog = j.processLogFile()
+ if iplimitActive {
+ if f2bInstalled && isAccessLogAvailable {
+ shouldClearAccessLog = j.processLogFile()
+ } else {
+ if !f2bInstalled {
+ logger.Warning("[LimitIP] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
+ }
+ }
}
if shouldClearAccessLog || (isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600) {
@@ -53,23 +58,18 @@ func (j *CheckClientIpJob) clearAccessLog() {
logAccessP, err := os.OpenFile(xray.GetAccessPersistentLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
j.checkError(err)
- // get access log path to open it
accessLogPath, err := xray.GetAccessLogPath()
j.checkError(err)
- // reopen the access log file for reading
file, err := os.Open(accessLogPath)
j.checkError(err)
- // copy access log content to persistent file
_, err = io.Copy(logAccessP, file)
j.checkError(err)
- // close the file after copying content
logAccessP.Close()
file.Close()
- // clean access log
err = os.Truncate(accessLogPath, 0)
j.checkError(err)
j.lastClear = time.Now().Unix()
@@ -105,74 +105,69 @@ func (j *CheckClientIpJob) hasLimitIp() bool {
}
func (j *CheckClientIpJob) processLogFile() bool {
- accessLogPath, err := xray.GetAccessLogPath()
- j.checkError(err)
- file, err := os.Open(accessLogPath)
- j.checkError(err)
+ ipRegex := regexp.MustCompile(`from \[?([0-9a-fA-F:.]+)\]?:\d+ accepted`)
+ emailRegex := regexp.MustCompile(`email: (.+)$`)
+
+ accessLogPath, _ := xray.GetAccessLogPath()
+ file, _ := os.Open(accessLogPath)
+ defer file.Close()
- InboundClientIps := make(map[string][]string)
+ inboundClientIps := make(map[string]map[string]struct{}, 100)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
- ipRegx, _ := regexp.Compile(`from \[?([0-9a-fA-F:.]+)\]?:\d+ accepted`)
- emailRegx, _ := regexp.Compile(`email: (\S+)$`)
+ ipMatches := ipRegex.FindStringSubmatch(line)
+ if len(ipMatches) < 2 {
+ continue
+ }
- matches := ipRegx.FindStringSubmatch(line)
- if len(matches) > 1 {
- ip := matches[1]
- if ip == "127.0.0.1" || ip == "::1" {
- continue
- }
+ ip := ipMatches[1]
- matchesEmail := emailRegx.FindString(line)
- if matchesEmail == "" {
- continue
- }
- matchesEmail = strings.Split(matchesEmail, "email: ")[1]
+ if ip == "127.0.0.1" || ip == "::1" {
+ continue
+ }
- if InboundClientIps[matchesEmail] != nil {
- if j.contains(InboundClientIps[matchesEmail], ip) {
- continue
- }
- InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
- } else {
- InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
- }
+ emailMatches := emailRegex.FindStringSubmatch(line)
+ if len(emailMatches) < 2 {
+ continue
}
- }
+ email := emailMatches[1]
- j.checkError(scanner.Err())
- file.Close()
+ if _, exists := inboundClientIps[email]; !exists {
+ inboundClientIps[email] = make(map[string]struct{})
+ }
+ inboundClientIps[email][ip] = struct{}{}
+ }
shouldCleanLog := false
+ for email, uniqueIps := range inboundClientIps {
- for clientEmail, ips := range InboundClientIps {
- inboundClientIps, err := j.getInboundClientIps(clientEmail)
+ ips := make([]string, 0, len(uniqueIps))
+ for ip := range uniqueIps {
+ ips = append(ips, ip)
+ }
sort.Strings(ips)
+
+ inboundClientIps, err := j.getInboundClientIps(email)
if err != nil {
- j.addInboundClientIps(clientEmail, ips)
- } else {
- shouldCleanLog = j.updateInboundClientIps(inboundClientIps, clientEmail, ips)
+ j.addInboundClientIps(email, ips)
+ continue
}
+
+ shouldCleanLog = j.updateInboundClientIps(inboundClientIps, email, ips) || shouldCleanLog
}
return shouldCleanLog
}
-func (j *CheckClientIpJob) checkFail2BanInstalled(iplimitActive bool) bool {
+func (j *CheckClientIpJob) checkFail2BanInstalled() bool {
cmd := "fail2ban-client"
args := []string{"-h"}
err := exec.Command(cmd, args...).Run()
-
- if iplimitActive && err != nil {
- logger.Warning("[LimitIP] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
- return false
- }
-
- return true
+ return err == nil
}
func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool {
@@ -253,7 +248,6 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
inboundClientIps.ClientEmail = clientEmail
inboundClientIps.Ips = string(jsonIps)
- // Fetch inbound settings by client email
inbound, err := j.getInboundByEmail(clientEmail)
if err != nil {
logger.Errorf("failed to fetch inbound settings for email %s: %s", clientEmail, err)
@@ -265,14 +259,12 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
return false
}
- // Unmarshal settings to get client limits
settings := map[string][]model.Client{}
json.Unmarshal([]byte(inbound.Settings), &settings)
clients := settings["clients"]
shouldCleanLog := false
j.disAllowedIps = []string{}
- // Open log file for IP limits
logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
logger.Errorf("failed to open IP limit log file: %s", err)
@@ -282,7 +274,6 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
log.SetOutput(logIpFile)
log.SetFlags(log.LstdFlags)
- // Check client IP limits
for _, client := range clients {
if client.Email == clientEmail {
limitIp := client.LimitIP