diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b2dc0ca4..6afe8618 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,4 +1,4 @@ -name: Release 3X-UI dockerhub +name: Release 3X-UI for Docker on: push: tags: @@ -36,6 +36,6 @@ jobs: with: context: . push: ${{ github.event_name != 'pull_request' }} - platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6 + platforms: linux/amd64, linux/arm64/v8, linux/arm/v7, linux/arm/v6, linux/386, linux/arm/v5 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 91a7e093..62bc6e7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,8 @@ jobs: - arm64 - armv7 - armv6 + - 386 + - armv5 runs-on: ubuntu-20.04 steps: - name: Checkout repository @@ -30,8 +32,14 @@ jobs: sudo apt-get update if [ "${{ matrix.platform }}" == "arm64" ]; then sudo apt install gcc-aarch64-linux-gnu - elif [ "${{ matrix.platform }}" == "armv7" ] || [ "${{ matrix.platform }}" == "armv6" ]; then + elif [ "${{ matrix.platform }}" == "armv7" ]; then sudo apt install gcc-arm-linux-gnueabihf + elif [ "${{ matrix.platform }}" == "armv6" ]; then + sudo apt install gcc-arm-linux-gnueabihf + elif [ "${{ matrix.platform }}" == "386" ]; then + sudo apt install gcc-i686-linux-gnu + elif [ "${{ matrix.platform }}" == "armv5" ]; then + sudo apt install gcc-arm-linux-gnueabi fi - name: Build x-ui @@ -42,10 +50,21 @@ jobs: if [ "${{ matrix.platform }}" == "arm64" ]; then export GOARCH=arm64 export CC=aarch64-linux-gnu-gcc - elif [ "${{ matrix.platform }}" == "armv7" ] || [ "${{ matrix.platform }}" == "armv6" ]; then + elif [ "${{ matrix.platform }}" == "armv7" ]; then export GOARCH=arm export GOARM=7 export CC=arm-linux-gnueabihf-gcc + elif [ "${{ matrix.platform }}" == "armv6" ]; then + export GOARCH=arm + export GOARM=6 + export CC=arm-linux-gnueabihf-gcc + elif [ "${{ matrix.platform }}" == "386" ]; then + export GOARCH=386 + export CC=i686-linux-gnu-gcc + elif [ "${{ matrix.platform }}" == "armv5" ]; then + export GOARCH=arm + export GOARM=5 + export CC=arm-linux-gnueabi-gcc fi go build -o xui-release -v main.go @@ -75,6 +94,14 @@ jobs: wget ${Xray_URL}Xray-linux-arm32-v6.zip unzip Xray-linux-arm32-v6.zip rm -f Xray-linux-arm32-v6.zip + elif [ "${{ matrix.platform }}" == "386" ]; then + wget ${Xray_URL}Xray-linux-32.zip + unzip Xray-linux-32.zip + rm -f Xray-linux-32.zip + elif [ "${{ matrix.platform }}" == "armv5" ]; then + wget ${Xray_URL}Xray-linux-arm32-v5.zip + unzip Xray-linux-arm32-v5.zip + rm -f Xray-linux-arm32-v5.zip fi rm -f geoip.dat geosite.dat wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat diff --git a/DockerInit.sh b/DockerInit.sh index c62dc77e..bbfcb04e 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -5,6 +5,10 @@ case $1 in ARCH="64" FNAME="amd64" ;; + i386) + ARCH="32" + FNAME="i386" + ;; armv8 | arm64 | aarch64) ARCH="arm64-v8a" FNAME="arm64" @@ -17,6 +21,10 @@ case $1 in ARCH="arm32-v6" FNAME="armv6" ;; + armv5) + ARCH="arm32-v5" + FNAME="armv5" + ;; *) ARCH="64" FNAME="amd64" @@ -29,7 +37,7 @@ cd build/bin wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.7/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" -rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat geoip_IR.dat geosite_IR.dat geoip_VN.dat geosite_VN.dat +rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat diff --git a/README.md b/README.md index 60c6c044..6b0beab7 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,22 @@ update to latest version - AlmaLinux 9+ - Rockylinux 9+ +## Compatible Architectures & Devices +Supports a variety of different architectures and devices. Here are some of the main architectures that we support: + +- **amd64**: This is the most common architecture for personal computers and servers. It supports most modern operating systems. + +- **x86 / i386**: This architecture is prevalent in desktop and laptop computers. It's widely supported by various operating systems and applications. (Ex: Most Windows, macOS, and Linux systems) + +- **armv8 / arm64 / aarch64**: This is the architecture for modern mobile and embedded devices, including smartphones and tablets. (Ex: Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS,...) + +- **armv7 / arm / arm32**: This is the architecture for older mobile and embedded devices. It is still widely used in many devices. (Ex: Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2,...) + +- **armv6 / arm / arm32**: This is the architecture for very old embedded devices. While not as common as before, there are still some devices using this architecture. (Ex: Raspberry Pi 1, Raspberry Pi Zero/Zero W,...) + +- **armv5 / arm / arm32**: This is an older architecture primarily used in early embedded systems. While it's less common today, some legacy devices may still rely on this architecture. (Ex: Early versions of Raspberry Pi, some older smartphones) + ## Languages - English @@ -398,20 +413,6 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go - -## Supported Architectures and Devices - -Supports a variety of different architectures and devices. Here are some of the main architectures that we support: - -- **amd64**: This is the most common architecture for personal computers and servers. It supports most modern operating systems. - -- **armv8 / arm64 / aarch64**: This is the architecture for modern mobile and embedded devices, including smartphones and tablets. (Ex: Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS,...) - -- **armv7 / arm / arm32**: This is the architecture for older mobile and embedded devices. It is still widely used in many devices. (Ex: Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2,...) - -- **armv6 / arm / arm32**: This is the architecture for very old embedded devices. While not as common as before, there are still some devices using this architecture. (Ex: Raspberry Pi 1, Raspberry Pi Zero/Zero W,...) - - ## Preview ![1](./media/1.png) diff --git a/go.mod b/go.mod index 6a116ba3..4e84c3e2 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/go-playground/validator/v10 v10.17.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.1.2 // indirect diff --git a/go.sum b/go.sum index 0b593906..f5d3b46b 100644 --- a/go.sum +++ b/go.sum @@ -76,8 +76,8 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= -github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= +github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= diff --git a/install.sh b/install.sh index 8d4a0c0c..ae489c2a 100644 --- a/install.sh +++ b/install.sh @@ -26,12 +26,15 @@ echo "The OS release is: $release" arch3xui() { case "$(uname -m)" in x86_64 | x64 | amd64) echo 'amd64' ;; + i*86 | x86) echo '386' ;; armv8* | armv8 | arm64 | aarch64) echo 'arm64' ;; armv7* | armv7 | arm) echo 'armv7' ;; - armv6* | armv6 | arm) echo 'armv6' ;; + armv6* | armv6) echo 'armv6' ;; + armv5* | armv5) echo 'armv5' ;; *) echo -e "${green}Unsupported CPU architecture! ${plain}" && rm -f install.sh && exit 1 ;; esac } + echo "arch: $(arch3xui)" os_version="" @@ -78,19 +81,21 @@ fi install_base() { case "${release}" in - centos|fedora|almalinux|rocky) - yum -y update && yum install -y -q wget curl tar - ;; - arch|manjaro) - pacman -Syu && pacman -Syu --noconfirm wget curl tar - ;; - *) - apt-get update && apt install -y -q wget curl tar - ;; + centos | almalinux | rocky) + yum -y update && yum install -y -q wget curl tar + ;; + fedora) + dnf -y update && dnf install -y -q wget curl tar + ;; + arch | manjaro) + pacman -Syu && pacman -Syu --noconfirm wget curl tar + ;; + *) + apt-get update && apt install -y -q wget curl tar + ;; esac } - # This function will be called when user installed x-ui out of security config_after_install() { echo -e "${yellow}Install/update finished! For security it's recommended to modify panel settings ${plain}" @@ -163,11 +168,11 @@ install_x-ui() { chmod +x x-ui # Check the system's architecture and rename the file accordingly - if [[ $(arch3xui) == "armv6" || $(arch3xui) == "armv7" ]]; then - mv bin/xray-linux-$(arch3xui) bin/xray-linux-arm - chmod +x bin/xray-linux-arm + if [[ $(arch3xui) == "armv5" || $(arch3xui) == "armv6" || $(arch3xui) == "armv7" ]]; then + mv bin/xray-linux-$(arch3xui) bin/xray-linux-arm + chmod +x bin/xray-linux-arm fi - + chmod +x x-ui bin/xray-linux-$(arch3xui) cp -f x-ui.service /etc/systemd/system/ wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh @@ -197,7 +202,6 @@ install_x-ui() { echo -e "----------------------------------------------" } - echo -e "${green}Running...${plain}" install_base install_x-ui $1 diff --git a/web/controller/inbound.go b/web/controller/inbound.go index 887559a1..4d6e0af0 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -162,24 +162,31 @@ func (a *InboundController) clearClientIps(c *gin.Context) { } func (a *InboundController) addInboundClient(c *gin.Context) { - data := &model.Inbound{} - err := c.ShouldBind(data) - if err != nil { - jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) - return - } + var requestData []model.Inbound - needRestart := true + err := c.ShouldBindJSON(&requestData) + + if err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } + + needRestart := true + + for _, data := range requestData { + + needRestart, err = a.inboundService.AddInboundClient(&data) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + } + + jsonMsg(c, "Client(s) added", nil) + if err == nil && needRestart { + a.xrayService.SetToNeedRestart() + } - needRestart, err = a.inboundService.AddInboundClient(data) - if err != nil { - jsonMsg(c, "Something went wrong!", err) - return - } - jsonMsg(c, "Client(s) added", nil) - if err == nil && needRestart { - a.xrayService.SetToNeedRestart() - } } func (a *InboundController) addGroupInboundClient(c *gin.Context) { diff --git a/web/job/check_client_ip_job.go b/web/job/check_client_ip_job.go index 65257170..b393e68d 100644 --- a/web/job/check_client_ip_job.go +++ b/web/job/check_client_ip_job.go @@ -16,17 +16,18 @@ import ( "x-ui/xray" ) -type CheckClientIpJob struct{} +type CheckClientIpJob struct { + disAllowedIps []string +} var job *CheckClientIpJob -var disAllowedIps []string var ipFiles = []string{ xray.GetIPLimitLogPath(), -xray.GetIPLimitPrevLogPath(), + xray.GetIPLimitPrevLogPath(), xray.GetIPLimitBannedLogPath(), -xray.GetIPLimitBannedPrevLogPath(), + xray.GetIPLimitBannedPrevLogPath(), xray.GetAccessPersistentLogPath(), -xray.GetAccessPersistentPrevLogPath(), + xray.GetAccessPersistentPrevLogPath(), } func NewCheckClientIpJob() *CheckClientIpJob { @@ -130,7 +131,6 @@ func (j *CheckClientIpJob) processLogFile() { } } - disAllowedIps = []string{} shouldCleanLog := false for clientEmail, ips := range InboundClientIps { @@ -237,6 +237,7 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun json.Unmarshal([]byte(inbound.Settings), &settings) clients := settings["clients"] shouldCleanLog := false + j.disAllowedIps = []string{} // create iplimit log file channel logIpFile, err := os.OpenFile(xray.GetIPLimitLogPath(), os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644) @@ -255,7 +256,7 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun shouldCleanLog = true if limitIp < len(ips) && inbound.Enable { - disAllowedIps = append(disAllowedIps, ips[limitIp:]...) + j.disAllowedIps = append(j.disAllowedIps, ips[limitIp:]...) for i := limitIp; i < len(ips); i++ { log.Printf("[LIMIT_IP] Email = %s || SRC = %s", clientEmail, ips[i]) } @@ -263,8 +264,12 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun } } } - logger.Debug("disAllowedIps ", disAllowedIps) - sort.Strings(disAllowedIps) + + sort.Strings(j.disAllowedIps) + + if len(j.disAllowedIps) > 0 { + logger.Debug("disAllowedIps ", j.disAllowedIps) + } db := database.GetDB() err = db.Save(inboundClientIps).Error diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 8c1a8000..4fcb50c6 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -178,7 +178,7 @@ "info" = "Info" "same" = "Same" "inboundData" = "Inbound's Data" -"copyToClipboard" = "Copy to Clipboard" +"exportInbound" = "Export Inbound" "import" = "Import" "importInbound" = "Import an Inbound" "isGroupEdit" = "Group editing" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 1fd2b72e..a61689f9 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -178,7 +178,7 @@ "info" = "Info" "same" = "misma" "inboundData" = "Datos de entrada" -"copyToClipboard" = "Copiar al portapapeles" +"exportInbound" = "Exportación entrante" "import" = "Importar" "importInbound" = "Importar un entrante" "isGroupEdit" = "Edición de grupo" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index d83b5e93..38c28579 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -178,7 +178,7 @@ "info" = "اطلاعات" "same" = "همسان" "inboundData" = "داده‌های ورودی" -"copyToClipboard" = "کپی در حافظه" +"exportInbound" = "استخراج ورودی" "import" = "افزودن" "importInbound" = "افزودن یک ورودی" "isGroupEdit" = "ویرایش گروهی" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index f78851e3..4bfda2b9 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -178,7 +178,7 @@ "info" = "Информация" "same" = "Тот же" "inboundData" = "Входящие данные" -"copyToClipboard" = "Копировать в буфер обмена" +"exportInbound" = "Экспорт входящих" "import" = "Импортировать" "importInbound" = "Импортировать входящее сообщение" "isGroupEdit" = "Редактирование группы" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 9277f7eb..cd19328d 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -74,9 +74,9 @@ [pages.index] "title" = "Trạng thái hệ thống" -"memory" = "Bộ nhớ" +"memory" = "Ram" "hard" = "Dung lượng" -"xrayStatus" = "Trạng thái" +"xrayStatus" = "Trạng thái Xray" "stopXray" = "Dừng lại" "restartXray" = "Khởi động lại" "xraySwitch" = "Phiên bản" @@ -178,7 +178,7 @@ "info" = "Thông tin" "same" = "Giống nhau" "inboundData" = "Dữ liệu gửi đến" -"copyToClipboard" = "Sao chép vào bảng nhớ tạm" +"exportInbound" = "Xuất nhập khẩu" "import" = "Nhập" "importInbound" = "Nhập inbound" "isGroupEdit" = "Chỉnh sửa nhóm" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index 7ed6972d..a7399642 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -178,7 +178,7 @@ "info" = "信息" "same" = "相同" "inboundData" = "入站数据" -"copyToClipboard" = "复制到剪贴板" +"exportInbound" = "出口 入境" "import"="导入" "importInbound" = "导入入站" "isGroupEdit" = "分组编辑" diff --git a/x-ui.sh b/x-ui.sh index 2807bc4f..c7331e6d 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -70,13 +70,11 @@ elif [[ "${release}" == "armbian" ]]; then echo "Your OS is Armbian" fi - # Declare Variables log_folder="${XUI_LOG_FOLDER:=/var/log}" iplimit_log_path="${log_folder}/3xipl.log" iplimit_banned_log_path="${log_folder}/3xipl-banned.log" - confirm() { if [[ $# > 1 ]]; then echo && read -p "$1 [Default $2]: " temp @@ -140,7 +138,7 @@ custom_version() { if [ -z "$panel_version" ]; then echo "Panel version cannot be empty. Exiting." - exit 1 + exit 1 fi download_link="https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh" @@ -329,15 +327,15 @@ show_log() { } show_banlog() { - if test -f "${iplimit_banned_log_path}"; then - if [[ -s "${iplimit_banned_log_path}" ]]; then - cat ${iplimit_banned_log_path} + if test -f "${iplimit_banned_log_path}"; then + if [[ -s "${iplimit_banned_log_path}" ]]; then + cat ${iplimit_banned_log_path} + else + echo -e "${red}Log file is empty.${plain}\n" + fi else - echo -e "${red}Log file is empty.${plain}\n" + echo -e "${red}Log file not found. Please Install Fail2ban and IP Limit first.${plain}\n" fi - else - echo -e "${red}Log file not found. Please Install Fail2ban and IP Limit first.${plain}\n" - fi } enable_bbr() { @@ -348,19 +346,19 @@ enable_bbr() { # Check the OS and install necessary packages case "${release}" in - ubuntu|debian) - apt-get update && apt-get install -yqq --no-install-recommends ca-certificates - ;; - centos|almalinux|rocky) - yum -y update && yum -y install ca-certificates - ;; - fedora) - dnf -y update && dnf -y install ca-certificates - ;; - *) - echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n" - exit 1 - ;; + ubuntu | debian) + apt-get update && apt-get install -yqq --no-install-recommends ca-certificates + ;; + centos | almalinux | rocky) + yum -y update && yum -y install ca-certificates + ;; + fedora) + dnf -y update && dnf -y install ca-certificates + ;; + *) + echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n" + exit 1 + ;; esac # Enable BBR @@ -581,21 +579,24 @@ ssl_cert_issue_main() { echo -e "${green}\t0.${plain} Back to Main Menu" read -p "Choose an option: " choice case "$choice" in - 0) - show_menu ;; - 1) - ssl_cert_issue ;; - 2) - local domain="" - read -p "Please enter your domain name to revoke the certificate: " domain - ~/.acme.sh/acme.sh --revoke -d ${domain} - LOGI "Certificate revoked" - ;; - 3) - local domain="" - read -p "Please enter your domain name to forcefully renew an SSL certificate: " domain - ~/.acme.sh/acme.sh --renew -d ${domain} --force ;; - *) echo "Invalid choice" ;; + 0) + show_menu + ;; + 1) + ssl_cert_issue + ;; + 2) + local domain="" + read -p "Please enter your domain name to revoke the certificate: " domain + ~/.acme.sh/acme.sh --revoke -d ${domain} + LOGI "Certificate revoked" + ;; + 3) + local domain="" + read -p "Please enter your domain name to forcefully renew an SSL certificate: " domain + ~/.acme.sh/acme.sh --renew -d ${domain} --force + ;; + *) echo "Invalid choice" ;; esac } @@ -611,15 +612,19 @@ ssl_cert_issue() { fi # install socat second case "${release}" in - ubuntu|debian|armbian) - apt update && apt install socat -y ;; - centos|almalinux|rocky) - yum -y update && yum -y install socat ;; - fedora) - dnf -y update && dnf -y install socat ;; - *) - echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n" - exit 1 ;; + ubuntu | debian | armbian) + apt update && apt install socat -y + ;; + centos | almalinux | rocky) + yum -y update && yum -y install socat + ;; + fedora) + dnf -y update && dnf -y install socat + ;; + *) + echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n" + exit 1 + ;; esac if [ $? -ne 0 ]; then LOGE "install socat failed, please check logs" @@ -750,8 +755,8 @@ ssl_cert_issue_CF() { LOGI "Certificate issued Successfully, Installing..." fi ~/.acme.sh/acme.sh --installcert -d ${CF_Domain} -d *.${CF_Domain} --ca-file /root/cert/ca.cer \ - --cert-file /root/cert/${CF_Domain}.cer --key-file /root/cert/${CF_Domain}.key \ - --fullchain-file /root/cert/fullchain.cer + --cert-file /root/cert/${CF_Domain}.cer --key-file /root/cert/${CF_Domain}.key \ + --fullchain-file /root/cert/fullchain.cer if [ $? -ne 0 ]; then LOGE "Certificate installation failed, script exiting..." exit 1 @@ -782,21 +787,22 @@ warp_cloudflare() { echo -e "${green}\t0.${plain} Back to Main Menu" read -p "Choose an option: " choice case "$choice" in - 0) - show_menu ;; - 1) - bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh) - ;; - 2) - warp a - ;; - 3) - warp y - ;; - 4) - warp u - ;; - *) echo "Invalid choice" ;; + 0) + show_menu + ;; + 1) + bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh) + ;; + 2) + warp a + ;; + 3) + warp y + ;; + 4) + warp u + ;; + *) echo "Invalid choice" ;; esac } @@ -809,45 +815,46 @@ multi_protocol() { echo -e "${green}\t0.${plain} Back to Main Menu" read -p "Choose an option: " choice case "$choice" in - 0) - show_menu ;; - 1) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/install.sh --ipv4) - ;; - 2) - bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/unistall.sh --ipv4) - ;; - 3) - systemctl start 3xui-multi-protocol - ;; - 4) - systemctl stop 3xui-multi-protocol - ;; - *) echo "Invalid choice" ;; + 0) + show_menu + ;; + 1) + bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/install.sh --ipv4) + ;; + 2) + bash <(curl -Ls https://raw.githubusercontent.com/M4mmad/3xui-multi-protocol/master/unistall.sh --ipv4) + ;; + 3) + systemctl start 3xui-multi-protocol + ;; + 4) + systemctl stop 3xui-multi-protocol + ;; + *) echo "Invalid choice" ;; esac } run_speedtest() { # Check if Speedtest is already installed - if ! command -v speedtest &> /dev/null; then + if ! command -v speedtest &>/dev/null; then # If not installed, install it local pkg_manager="" local speedtest_install_script="" - - if command -v dnf &> /dev/null; then + + if command -v dnf &>/dev/null; then pkg_manager="dnf" speedtest_install_script="https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.rpm.sh" - elif command -v yum &> /dev/null; then + elif command -v yum &>/dev/null; then pkg_manager="yum" speedtest_install_script="https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.rpm.sh" - elif command -v apt-get &> /dev/null; then + elif command -v apt-get &>/dev/null; then pkg_manager="apt-get" speedtest_install_script="https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh" - elif command -v apt &> /dev/null; then + elif command -v apt &>/dev/null; then pkg_manager="apt" speedtest_install_script="https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh" fi - + if [[ -z $pkg_manager ]]; then echo "Error: Package manager not found. You may need to install Speedtest manually." return 1 @@ -862,8 +869,11 @@ run_speedtest() { } create_iplimit_jails() { - # Use default bantime if not passed => 5 minutes - local bantime="${1:-5}" + # Use default bantime if not passed => 30 minutes + local bantime="${1:-30}" + + # Uncomment 'allowipv6 = auto' in fail2ban.conf + sed -i 's/#allowipv6 = auto/allowipv6 = auto/g' /etc/fail2ban/fail2ban.conf cat << EOF > /etc/fail2ban/jail.d/3x-ipl.conf [3x-ipl] @@ -907,7 +917,7 @@ actionunban = -D f2b- -s -j [Init] EOF - echo -e "${green}Created Ip Limit jail files with a bantime of ${bantime} minutes.${plain}" + echo -e "${green}Ip Limit jail files created with a bantime of ${bantime} minutes.${plain}" } iplimit_remove_conflicts() { @@ -935,61 +945,73 @@ iplimit_main() { 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 - create_iplimit_jails ${NUM} - systemctl restart fail2ban - 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) - show_banlog - ;; - 5) - service fail2ban status - ;; + 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 30]: " NUM + if [[ $NUM =~ ^[0-9]+$ ]]; then + create_iplimit_jails ${NUM} + systemctl restart fail2ban + 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 + truncate -s 0 "${iplimit_banned_log_path}" + echo -e "${green}All users Unbanned successfully.${plain}" + iplimit_main + else + echo -e "${yellow}Cancelled.${plain}" + fi + iplimit_main + ;; + 4) + show_banlog + ;; + 5) + service fail2ban status + ;; - 6) - remove_iplimit ;; - *) echo "Invalid choice" ;; + 6) + 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) - apt update && apt install fail2ban -y ;; - centos|almalinux|rocky) - yum -y update && yum -y install fail2ban ;; - fedora) - dnf -y update && dnf -y install fail2ban ;; - *) - echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n" - exit 1 ;; + ubuntu | debian) + apt update && apt install fail2ban -y + ;; + centos | almalinux | rocky) + yum update -y && yum install epel-release -y + yum -y install fail2ban + ;; + fedora) + dnf -y update && 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 if ! command -v fail2ban-client &>/dev/null; then @@ -1024,6 +1046,7 @@ install_iplimit() { # Launching fail2ban if ! systemctl is-active --quiet fail2ban; then systemctl start fail2ban + systemctl enable fail2ban else systemctl restart fail2ban fi @@ -1033,41 +1056,53 @@ install_iplimit() { before_show_menu } -remove_iplimit(){ +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 - systemctl restart fail2ban - echo -e "${green}IP Limit removed successfully!${plain}\n" - before_show_menu ;; - 2) - rm -rf /etc/fail2ban - systemctl stop fail2ban - case "${release}" in - ubuntu|debian) - apt-get purge fail2ban -y;; - centos|almalinux|rocky) - yum remove fail2ban -y;; - fedora) - dnf remove fail2ban -y;; - *) - echo -e "${red}Unsupported operating system. Please uninstall Fail2ban manually.${plain}\n" - exit 1 ;; - esac - 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 ;; + 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 + systemctl restart fail2ban + echo -e "${green}IP Limit removed successfully!${plain}\n" + before_show_menu + ;; + 2) + rm -rf /etc/fail2ban + systemctl stop fail2ban + case "${release}" in + ubuntu | debian) + apt-get remove -y fail2ban + apt-get purge -y fail2ban -y + apt-get autoremove -y + ;; + centos | almalinux | rocky) + yum remove fail2ban -y + yum autoremove -y + ;; + fedora) + dnf remove fail2ban -y + dnf autoremove -y + ;; + *) + echo -e "${red}Unsupported operating system. Please uninstall Fail2ban manually.${plain}\n" + exit 1 + ;; + esac + 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 } @@ -1202,7 +1237,7 @@ show_menu() { ;; 24) run_speedtest - ;; + ;; *) LOGE "Please enter the correct number [0-24]" ;;