From a85b02c6ab9124dba856399dab2887bbe445e679 Mon Sep 17 00:00:00 2001 From: bnam999 Date: Sun, 6 Oct 2024 23:10:07 +0800 Subject: [PATCH 01/24] support for openEuler (#2574) --- README.es_ES.md | 1 + README.md | 1 + README.ru_RU.md | 1 + README.zh_CN.md | 1 + install.sh | 5 +++++ x-ui.sh | 5 +++++ 6 files changed, 14 insertions(+) diff --git a/README.es_ES.md b/README.es_ES.md index 5da2e5a6..ffb5b7d1 100644 --- a/README.es_ES.md +++ b/README.es_ES.md @@ -218,6 +218,7 @@ location /sub { - Ubuntu 20.04+ - Debian 11+ - CentOS 8+ +- OpenEuler 22.03+ - Fedora 36+ - Arch Linux - Parch Linux diff --git a/README.md b/README.md index a2edad7f..ed4dfecb 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,7 @@ location /sub { - Ubuntu 20.04+ - Debian 11+ - CentOS 8+ +- OpenEuler 22.03+ - Fedora 36+ - Arch Linux - Parch Linux diff --git a/README.ru_RU.md b/README.ru_RU.md index 0da90fb6..5483c658 100644 --- a/README.ru_RU.md +++ b/README.ru_RU.md @@ -244,6 +244,7 @@ location /sub { - Ubuntu 20.04+ - Debian 11+ - CentOS 8+ +- OpenEuler 22.03+ - Fedora 36+ - Arch Linux - Parch Linux diff --git a/README.zh_CN.md b/README.zh_CN.md index 0aa7efcf..46b4b8a4 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -241,6 +241,7 @@ location /sub { - Ubuntu 20.04+ - Debian 11+ - CentOS 8+ +- OpenEuler 22.03+ - Fedora 36+ - Arch Linux - Parch Linux diff --git a/install.sh b/install.sh index 375adc9d..856adb85 100644 --- a/install.sh +++ b/install.sh @@ -51,6 +51,10 @@ elif [[ "${release}" == "armbian" ]]; then echo "Your OS is Armbian" elif [[ "${release}" == "opensuse-tumbleweed" ]]; then echo "Your OS is OpenSUSE Tumbleweed" +elif [[ "${release}" == "openEuler" ]]; then + if [[ ${os_version} -lt 2203 ]]; then + echo -e "${red} Please use OpenEuler 22.03 or higher ${plain}\n" && exit 1 + fi elif [[ "${release}" == "centos" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1 @@ -89,6 +93,7 @@ else echo "- Ubuntu 20.04+" echo "- Debian 11+" echo "- CentOS 8+" + echo "- OpenEuler 22.03+" echo "- Fedora 36+" echo "- Arch Linux" echo "- Parch Linux" diff --git a/x-ui.sh b/x-ui.sh index 3219453e..6d642fa7 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -48,6 +48,10 @@ elif [[ "${release}" == "armbian" ]]; then echo "Your OS is Armbian" elif [[ "${release}" == "opensuse-tumbleweed" ]]; then echo "Your OS is OpenSUSE Tumbleweed" +elif [[ "${release}" == "openEuler" ]]; then + if [[ ${os_version} -lt 2203 ]]; then + echo -e "${red} Please use OpenEuler 22.03 or higher ${plain}\n" && exit 1 + fi elif [[ "${release}" == "centos" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1 @@ -86,6 +90,7 @@ else echo "- Ubuntu 20.04+" echo "- Debian 11+" echo "- CentOS 8+" + echo "- OpenEuler 22.03+" echo "- Fedora 36+" echo "- Arch Linux" echo "- Parch Linux" From db6781f3115202c4f77e679db93982a9a4315c37 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 10:35:22 +0200 Subject: [PATCH 02/24] Update release.yml --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 799f6b42..731a916a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,10 @@ name: Release 3X-UI on: + workflow_dispatch: push: tags: - - "*" - workflow_dispatch: + - "v*.*.*" jobs: build: From aaf68ecb2160f91fbe3f94ea4c8cb292bbe1eecd Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 14:02:51 +0200 Subject: [PATCH 03/24] update api doc --- README.es_ES.md | 4 ++-- README.md | 4 ++-- README.ru_RU.md | 4 ++-- README.zh_CN.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.es_ES.md b/README.es_ES.md index ffb5b7d1..c6ac544b 100644 --- a/README.es_ES.md +++ b/README.es_ES.md @@ -482,8 +482,8 @@ Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas d - `client.email` para Shadowsocks -- [Documentación de API](https://documenter.getpostman.com/view/16802678/2s9YkgD5jm) -- [Run In Postman](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9) +- [Documentación de API](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) +- [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) ## Variables de Entorno diff --git a/README.md b/README.md index ed4dfecb..ef1e92ee 100644 --- a/README.md +++ b/README.md @@ -515,8 +515,8 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi - `client.email` for Shadowsocks -- [API Documentation](https://documenter.getpostman.com/view/16802678/2s9YkgD5jm) -- [Run In Postman](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9) +- [API Documentation](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) +- [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) ## Environment Variables diff --git a/README.ru_RU.md b/README.ru_RU.md index 5483c658..9d0d9a38 100644 --- a/README.ru_RU.md +++ b/README.ru_RU.md @@ -512,8 +512,8 @@ WARP встроен, и дополнительная установка не т -- [API-документация](https://documenter.getpostman.com/view/16802678/2s9YkgD5jm) -- [Run In Postman](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9) +- [API документация](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) +- [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) ## Переменные среды diff --git a/README.zh_CN.md b/README.zh_CN.md index 46b4b8a4..a42a1d6b 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -504,8 +504,8 @@ Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备 - `client.email` Shadowsocks -- [API 文档](https://documenter.getpostman.com/view/16802678/2s9YkgD5jm) -- [Run In Postman](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9) +- [API 文档](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) +- [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) ## 环境变量 From 8335238eb3ccb6990414b45183b3bac6b544bbf7 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 14:50:59 +0200 Subject: [PATCH 04/24] Auto-detect existing SSL domains --- x-ui.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 6d642fa7..2827c2bf 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -788,7 +788,9 @@ ssl_cert_issue_main() { echo -e "${green}\t1.${plain} Get SSL" echo -e "${green}\t2.${plain} Revoke" echo -e "${green}\t3.${plain} Force Renew" + echo -e "${green}\t4.${plain} Show Existing Domains" echo -e "${green}\t0.${plain} Back to Main Menu" + read -p "Choose an option: " choice case "$choice" in 0) @@ -798,17 +800,62 @@ ssl_cert_issue_main() { 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" + # Auto-detect existing domains for revoking + local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + if [ -z "$domains" ]; then + echo "No certificates found to revoke." + else + echo "Existing domains:" + echo "$domains" + read -p "Please enter a domain from the list to revoke the certificate: " domain + if [[ " $domains " =~ " $domain " ]]; then + ~/.acme.sh/acme.sh --revoke -d ${domain} + LOGI "Certificate revoked for domain: $domain" + else + echo "Invalid domain entered." + fi + fi ;; 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 + # Auto-detect existing domains for force renewal + local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + if [ -z "$domains" ]; then + echo "No certificates found to renew." + else + echo "Existing domains:" + echo "$domains" + read -p "Please enter a domain from the list to renew the SSL certificate: " domain + if [[ " $domains " =~ " $domain " ]]; then + ~/.acme.sh/acme.sh --renew -d ${domain} --force + LOGI "Certificate forcefully renewed for domain: $domain" + else + echo "Invalid domain entered." + fi + fi + ;; + 4) + # Show existing certificate paths for all domains + local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + if [ -z "$domains" ]; then + echo "No certificates found." + else + echo "Existing domains and their paths:" + for domain in $domains; do + local cert_path="/root/cert/${domain}/fullchain.pem" + local key_path="/root/cert/${domain}/privkey.pem" + if [[ -f "${cert_path}" && -f "${key_path}" ]]; then + echo -e "Domain: ${domain}" + echo -e "\tCertificate Path: ${cert_path}" + echo -e "\tPrivate Key Path: ${key_path}" + else + echo -e "Domain: ${domain} - Certificate or Key missing." + fi + done + fi + ;; + *) + echo "Invalid choice" ;; - *) echo "Invalid choice" ;; esac } From 5f531f2de1340f39fae89a3140d91ee86293f11c Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 15:13:38 +0200 Subject: [PATCH 05/24] Set Cert paths for the panel Option to automatically set the web certificate and key file paths for the panel --- x-ui.sh | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 2827c2bf..615a7708 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -789,6 +789,7 @@ ssl_cert_issue_main() { echo -e "${green}\t2.${plain} Revoke" echo -e "${green}\t3.${plain} Force Renew" echo -e "${green}\t4.${plain} Show Existing Domains" + echo -e "${green}\t5.${plain} Set Cert paths for the panel" echo -e "${green}\t0.${plain} Back to Main Menu" read -p "Choose an option: " choice @@ -800,7 +801,6 @@ ssl_cert_issue_main() { ssl_cert_issue ;; 2) - # Auto-detect existing domains for revoking local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) if [ -z "$domains" ]; then echo "No certificates found to revoke." @@ -817,7 +817,6 @@ ssl_cert_issue_main() { fi ;; 3) - # Auto-detect existing domains for force renewal local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) if [ -z "$domains" ]; then echo "No certificates found to renew." @@ -834,7 +833,6 @@ ssl_cert_issue_main() { fi ;; 4) - # Show existing certificate paths for all domains local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) if [ -z "$domains" ]; then echo "No certificates found." @@ -853,7 +851,33 @@ ssl_cert_issue_main() { done fi ;; - *) + 5) + local domains=$(find /root/cert/ -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + if [ -z "$domains" ]; then + echo "No certificates found." + else + echo "Available domains:" + echo "$domains" + read -p "Please choose a domain to set the panel paths: " domain + if [[ " $domains " =~ " $domain " ]]; then + local webCertFile="/root/cert/${domain}/fullchain.pem" + local webKeyFile="/root/cert/${domain}/privkey.pem" + + if [[ -f "${webCertFile}" && -f "${webKeyFile}" ]]; then + /usr/local/x-ui/x-ui setting -webCert "$webCertFile" + /usr/local/x-ui/x-ui setting -webCertKey "$webKeyFile" + echo "Panel paths set for domain: $domain" + echo " - Certificate File: $webCertFile" + echo " - Private Key File: $webKeyFile" + else + echo "Certificate or private key not found for domain: $domain." + fi + else + echo "Invalid domain entered." + fi + fi + ;; + *) echo "Invalid choice" ;; esac From b8df15171e5fedb5919f978aef84973690a7e939 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 15:18:56 +0200 Subject: [PATCH 06/24] ask auto set after get new cert --- x-ui.sh | 71 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 615a7708..eed60faf 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -864,8 +864,8 @@ ssl_cert_issue_main() { local webKeyFile="/root/cert/${domain}/privkey.pem" if [[ -f "${webCertFile}" && -f "${webKeyFile}" ]]; then - /usr/local/x-ui/x-ui setting -webCert "$webCertFile" - /usr/local/x-ui/x-ui setting -webCertKey "$webKeyFile" + /usr/local/x-ui/x-ui cert -webCert "$webCertFile" + /usr/local/x-ui/x-ui cert -webCertKey "$webKeyFile" echo "Panel paths set for domain: $domain" echo " - Certificate File: $webCertFile" echo " - Private Key File: $webKeyFile" @@ -893,6 +893,7 @@ ssl_cert_issue() { exit 1 fi fi + # install socat second case "${release}" in ubuntu | debian | armbian) @@ -919,23 +920,23 @@ ssl_cert_issue() { LOGI "install socat succeed..." fi - # get the domain here,and we need verify it + # get the domain here, and we need to verify it local domain="" - read -p "Please enter your domain name:" domain - LOGD "your domain is:${domain},check it..." - # here we need to judge whether there exists cert already - local currentCert=$(~/.acme.sh/acme.sh --list | tail -1 | awk '{print $1}') + read -p "Please enter your domain name: " domain + LOGD "Your domain is: ${domain}, checking it..." - if [ ${currentCert} == ${domain} ]; then + # check if there already exists a certificate + local currentCert=$(~/.acme.sh/acme.sh --list | tail -1 | awk '{print $1}') + if [ "${currentCert}" == "${domain}" ]; then local certInfo=$(~/.acme.sh/acme.sh --list) - LOGE "system already has certs here,can not issue again,current certs details:" + LOGE "System already has certificates for this domain. Cannot issue again. Current certificate details:" LOGI "$certInfo" exit 1 else - LOGI "your domain is ready for issuing cert now..." + LOGI "Your domain is ready for issuing certificates now..." fi - # create a directory for install cert + # create a directory for the certificate certPath="/root/cert/${domain}" if [ ! -d "$certPath" ]; then mkdir -p "$certPath" @@ -944,48 +945,70 @@ ssl_cert_issue() { mkdir -p "$certPath" fi - # get needed port here + # get the port number for the standalone server local WebPort=80 - read -p "please choose which port do you use,default will be 80 port:" WebPort + read -p "Please choose which port to use (default is 80): " WebPort if [[ ${WebPort} -gt 65535 || ${WebPort} -lt 1 ]]; then - LOGE "your input ${WebPort} is invalid,will use default port" + LOGE "Your input ${WebPort} is invalid, will use default port 80." + WebPort=80 fi - LOGI "will use port:${WebPort} to issue certs,please make sure this port is open..." - # NOTE:This should be handled by user - # open the port and kill the occupied progress + LOGI "Will use port: ${WebPort} to issue certificates. Please make sure this port is open." + + # issue the certificate ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt ~/.acme.sh/acme.sh --issue -d ${domain} --listen-v6 --standalone --httpport ${WebPort} if [ $? -ne 0 ]; then - LOGE "issue certs failed,please check logs" + LOGE "Issuing certificate failed, please check logs." rm -rf ~/.acme.sh/${domain} exit 1 else - LOGE "issue certs succeed,installing certs..." + LOGE "Issuing certificate succeeded, installing certificates..." fi - # install cert + + # install the certificate ~/.acme.sh/acme.sh --installcert -d ${domain} \ --key-file /root/cert/${domain}/privkey.pem \ --fullchain-file /root/cert/${domain}/fullchain.pem if [ $? -ne 0 ]; then - LOGE "install certs failed,exit" + LOGE "Installing certificate failed, exiting." rm -rf ~/.acme.sh/${domain} exit 1 else - LOGI "install certs succeed,enable auto renew..." + LOGI "Installing certificate succeeded, enabling auto renew..." fi + # enable auto-renew ~/.acme.sh/acme.sh --upgrade --auto-upgrade if [ $? -ne 0 ]; then - LOGE "auto renew failed, certs details:" + LOGE "Auto renew failed, certificate details:" ls -lah cert/* chmod 755 $certPath/* exit 1 else - LOGI "auto renew succeed, certs details:" + LOGI "Auto renew succeeded, certificate details:" ls -lah cert/* chmod 755 $certPath/* fi + + # Prompt user to set panel paths after successful certificate installation + read -p "Would you like to set this certificate for the panel? (y/n): " setPanel + if [[ "$setPanel" == "y" || "$setPanel" == "Y" ]]; then + local webCertFile="/root/cert/${domain}/fullchain.pem" + local webKeyFile="/root/cert/${domain}/privkey.pem" + + if [[ -f "$webCertFile" && -f "$webKeyFile" ]]; then + /usr/local/x-ui/x-ui cert -webCert "$webCertFile" + /usr/local/x-ui/x-ui cert -webCertKey "$webKeyFile" + LOGI "Panel paths set for domain: $domain" + LOGI " - Certificate File: $webCertFile" + LOGI " - Private Key File: $webKeyFile" + else + LOGE "Error: Certificate or private key file not found for domain: $domain." + fi + else + LOGI "Skipping panel path setting." + fi } ssl_cert_issue_CF() { From e72f67ca54dd8e4a2a5b263f466603a60d20a9d2 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 15:24:35 +0200 Subject: [PATCH 07/24] update dependencies --- go.mod | 24 ++++++++++++------------ go.sum | 46 +++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index e62cdcf9..1d01274c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module x-ui -go 1.23.1 +go 1.23.2 require ( github.com/gin-contrib/gzip v1.0.1 @@ -16,7 +16,7 @@ require ( github.com/valyala/fasthttp v1.56.0 github.com/xtls/xray-core v1.8.25-0.20241002041629-e45cef542e26 go.uber.org/atomic v1.11.0 - golang.org/x/text v0.18.0 + golang.org/x/text v0.19.0 google.golang.org/grpc v1.67.1 gorm.io/driver/sqlite v1.5.6 gorm.io/gorm v1.25.12 @@ -51,11 +51,11 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.10 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect - github.com/kr/text v0.1.0 // indirect + github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.23 // indirect + github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/onsi/ginkgo/v2 v2.20.2 // indirect @@ -71,7 +71,7 @@ require ( github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.8.0 // indirect + github.com/tklauser/numcpus v0.9.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect @@ -83,15 +83,15 @@ require ( github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/mock v0.4.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/arch v0.10.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect + golang.org/x/arch v0.11.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.26.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect diff --git a/go.sum b/go.sum index c2efc22a..3e52536e 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,7 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -89,17 +90,16 @@ github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0= -github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -162,8 +162,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= -github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= -github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= +github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -192,16 +192,16 @@ go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= -golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= +golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -211,14 +211,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= From 761eb5f38435dee33ca6c6088321cb5005a43acb Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 15:28:00 +0200 Subject: [PATCH 08/24] update install_acme --- x-ui.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index eed60faf..5bf68fbd 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -772,15 +772,23 @@ update_geo() { } install_acme() { - cd ~ - LOGI "install acme..." - curl https://get.acme.sh | sh + # Check if acme.sh is already installed + if command -v ~/.acme.sh/acme.sh &>/dev/null; then + LOGI "acme.sh is already installed." + return 0 + fi + + LOGI "Installing acme.sh..." + cd ~ || return 1 # Ensure you can change to the home directory + + curl -s https://get.acme.sh | sh if [ $? -ne 0 ]; then - LOGE "install acme failed" + LOGE "Installation of acme.sh failed." return 1 else - LOGI "install acme succeed" + LOGI "Installation of acme.sh succeeded." fi + return 0 } From 41d39dfaa8a92847b4e83807ace32a6395347b05 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 15:37:53 +0200 Subject: [PATCH 09/24] Add user choice for geo updates --- x-ui.sh | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 5bf68fbd..12621589 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -748,26 +748,43 @@ delete_ports() { } update_geo() { - local defaultBinFolder="/usr/local/x-ui/bin" - read -p "Please enter x-ui bin folder path. Leave blank for default. (Default: '${defaultBinFolder}')" binFolder - binFolder=${binFolder:-${defaultBinFolder}} - if [[ ! -d ${binFolder} ]]; then - LOGE "Folder ${binFolder} not exists!" - LOGI "making bin folder: ${binFolder}..." - mkdir -p ${binFolder} - fi - + echo -e "${green}\t1.${plain} Loyalsoldier (geoip.dat, geosite.dat)" + echo -e "${green}\t2.${plain} chocolate4u (geoip_IR.dat, geosite_IR.dat)" + echo -e "${green}\t3.${plain} vuong2023 (geoip_VN.dat, geosite_VN.dat)" + echo -e "${green}\t0.${plain} Back to Main Menu" + read -p "Choose an option: " choice + systemctl stop x-ui - cd ${binFolder} - rm -f geoip.dat geosite.dat geoip_IR.dat geosite_IR.dat geoip_VN.dat geosite_VN.dat - wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat - wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat - wget -O geoip_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat - wget -O geosite_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat - wget -O geoip_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat - wget -O geosite_VN.dat https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat + cd /usr/local/x-ui/bin + + case "$choice" in + 0) + show_menu + ;; + 1) + rm -f geoip.dat geosite.dat + wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat + wget -N https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat + echo -e "${green}Loyalsoldier datasets have been updated successfully!${plain}" + ;; + 2) + rm -f geoip_IR.dat geosite_IR.dat + wget -O geoip_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat + wget -O geosite_IR.dat -N https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat + echo -e "${green}chocolate4u datasets have been updated successfully!${plain}" + ;; + 3) + rm -f geoip_VN.dat geosite_VN.dat + wget -O geoip_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geoip.dat + wget -O geosite_VN.dat -N https://github.com/vuong2023/vn-v2ray-rules/releases/latest/download/geosite.dat + echo -e "${green}vuong2023 datasets have been updated successfully!${plain}" + ;; + *) + echo "Invalid option selected! No updates made." + ;; + esac + systemctl start x-ui - echo -e "${green}Geosite.dat + Geoip.dat + geoip_IR.dat + geosite_IR.dat have been updated successfully in bin folder '${binfolder}'!${plain}" before_show_menu } From 8404b3323234dc40b8c023f9f9f4ee9dca975097 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 17:21:32 +0200 Subject: [PATCH 10/24] bash - minor change --- x-ui.sh | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 12621589..8c294cd5 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -176,12 +176,12 @@ update_menu() { fi return 0 fi - + wget --no-check-certificate -O /usr/bin/x-ui https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh chmod +x /usr/local/x-ui/x-ui.sh chmod +x /usr/bin/x-ui - - if [[ $? == 0 ]]; then + + if [[ $? == 0 ]]; then echo -e "${green}Update successful. The panel has automatically restarted.${plain}" exit 0 else @@ -216,7 +216,7 @@ custom_version() { # Function to handle the deletion of the script file delete_script() { - rm "$0" # Remove the script file itself + rm "$0" # Remove the script file itself exit 1 } @@ -275,7 +275,7 @@ gen_random_string() { reset_webbasepath() { echo -e "${yellow}Resetting Web Base Path${plain}" - + read -rp "Are you sure you want to reset the web base path? (y/n): " confirm if [[ $confirm != "y" && $confirm != "Y" ]]; then echo -e "${yellow}Operation canceled.${plain}" @@ -283,11 +283,11 @@ reset_webbasepath() { fi config_webBasePath=$(gen_random_string 10) - + # Apply the new web base path setting /usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}" >/dev/null 2>&1 systemctl restart x-ui - + # Display confirmation message echo -e "Web base path has been reset to: ${green}${config_webBasePath}${plain}" echo -e "${green}Please use the new web base path to access the panel.${plain}" @@ -732,7 +732,7 @@ delete_ports() { done # Confirm that the ports are deleted - + echo "Deleted the specified ports:" for port in "${PORT_LIST[@]}"; do if [[ $port == *-* ]]; then @@ -753,7 +753,7 @@ update_geo() { echo -e "${green}\t3.${plain} vuong2023 (geoip_VN.dat, geosite_VN.dat)" echo -e "${green}\t0.${plain} Back to Main Menu" read -p "Choose an option: " choice - + systemctl stop x-ui cd /usr/local/x-ui/bin @@ -783,7 +783,7 @@ update_geo() { echo "Invalid option selected! No updates made." ;; esac - + systemctl start x-ui before_show_menu } @@ -796,7 +796,7 @@ install_acme() { fi LOGI "Installing acme.sh..." - cd ~ || return 1 # Ensure you can change to the home directory + cd ~ || return 1 # Ensure you can change to the home directory curl -s https://get.acme.sh | sh if [ $? -ne 0 ]; then @@ -833,7 +833,7 @@ ssl_cert_issue_main() { echo "Existing domains:" echo "$domains" read -p "Please enter a domain from the list to revoke the certificate: " domain - if [[ " $domains " =~ " $domain " ]]; then + if echo "$domains" | grep -qw "$domain"; then ~/.acme.sh/acme.sh --revoke -d ${domain} LOGI "Certificate revoked for domain: $domain" else @@ -849,7 +849,7 @@ ssl_cert_issue_main() { echo "Existing domains:" echo "$domains" read -p "Please enter a domain from the list to renew the SSL certificate: " domain - if [[ " $domains " =~ " $domain " ]]; then + if echo "$domains" | grep -qw "$domain"; then ~/.acme.sh/acme.sh --renew -d ${domain} --force LOGI "Certificate forcefully renewed for domain: $domain" else @@ -884,13 +884,13 @@ ssl_cert_issue_main() { echo "Available domains:" echo "$domains" read -p "Please choose a domain to set the panel paths: " domain - if [[ " $domains " =~ " $domain " ]]; then + + if echo "$domains" | grep -qw "$domain"; then local webCertFile="/root/cert/${domain}/fullchain.pem" local webKeyFile="/root/cert/${domain}/privkey.pem" - + if [[ -f "${webCertFile}" && -f "${webKeyFile}" ]]; then - /usr/local/x-ui/x-ui cert -webCert "$webCertFile" - /usr/local/x-ui/x-ui cert -webCertKey "$webKeyFile" + /usr/local/x-ui/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile" echo "Panel paths set for domain: $domain" echo " - Certificate File: $webCertFile" echo " - Private Key File: $webKeyFile" @@ -902,7 +902,8 @@ ssl_cert_issue_main() { fi fi ;; - *) + + *) echo "Invalid choice" ;; esac @@ -1021,10 +1022,9 @@ ssl_cert_issue() { if [[ "$setPanel" == "y" || "$setPanel" == "Y" ]]; then local webCertFile="/root/cert/${domain}/fullchain.pem" local webKeyFile="/root/cert/${domain}/privkey.pem" - + if [[ -f "$webCertFile" && -f "$webKeyFile" ]]; then - /usr/local/x-ui/x-ui cert -webCert "$webCertFile" - /usr/local/x-ui/x-ui cert -webCertKey "$webKeyFile" + /usr/local/x-ui/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile" LOGI "Panel paths set for domain: $domain" LOGI " - Certificate File: $webCertFile" LOGI " - Private Key File: $webKeyFile" @@ -1146,7 +1146,6 @@ run_speedtest() { # Run Speedtest speedtest } - create_iplimit_jails() { # Use default bantime if not passed => 15 minutes local bantime="${1:-15}" From 1d84284b6ddca4ff24b0fd377e15a16656a25d1d Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 17:33:55 +0200 Subject: [PATCH 11/24] Update docker.yml --- .github/workflows/docker.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 94a82bb3..50ce7fbc 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,9 +1,10 @@ name: Release 3X-UI for Docker + on: + workflow_dispatch: push: tags: - - "*" - workflow_dispatch: + - "v*.*.*" jobs: build_and_push: From 7efe1d60d54358d6d7d8fb9ff03406cb75f15c9a Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 17:34:08 +0200 Subject: [PATCH 12/24] readme --- README.es_ES.md | 3 +-- README.md | 3 +-- README.ru_RU.md | 2 +- README.zh_CN.md | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.es_ES.md b/README.es_ES.md index c6ac544b..e5009057 100644 --- a/README.es_ES.md +++ b/README.es_ES.md @@ -452,6 +452,7 @@ Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas d #### Uso +- [Documentación de API](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - `/login` con `POST` datos de usuario: `{username: '', password: ''}` para iniciar sesión - `/panel/api/inbounds` base para las siguientes acciones: @@ -481,8 +482,6 @@ Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas d - `client.password` para TROJAN - `client.email` para Shadowsocks - -- [Documentación de API](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) diff --git a/README.md b/README.md index ef1e92ee..d0205f31 100644 --- a/README.md +++ b/README.md @@ -484,6 +484,7 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi #### Usage +- [API Documentation](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - `/login` with `POST` user data: `{username: '', password: ''}` for login - `/panel/api/inbounds` base for following actions: @@ -514,8 +515,6 @@ Enter the user ID in input field number 4. The Telegram accounts with this id wi - `client.password` for TROJAN - `client.email` for Shadowsocks - -- [API Documentation](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) diff --git a/README.ru_RU.md b/README.ru_RU.md index 9d0d9a38..20e108bb 100644 --- a/README.ru_RU.md +++ b/README.ru_RU.md @@ -479,6 +479,7 @@ WARP встроен, и дополнительная установка не т #### Использование +- [API документация](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - `/login` с `POST`-данными: `{username: '', password: ''}` для входа - `/panel/api/inbounds` это базовый путь для следующих действий: @@ -512,7 +513,6 @@ WARP встроен, и дополнительная установка не т -- [API документация](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) diff --git a/README.zh_CN.md b/README.zh_CN.md index a42a1d6b..dda0651e 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -474,6 +474,7 @@ Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备 #### 使用 +- [API 文档](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - `/login` 使用 `POST` 用户名称 & 密码: `{username: '', password: ''}` 登录 - `/panel/api/inbounds` 以下操作的基础: @@ -503,8 +504,6 @@ Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备 - `client.password` TROJAN - `client.email` Shadowsocks - -- [API 文档](https://documenter.getpostman.com/view/5146551/2sAXxP8Y12) - [Run In Postman](https://god.gw.postman.com/run-collection/5146551-e6aac565-e0e2-46df-acff-2607a51bbd04?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-e6aac565-e0e2-46df-acff-2607a51bbd04%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124) From e70305579345da3599f4d1a5dfbeee7f37744f75 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Mon, 7 Oct 2024 17:38:23 +0200 Subject: [PATCH 13/24] bash - restart panel after cert set --- x-ui.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-ui.sh b/x-ui.sh index 8c294cd5..ab3c34a1 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -286,11 +286,10 @@ reset_webbasepath() { # Apply the new web base path setting /usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}" >/dev/null 2>&1 - systemctl restart x-ui - - # Display confirmation message + echo -e "Web base path has been reset to: ${green}${config_webBasePath}${plain}" echo -e "${green}Please use the new web base path to access the panel.${plain}" + restart } reset_config() { @@ -894,6 +893,7 @@ ssl_cert_issue_main() { echo "Panel paths set for domain: $domain" echo " - Certificate File: $webCertFile" echo " - Private Key File: $webKeyFile" + restart else echo "Certificate or private key not found for domain: $domain." fi @@ -1028,6 +1028,7 @@ ssl_cert_issue() { LOGI "Panel paths set for domain: $domain" LOGI " - Certificate File: $webCertFile" LOGI " - Private Key File: $webKeyFile" + restart else LOGE "Error: Certificate or private key file not found for domain: $domain." fi From dcab4e6f9c9201972e22b941bf60af549b319856 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Tue, 8 Oct 2024 16:42:47 +0200 Subject: [PATCH 14/24] fix oracle --- install.sh | 4 ++-- x-ui.sh | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index 856adb85..2926f6b3 100644 --- a/install.sh +++ b/install.sh @@ -83,7 +83,7 @@ elif [[ "${release}" == "rocky" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1 fi -elif [[ "${release}" == "oracle" ]]; then +elif [[ "${release}" == "ol" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use Oracle Linux 8 or higher ${plain}\n" && exit 1 fi @@ -112,7 +112,7 @@ install_base() { ubuntu | debian | armbian) apt-get update && apt-get install -y -q wget curl tar tzdata ;; - centos | almalinux | rocky | oracle) + centos | almalinux | rocky | ol) yum -y update && yum install -y -q wget curl tar tzdata ;; fedora | amzn) diff --git a/x-ui.sh b/x-ui.sh index ab3c34a1..d312a225 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -80,7 +80,7 @@ elif [[ "${release}" == "rocky" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1 fi -elif [[ "${release}" == "oracle" ]]; then +elif [[ "${release}" == "ol" ]]; then if [[ ${os_version} -lt 8 ]]; then echo -e "${red} Please use Oracle Linux 8 or higher ${plain}\n" && exit 1 fi @@ -486,7 +486,7 @@ enable_bbr() { ubuntu | debian | armbian) apt-get update && apt-get install -yqq --no-install-recommends ca-certificates ;; - centos | almalinux | rocky | oracle) + centos | almalinux | rocky | ol) yum -y update && yum -y install ca-certificates ;; fedora | amzn) @@ -925,7 +925,7 @@ ssl_cert_issue() { ubuntu | debian | armbian) apt update && apt install socat -y ;; - centos | almalinux | rocky | oracle) + centos | almalinux | rocky | ol) yum -y update && yum -y install socat ;; fedora | amzn) @@ -1296,7 +1296,7 @@ install_iplimit() { debian | armbian) apt update && apt install fail2ban -y ;; - centos | almalinux | rocky | oracle) + centos | almalinux | rocky | ol) yum update -y && yum install epel-release -y yum -y install fail2ban ;; @@ -1377,7 +1377,7 @@ remove_iplimit() { apt-get purge -y fail2ban -y apt-get autoremove -y ;; - centos | almalinux | rocky | oracle) + centos | almalinux | rocky | ol) yum remove fail2ban -y yum autoremove -y ;; From 4f2f855c04322bb64f32cfb695878e946c4359e8 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Wed, 9 Oct 2024 10:49:05 +0200 Subject: [PATCH 15/24] validate Email - non-English Pattern --- web/service/inbound.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/service/inbound.go b/web/service/inbound.go index 5213fce6..822a4e8d 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -2024,6 +2024,7 @@ func (s *InboundService) GetOnlineClients() []string { } func validateEmail(email string) (bool, error) { + if strings.Contains(email, " ") { return false, errors.New("email contains spaces, please remove them") } @@ -2032,6 +2033,11 @@ func validateEmail(email string) (bool, error) { return false, errors.New("email contains uppercase letters, please convert to lowercase") } + nonEnglishPattern := `[^\x00-\x7F]` + if regexp.MustCompile(nonEnglishPattern).MatchString(email) { + return false, errors.New("email contains non-English characters, please use only English") + } + emailPattern := `^[a-z0-9@._-]+$` if !regexp.MustCompile(emailPattern).MatchString(email) { return false, errors.New("email contains invalid characters, please use only lowercase letters, digits, and @._-") From e37f2d322256ed4468fd0277b0cb10a5bf4ccaa9 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Wed, 9 Oct 2024 11:15:37 +0200 Subject: [PATCH 16/24] Username & Password will be generated randomly --- install.sh | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/install.sh b/install.sh index 2926f6b3..c4cc6798 100644 --- a/install.sh +++ b/install.sh @@ -138,27 +138,25 @@ gen_random_string() { config_after_install() { echo -e "${yellow}Install/update finished! For security, it's recommended to modify panel settings ${plain}" - read -p "Would you like to customize the panel settings? (If not, random settings will be applied) [y/n]: " config_confirm + read -p "Would you like to customize ${yellow}the Panel Port ${plain}settings? (If not, random settings will be applied) [y/n]: " config_confirm - local config_webBasePath=$(gen_random_string 10) + local config_webBasePath=$(gen_random_string 15) + local config_account=$(gen_random_string 10) + local config_password=$(gen_random_string 10) if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then - read -p "Please set up your username: " config_account - echo -e "${yellow}Your username will be: ${config_account}${plain}" - - read -p "Please set up your password: " config_password - echo -e "${yellow}Your password will be: ${config_password}${plain}" - read -p "Please set up the panel port: " config_port - echo -e "${yellow}Your panel port is: ${config_port}${plain}" + echo -e "${yellow}Your Panel Port is: ${config_port}${plain}" - echo -e "${yellow}Your web base path will be generated randomly: ${config_webBasePath}${plain}" + echo -e "${yellow}Your Username will be generated randomly: ${config_account}${plain}" + echo -e "${yellow}Your Password will be generated randomly: ${config_password}${plain}" + echo -e "${yellow}Your Web Base Path will be generated randomly: ${config_webBasePath}${plain}" echo -e "${yellow}Initializing, please wait...${plain}" /usr/local/x-ui/x-ui setting -username "${config_account}" -password "${config_password}" -port "${config_port}" -webBasePath "${config_webBasePath}" - echo -e "${yellow}Settings applied successfully!${plain}" + echo -e "${green}Settings applied successfully!${plain}" echo -e "###############################################" echo -e "${green}Username: ${config_account}${plain}" @@ -173,15 +171,13 @@ config_after_install() { if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then - local usernameTemp=$(gen_random_string 10) - local passwordTemp=$(gen_random_string 10) local portTemp=$(shuf -i 1024-62000 -n 1) - /usr/local/x-ui/x-ui setting -username "${usernameTemp}" -password "${passwordTemp}" -port "${portTemp}" -webBasePath "${config_webBasePath}" + /usr/local/x-ui/x-ui setting -username "${config_account}" -password "${config_password}" -port "${portTemp}" -webBasePath "${config_webBasePath}" echo -e "This is a fresh installation, generating random login info for security concerns:" echo -e "###############################################" - echo -e "${green}Username: ${usernameTemp}${plain}" - echo -e "${green}Password: ${passwordTemp}${plain}" + echo -e "${green}Username: ${config_account}${plain}" + echo -e "${green}Password: ${config_password}${plain}" echo -e "${green}Port: ${portTemp}${plain}" echo -e "${green}WebBasePath: ${config_webBasePath}${plain}" echo -e "###############################################" @@ -195,7 +191,7 @@ config_after_install() { echo -e "${yellow}WebBasePath is empty, generating a random one...${plain}" /usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}" - echo -e "${green}New webBasePath: ${config_webBasePath}${plain}" + echo -e "${green}New WebBasePath: ${config_webBasePath}${plain}" fi fi fi From f1f5d323e820e3839f3d400bbcf0a35db916aa2a Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Wed, 9 Oct 2024 12:31:11 +0200 Subject: [PATCH 17/24] Sniffing - change default --- web/assets/js/model/xray.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 078b8711..6d0c1c9d 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -1184,7 +1184,7 @@ class StreamSettings extends XrayCommonClass { class Sniffing extends XrayCommonClass { constructor( - enabled = true, + enabled = false, destOverride = ['http', 'tls', 'quic', 'fakedns'], metadataOnly = false, routeOnly = false) { From 4b1c76e97252c5bcc7a9ee16b8bd0dde693cabbb Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Thu, 10 Oct 2024 17:32:50 +0200 Subject: [PATCH 18/24] [refactor] email verification method --- web/service/inbound.go | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/web/service/inbound.go b/web/service/inbound.go index 822a4e8d..1450dd57 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -2,9 +2,7 @@ package service import ( "encoding/json" - "errors" "fmt" - "regexp" "strconv" "strings" "time" @@ -101,8 +99,9 @@ func (s *InboundService) getAllEmails() ([]string, error) { } func (s *InboundService) contains(slice []string, str string) bool { + lowerStr := strings.ToLower(str) for _, s := range slice { - if s == str { + if strings.ToLower(s) == lowerStr { return true } } @@ -414,12 +413,6 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) { return false, err } - email := clients[0].Email - valid, err := validateEmail(email) - if !valid { - return false, err - } - var settings map[string]interface{} err = json.Unmarshal([]byte(data.Settings), &settings) if err != nil { @@ -610,12 +603,6 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin return false, err } - email := clients[0].Email - valid, err := validateEmail(email) - if !valid { - return false, err - } - var settings map[string]interface{} err = json.Unmarshal([]byte(data.Settings), &settings) if err != nil { @@ -2022,26 +2009,3 @@ func (s *InboundService) MigrateDB() { func (s *InboundService) GetOnlineClients() []string { return p.GetOnlineClients() } - -func validateEmail(email string) (bool, error) { - - if strings.Contains(email, " ") { - return false, errors.New("email contains spaces, please remove them") - } - - if email != strings.ToLower(email) { - return false, errors.New("email contains uppercase letters, please convert to lowercase") - } - - nonEnglishPattern := `[^\x00-\x7F]` - if regexp.MustCompile(nonEnglishPattern).MatchString(email) { - return false, errors.New("email contains non-English characters, please use only English") - } - - emailPattern := `^[a-z0-9@._-]+$` - if !regexp.MustCompile(emailPattern).MatchString(email) { - return false, errors.New("email contains invalid characters, please use only lowercase letters, digits, and @._-") - } - - return true, nil -} From 1454c4ebc53027df757f92e9d6d205a82b7db559 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Thu, 10 Oct 2024 17:37:06 +0200 Subject: [PATCH 19/24] [bug] fix restarting core on disabling depleted user --- web/service/inbound.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/web/service/inbound.go b/web/service/inbound.go index 1450dd57..60530143 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -1037,8 +1037,12 @@ func (s *InboundService) disableInvalidInbounds(tx *gorm.DB) (bool, int64, error if err1 == nil { logger.Debug("Inbound disabled by api:", tag) } else { - logger.Debug("Error in disabling inbound by api:", err1) - needRestart = true + if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", tag)) { + logger.Debug("User is already disabled. Nothing to do more...") + } else { + logger.Debug("Error in disabling client by api:", err1) + needRestart = true + } } } s.xrayApi.Close() @@ -1076,8 +1080,16 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error) if err1 == nil { logger.Debug("Client disabled by api:", result.Email) } else { - logger.Debug("Error in disabling client by api:", err1) - needRestart = true + if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) { + logger.Debug("User is already disabled. Nothing to do more...") + } else { + if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) { + logger.Debug("User is already disabled. Nothing to do more...") + } else { + logger.Debug("Error in disabling client by api:", err1) + needRestart = true + } + } } } s.xrayApi.Close() From c385662783e6b95c5002745dfda6418762f05e47 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Thu, 10 Oct 2024 21:38:56 +0200 Subject: [PATCH 20/24] simplified basic routing (#2579) --- web/html/xui/xray.html | 616 +++++++-------------------- web/translation/translate.en_US.toml | 46 +- web/translation/translate.es_ES.toml | 39 +- web/translation/translate.fa_IR.toml | 39 +- web/translation/translate.id_ID.toml | 39 +- web/translation/translate.pt_BR.toml | 39 +- web/translation/translate.ru_RU.toml | 39 +- web/translation/translate.tr_TR.toml | 39 +- web/translation/translate.uk_UA.toml | 39 +- web/translation/translate.vi_VN.toml | 39 +- web/translation/translate.zh_CN.toml | 39 +- web/translation/translate.zh_TW.toml | 39 +- 12 files changed, 202 insertions(+), 850 deletions(-) diff --git a/web/html/xui/xray.html b/web/html/xui/xray.html index f467c97a..ac97b1f1 100644 --- a/web/html/xui/xray.html +++ b/web/html/xui/xray.html @@ -228,14 +228,10 @@ - - - - - +