diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html
index e4c46cc0..d2d3b0d4 100644
--- a/web/html/xui/client_bulk_modal.html
+++ b/web/html/xui/client_bulk_modal.html
@@ -57,6 +57,7 @@
+
{{ i18n "pages.inbounds.IPLimit" }}
diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html
index ba9fce31..e8236778 100644
--- a/web/html/xui/client_modal.html
+++ b/web/html/xui/client_modal.html
@@ -120,26 +120,27 @@
},
},
methods: {
- async getDBClientIps(email, event) {
- const msg = await HttpUtil.post('/panel/inbound/clientIps/' + email);
- if (!msg.success) {
- return;
- }
+ async getDBClientIps(email) {
try {
- ips = JSON.parse(msg.obj)
- ips = ips.join(",")
- event.target.value = ips
+ const msg = await HttpUtil.post(`/panel/inbound/clientIps/${email}`);
+ if (!msg.success) {
+ return;
+ }
+ const ips = JSON.parse(msg.obj).join(",\n");
+ document.getElementById("clientIPs").value = ips;
} catch (error) {
- // text
- event.target.value = msg.obj
+ document.getElementById("clientIPs").value = msg.obj;
}
},
async clearDBClientIps(email) {
- const msg = await HttpUtil.post('/panel/inbound/clearClientIps/' + email);
- if (!msg.success) {
- return;
+ try {
+ const msg = await HttpUtil.post(`/panel/inbound/clearClientIps/${email}`);
+ if (!msg.success) {
+ return;
+ }
+ document.getElementById("clientIPs").value = "";
+ } catch (error) {
}
- document.getElementById("clientIPs").value = ""
},
resetClientTraffic(email, dbInboundId, iconElement) {
this.$confirm({
diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html
index 9494f0ac..45068f91 100644
--- a/web/html/xui/form/client.html
+++ b/web/html/xui/form/client.html
@@ -72,31 +72,32 @@
-
- {{ i18n "pages.inbounds.IPLimitlog" }}
-
-
- {{ i18n "pages.inbounds.IPLimitlogDesc" }}
-
-
-
-
-
- {{ i18n "pages.inbounds.IPLimitlogclear" }}
-
-
-
-
-
-
-
-
-
-
-
+
+ {{ i18n "pages.inbounds.IPLimitlog" }}
+
+
+ {{ i18n "pages.inbounds.IPLimitlogDesc" }}
+
+
+
+
+
+ {{ i18n "pages.inbounds.IPLimitlogclear" }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/html/xui/form/inbound.html b/web/html/xui/form/inbound.html
index 383105ac..e5b3bfc3 100644
--- a/web/html/xui/form/inbound.html
+++ b/web/html/xui/form/inbound.html
@@ -1,12 +1,13 @@
{{define "form/inbound"}}
-
-
-
+
+
+
+
[[ p ]]
diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go
index 9ec15171..fb1227f8 100644
--- a/web/job/check_client_ip_job.go
+++ b/web/job/check_client_ip_job.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"os"
"regexp"
- "sync"
"x-ui/database"
"x-ui/database/model"
"x-ui/logger"
@@ -21,38 +20,33 @@ import (
type CheckClientIpJob struct {
xrayService service.XrayService
- AllowedIps []string
- mutex sync.Mutex
}
var job *CheckClientIpJob
-var AllowedIps []string
-var ipRegx *regexp.Regexp = regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
-var emailRegx *regexp.Regexp = regexp.MustCompile(`email:.+`)
+var disAllowedIps []string
func NewCheckClientIpJob() *CheckClientIpJob {
- job := &CheckClientIpJob{}
+ job = new(CheckClientIpJob)
return job
}
func (j *CheckClientIpJob) Run() {
logger.Debug("Check Client IP Job...")
- j.processLogFile()
+ processLogFile()
- // AllowedIps = []string{"192.168.1.183","192.168.1.197"}
- allowedIps := []byte(strings.Join(j.getAllowedIps(), ","))
+ blockedIps := []byte(strings.Join(disAllowedIps, ","))
// check if file exists, if not create one
- _, err := os.Stat(xray.GetAllowedIPsPath())
+ _, err := os.Stat(xray.GetBlockedIPsPath())
if os.IsNotExist(err) {
- _, err = os.OpenFile(xray.GetAllowedIPsPath(), os.O_RDWR|os.O_CREATE, 0755)
+ _, err = os.OpenFile(xray.GetBlockedIPsPath(), os.O_RDWR|os.O_CREATE, 0755)
checkError(err)
}
- err = os.WriteFile(xray.GetAllowedIPsPath(), allowedIps, 0755)
+ err = os.WriteFile(xray.GetBlockedIPsPath(), blockedIps, 0755)
checkError(err)
}
-func (j *CheckClientIpJob) processLogFile() {
+func processLogFile() {
accessLogPath := GetAccessLogPath()
if accessLogPath == "" {
logger.Warning("access.log doesn't exist in your config.json")
@@ -70,6 +64,8 @@ func (j *CheckClientIpJob) processLogFile() {
lines := strings.Split(string(data), "\n")
for _, line := range lines {
+ ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
+ emailRegx, _ := regexp.Compile(`email:.+`)
matchesIp := ipRegx.FindString(line)
if len(matchesIp) > 0 {
@@ -84,13 +80,19 @@ func (j *CheckClientIpJob) processLogFile() {
}
matchesEmail = strings.TrimSpace(strings.Split(matchesEmail, "email: ")[1])
- if !contains(InboundClientIps[matchesEmail], ip) {
+ if InboundClientIps[matchesEmail] != nil {
+ if contains(InboundClientIps[matchesEmail], ip) {
+ continue
+ }
+ InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
+
+ } else {
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
}
}
}
- j.setAllowedIps([]string{})
+ disAllowedIps = []string{}
for clientEmail, ips := range InboundClientIps {
inboundClientIps, err := GetInboundClientIps(clientEmail)
@@ -99,7 +101,7 @@ func (j *CheckClientIpJob) processLogFile() {
addInboundClientIps(clientEmail, ips)
} else {
- j.updateInboundClientIps(inboundClientIps, clientEmail, ips)
+ updateInboundClientIps(inboundClientIps, clientEmail, ips)
}
}
@@ -112,7 +114,6 @@ func (j *CheckClientIpJob) processLogFile() {
stop <- true
}
-
func GetAccessLogPath() string {
config, err := os.ReadFile(xray.GetConfigPath())
@@ -133,22 +134,20 @@ func GetAccessLogPath() string {
return ""
}
-
func checkError(e error) {
if e != nil {
logger.Warning("client ip job err:", e)
}
}
-
func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}
+
return false
}
-
func GetInboundClientIps(clientEmail string) (*model.InboundClientIps, error) {
db := database.GetDB()
InboundClientIps := &model.InboundClientIps{}
@@ -158,7 +157,6 @@ func GetInboundClientIps(clientEmail string) (*model.InboundClientIps, error) {
}
return InboundClientIps, nil
}
-
func addInboundClientIps(clientEmail string, ips []string) error {
inboundClientIps := &model.InboundClientIps{}
jsonIps, err := json.Marshal(ips)
@@ -171,10 +169,10 @@ func addInboundClientIps(clientEmail string, ips []string) error {
tx := db.Begin()
defer func() {
- if r := recover(); r != nil {
- tx.Rollback()
- } else {
+ if err == nil {
tx.Commit()
+ } else {
+ tx.Rollback()
}
}()
@@ -184,7 +182,13 @@ func addInboundClientIps(clientEmail string, ips []string) error {
}
return nil
}
-func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) error {
+func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) error {
+
+ jsonIps, err := json.Marshal(ips)
+ checkError(err)
+
+ inboundClientIps.ClientEmail = clientEmail
+ inboundClientIps.Ips = string(jsonIps)
// check inbound limitation
inbound, err := GetInboundByEmail(clientEmail)
@@ -201,22 +205,17 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
for _, client := range clients {
if client.Email == clientEmail {
+
limitIp := client.LimitIP
+
if limitIp < len(ips) && limitIp != 0 && inbound.Enable {
- for _, ip := range ips[:limitIp] {
- j.addAllowedIp(ip)
- }
+
+ disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
}
}
}
-
- jsonIps, err := json.Marshal(ips) // marshal the possibly truncated list of IPs
- checkError(err)
-
- inboundClientIps.ClientEmail = clientEmail
- inboundClientIps.Ips = string(jsonIps)
-
- logger.Debug("Allowed IPs: ", ips)
+ logger.Debug("disAllowedIps ", disAllowedIps)
+ sort.Strings(disAllowedIps)
db := database.GetDB()
err = db.Save(inboundClientIps).Error
@@ -225,25 +224,6 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
}
return nil
}
-
-func (j *CheckClientIpJob) setAllowedIps(ips []string) {
- j.mutex.Lock()
- defer j.mutex.Unlock()
- j.AllowedIps = ips
-}
-
-func (j *CheckClientIpJob) addAllowedIp(ip string) {
- j.mutex.Lock()
- defer j.mutex.Unlock()
- j.AllowedIps = append(j.AllowedIps, ip)
-}
-
-func (j *CheckClientIpJob) getAllowedIps() []string {
- j.mutex.Lock()
- defer j.mutex.Unlock()
- return j.AllowedIps
-}
-
func DisableInbound(id int) error {
db := database.GetDB()
result := db.Model(model.Inbound{}).
@@ -297,7 +277,7 @@ func LimitDevice() {
srcPort = portRegx.FindString(data[1])
srcPort = strings.Replace(srcPort, ":", "", -1)
- if contains(AllowedIps, srcIp) {
+ if contains(disAllowedIps, srcIp) {
dropCmd := cmd.NewCmd("bash", "-c", "ss -K dport = "+srcPort)
dropCmd.Start()
diff --git a/xray/process.go b/xray/process.go
index 41742f3a..d0117324 100644
--- a/xray/process.go
+++ b/xray/process.go
@@ -51,8 +51,8 @@ func GetIranPath() string {
return config.GetBinFolderPath() + "/iran.dat"
}
-func GetAllowedIPsPath() string {
- return config.GetBinFolderPath() + "/AllowedIPs"
+func GetBlockedIPsPath() string {
+ return config.GetBinFolderPath() + "/BlockedIps"
}
func stopProcess(p *Process) {
@@ -173,7 +173,7 @@ func (p *process) Start() (err error) {
return common.NewErrorf("Failed to write configuration file: %v", err)
}
- cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", GetAllowedIPsPath())
+ cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", GetBlockedIPsPath())
p.cmd = cmd
stdReader, err := cmd.StdoutPipe()