diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go
index c1b4ab34..758929e9 100644
--- a/web/job/check_client_ip_job.go
+++ b/web/job/check_client_ip_job.go
@@ -2,6 +2,7 @@ package job
import (
"encoding/json"
+ "log"
"os"
"regexp"
"x-ui/database"
@@ -31,6 +32,18 @@ func (j *CheckClientIpJob) Run() {
logger.Debug("Check Client IP Job...")
if hasLimitIp() {
+ //create log file for Fail2ban IP Limit
+ logIpFile, err := os.OpenFile("/var/log/3xipl.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
+ checkError(err)
+ defer logIpFile.Close()
+ log.SetOutput(logIpFile)
+ log.SetFlags(log.LstdFlags)
+
+ //create file to collect access.log to another file accessp.log (p=persistent)
+ logAccessP, err := os.OpenFile("/usr/local/x-ui/accessp.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
+ checkError(err)
+ defer logAccessP.Close()
+
processLogFile()
}
@@ -129,9 +142,18 @@ func processLogFile() {
}
- time.Sleep(time.Second * 5)
- //added 5 seconds delay before cleaning logs to reduce chance of logging IP that already has been banned
+ time.Sleep(time.Second * 3)
+ //added 3 seconds delay before cleaning logs to reduce chance of logging IP that already has been banned
if shouldCleanLog {
+ //copy log
+ logAccessP, err := os.OpenFile("/usr/local/x-ui/accessp.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
+ checkError(err)
+ input, err := os.ReadFile(accessLogPath)
+ checkError(err)
+ if _, err := logAccessP.Write(input); err != nil {
+ checkError(err)
+ }
+ defer logAccessP.Close()
// clean log
if err := os.Truncate(GetAccessLogPath(), 0); err != nil {
checkError(err)
@@ -239,10 +261,9 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmai
shouldCleanLog = true
if limitIp < len(ips) && inbound.Enable {
-
disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
for i := limitIp; i < len(ips); i++ {
- logger.Notice("[LIMIT_IP] Email=", clientEmail, " SRC=", ips[i])
+ log.Printf("[LIMIT_IP] Email = %s || SRC = %s", clientEmail, ips[i])
}
}
}
diff --git a/web/web.go b/web/web.go
index a70ae3c8..3372344a 100644
--- a/web/web.go
+++ b/web/web.go
@@ -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 30 sec
- s.cron.AddJob("@every 30s", job.NewCheckClientIpJob())
+ // check client ips from log file every 20 sec
+ s.cron.AddJob("@every 20s", job.NewCheckClientIpJob())
// Make a traffic condition every day, 8:30
var entry cron.EntryID
diff --git a/x-ui.sh b/x-ui.sh
index 5b8950cc..57e1c714 100644
--- a/x-ui.sh
+++ b/x-ui.sh
@@ -518,9 +518,9 @@ install_acme() {
}
ssl_cert_issue_main() {
- echo "1) Get SSL"
- echo "2) Revoke"
- echo "3) Force Renew"
+ echo -e "${green}\t1.${plain} Get SSL"
+ echo -e "${green}\t2.${plain} Revoke"
+ echo -e "${green}\t3.${plain} Force Renew"
read -p "Choose an option: " choice
case "$choice" in
1) ssl_cert_issue ;;
@@ -671,6 +671,186 @@ run_speedtest() {
speedtest
}
+iplimit_main() {
+ echo -e "\n${green}\t1.${plain} Install Fail2ban and configure IP Limit"
+ echo -e "${green}\t2.${plain} Change Ban Duration"
+ echo -e "${green}\t3.${plain} Unban Everyone"
+ echo -e "${green}\t4.${plain} Check Logs"
+ echo -e "${green}\t5.${plain} Uninstall IP Limit"
+ echo -e "${green}\t0.${plain} Back to Main Menu"
+ read -p "Choose an option: " choice
+ case "$choice" in
+ 0)
+ show_menu ;;
+ 1)
+ confirm "Proceed with installation of Fail2ban & IP Limit?" "y"
+ if [[ $? == 0 ]]; then
+ install_iplimit
+ else
+ iplimit_main
+ fi ;;
+ 2)
+ read -rp "Please enter new Ban Duration in Minutes [default 5]: " NUM
+ if [[ $NUM =~ ^[0-9]+$ ]]; then
+ echo -e "\n[3x-ipl]\nenabled=true\nfilter=3x-ipl\naction=3x-ipl\nlogpath=/var/log/3xipl.log\nmaxretry=3\nfindtime=100\nbantime=${NUM}m" > /etc/fail2ban/jail.d/3x-ipl.conf
+ sudo systemctl restart fail2ban
+ echo -e "${green}Bantime set to ${NUM} minutes successfully.${plain}"
+ else
+ echo -e "${red}${NUM} is not a number! Please, try again.${plain}"
+ fi
+ iplimit_main ;;
+ 3)
+ confirm "Proceed with Unbanning everyone from IP Limit jail?" "y"
+ if [[ $? == 0 ]]; then
+ fail2ban-client reload --restart --unban 3x-ipl
+ echo -e "${green}All users Unbanned successfully.${plain}"
+ iplimit_main
+ else
+ echo -e "${yellow}Cancelled.${plain}"
+ fi
+ iplimit_main ;;
+ 4)
+ if test -f "/var/log/3xipl-banned.log"; then
+ if [[ -s "/var/log/3xipl-banned.log" ]]; then
+ cat /var/log/3xipl-banned.log
+ else
+ echo -e "${red}Log file is empty.${plain}\n"
+ fi
+ else
+ echo -e "${red}Log file not found. Please Install Fail2ban and IP Limit first.${plain}\n"
+ iplimit_main
+ fi ;;
+ 5)
+ remove_iplimit ;;
+ *) echo "Invalid choice" ;;
+ esac
+}
+
+install_iplimit() {
+ if ! command -v fail2ban-client &>/dev/null; then
+ echo -e "${green}Fail2ban is not installed. Installing now...!${plain}\n"
+ # Check the OS and install necessary packages
+ case "${release}" in
+ ubuntu|debian)
+ sudo apt-get update && sudo apt-get install fail2ban -y ;;
+ centos)
+ sudo yum -y update && sudo yum -y install fail2ban ;;
+ fedora)
+ sudo dnf -y update && sudo dnf -y install fail2ban ;;
+ *)
+ echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n"
+ exit 1 ;;
+ esac
+ echo -e "${green}Fail2ban installed successfully!${plain}\n"
+ else
+ echo -e "${yellow}Fail2ban is already installed.${plain}\n"
+ fi
+
+ echo -e "${green}Configuring IP Limit...${plain}\n"
+
+ #Check if [3x-ipl] exists in jail.local (just making sure there's no double config for jail)
+ if grep -qw '3x-ipl' /etc/fail2ban/jail.local || grep -qw '3x-ipl' /etc/fail2ban/jail.conf; then
+ echo -e "${red}Found conflicts in /etc/fail2ban/jail.conf or jail.local file!\nPlease manually remove anything related 3x-ipl in that files and try again.\nInstallation of IP Limit failed.${plain}\n"
+ exit 1
+ fi
+
+ #Check if log file exists
+ if ! test -f "/var/log/3xipl-banned.log"; then
+ touch /var/log/3xipl-banned.log
+ fi
+
+ #Check if service log file exists so fail2ban won't return error
+ if ! test -f "/var/log/3xipl.log"; then
+ touch /var/log/3xipl.log
+ fi
+
+
+ echo -e "\n[3x-ipl]\nenabled=true\nfilter=3x-ipl\naction=3x-ipl\nlogpath=/var/log/3xipl.log\nmaxretry=3\nfindtime=100\nbantime=5m" > /etc/fail2ban/jail.d/3x-ipl.conf
+
+ sudo cat > /etc/fail2ban/filter.d/3x-ipl.conf << EOF
+[Definition]
+datepattern = ^%%Y/%%m/%%d %%H:%%M:%%S
+failregex = \[LIMIT_IP\]\s*Email\s*=\s*.+\s*\|\|\s*SRC\s*=\s*
+ignoreregex =
+EOF
+
+ sudo cat > /etc/fail2ban/action.d/3x-ipl.conf << 'EOF'
+[INCLUDES]
+before = iptables-common.conf
+
+[Definition]
+actionstart = -N f2b-
+ -A f2b- -j
+ -I -p -j f2b-
+
+actionstop = -D -p -j f2b-
+
+ -X f2b-
+
+actioncheck = -n -L | grep -q 'f2b-[ \t]'
+
+actionban = -I f2b- 1 -s -j
+ echo "$(date +"%%Y/%%m/%%d %%H:%%M:%%S") BAN [Email] = [IP] = banned for seconds." >> /var/log/3xipl-banned.log
+
+actionunban = -D f2b- -s -j
+ echo "$(date +"%%Y/%%m/%%d %%H:%%M:%%S") UNBAN [Email] = [IP] = unbanned." >> /var/log/3xipl-banned.log
+
+[Init]
+EOF
+
+ #Launching fail2ban
+ if ! sudo systemctl is-active --quiet fail2ban; then
+ sudo systemctl start fail2ban
+ else
+ systemctl restart fail2ban
+ fi
+ sudo systemctl enable fail2ban
+
+ echo -e "${green}IP Limit installed and configured successfully!${plain}\n"
+ before_show_menu
+}
+
+remove_iplimit(){
+ echo -e "${green}\t1.${plain} Only remove IP Limit configurations"
+ echo -e "${green}\t2.${plain} Uninstall Fail2ban and IP Limit"
+ echo -e "${green}\t0.${plain} Abort"
+ read -p "Choose an option: " num
+ case "$num" in
+ 1)
+ rm -f /etc/fail2ban/filter.d/3x-ipl.conf
+ rm -f /etc/fail2ban/action.d/3x-ipl.conf
+ rm -f /etc/fail2ban/jail.d/3x-ipl.conf
+ sudo systemctl restart fail2ban
+ echo -e "${green}IP Limit removed successfully!${plain}\n"
+ before_show_menu ;;
+ 2)
+ rm -f /etc/fail2ban/filter.d/3x-ipl.conf
+ rm -f /etc/fail2ban/action.d/3x-ipl.conf
+ rm -f /etc/fail2ban/jail.d/3x-ipl.conf
+ sudo systemctl stop fail2ban
+ sudo systemctl disable fail2ban
+ case "${release}" in
+ ubuntu|debian)
+ sudo apt-get remove fail2ban -y ;;
+ centos)
+ sudo yum -y remove fail2ban ;;
+ fedora)
+ sudo dnf -y remove fail2ban ;;
+ *)
+ echo -e "${red}Unsupported operating system. Please uninstall Fail2ban manually.${plain}\n"
+ exit 1 ;;
+ esac
+ rm -rf /etc/fail2ban/*
+ echo -e "${green}Fail2ban and IP Limit removed successfully!${plain}\n"
+ before_show_menu ;;
+ 0)
+ echo -e "${yellow}Cancelled.${plain}\n"
+ iplimit_main ;;
+ *)
+ echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
+ remove_iplimit ;;
+ esac
+}
show_usage() {
echo "x-ui control menu usages: "
@@ -718,9 +898,10 @@ show_menu() {
${green}18.${plain} Active Firewall and open ports
${green}19.${plain} Install WARP
${green}20.${plain} Speedtest by Ookla
+ ${green}21.${plain} IP Limit Management
"
show_status
- echo && read -p "Please enter your selection [0-20]: " num
+ echo && read -p "Please enter your selection [0-21]: " num
case "${num}" in
0)
@@ -786,8 +967,11 @@ show_menu() {
20)
run_speedtest
;;
+ 21)
+ iplimit_main
+ ;;
*)
- LOGE "Please enter the correct number [0-20]"
+ LOGE "Please enter the correct number [0-21]"
;;
esac
}