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

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormohammadmovaghari <52345697+mohammadmovaghari@users.noreply.github.com>2023-04-04 16:44:40 +0300
committerGitHub <noreply@github.com>2023-04-04 16:44:40 +0300
commit9f18d60b9ce16d89af97ae993a3224bb6c8cd288 (patch)
tree978b3178c6dd5bb616d46a442d8c50b19856bb70
parentc0580bccb5b574f4a8e4a7f2789d5cdf6049e7fc (diff)
parent0e5de1aec8f3b090fce14638d7e0030ff7b7f40f (diff)
Merge branch 'MHSanaei:main' into api-fix
-rw-r--r--.github/workflows/release.yml1
-rw-r--r--config/version2
-rw-r--r--go.mod3
-rw-r--r--go.sum9
-rw-r--r--install.sh27
-rw-r--r--media/enable-traffic+block-IR-IP.txt18
-rw-r--r--media/enable-traffic+block-IR-domain.txt11
-rw-r--r--media/enable-traffic.txt5
-rw-r--r--web/assets/favicon.icobin0 -> 15406 bytes
-rw-r--r--web/html/login.html10
-rw-r--r--web/html/xui/setting.html6
-rw-r--r--web/service/config.json8
-rw-r--r--web/web.go3
-rw-r--r--x-ui.sh232
14 files changed, 244 insertions, 91 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7fae989a..5e02540f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -27,6 +27,7 @@ jobs:
rm -f Xray-linux-64.zip geoip.dat geosite.dat
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
wget https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
+ wget https://github.com/bootmortis/iran-hosted-domains/releases/latest/download/iran.dat
mv xray xray-linux-amd64
cd ..
cd ..
diff --git a/config/version b/config/version
index 781dcb07..65087b4f 100644
--- a/config/version
+++ b/config/version
@@ -1 +1 @@
-1.1.3
+1.1.4
diff --git a/go.mod b/go.mod
index 9d29e819..377ffab8 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.0.7
github.com/robfig/cron/v3 v3.0.1
- github.com/shirou/gopsutil/v3 v3.23.2
+ github.com/shirou/gopsutil/v3 v3.23.3
github.com/xtls/xray-core v1.8.0
go.uber.org/atomic v1.10.0
golang.org/x/text v0.8.0
@@ -47,6 +47,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pires/go-proxyproto v0.6.2 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
+ github.com/shoenig/go-m1cpu v0.1.4 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
diff --git a/go.sum b/go.sum
index 4122d949..61f0ec46 100644
--- a/go.sum
+++ b/go.sum
@@ -137,8 +137,12 @@ github.com/sagernet/sing v0.1.7 h1:g4vjr3q8SUlBZSx97Emz5OBfSMBxxW5Q8C2PfdoSo08=
github.com/sagernet/sing-shadowsocks v0.1.1 h1:uFK2rlVeD/b1xhDwSMbUI2goWc6fOKxp+ZeKHZq6C9Q=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
-github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU=
-github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M=
+github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
+github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
+github.com/shoenig/go-m1cpu v0.1.4 h1:SZPIgRM2sEF9NJy50mRHu9PKGwxyyTTJIWvCtgVbozs=
+github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
+github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
+github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -211,7 +215,6 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
diff --git a/install.sh b/install.sh
index 0d548e0d..ffaeb370 100644
--- a/install.sh
+++ b/install.sh
@@ -66,14 +66,33 @@ else
echo -e "${red}Failed to check the OS version, please contact the author!${plain}" && exit 1
fi
-
+# This function installs the base packages required for most scripts
install_base() {
- if [[ "${release}" == "centos" ]]; then
- yum install wget curl tar -y
+ # Store the package names in a variable for easy modification
+ local packages="wget curl tar"
+
+ # Check for the package managers and install the packages if they are not already installed
+ if ! command -v wget >/dev/null 2>&1 || ! command -v curl >/dev/null 2>&1 || ! command -v tar >/dev/null 2>&1; then
+ if command -v apt >/dev/null 2>&1; then
+ apt-get update && apt-get install -y $packages
+ elif command -v dnf >/dev/null 2>&1; then
+ dnf install -y $packages
+ elif command -v yum >/dev/null 2>&1; then
+ yum install -y $packages
+ else
+ echo "ERROR: No package managers found. Please install wget, curl, and tar manually."
+ return 1
+ fi
+
+ # Print a confirmation message after the installation is complete
+ echo "The following packages have been successfully installed: $packages"
else
- apt install wget curl tar -y
+ # Print a message confirming that the packages are already installed
+ echo "The following packages are already installed: $packages"
fi
}
+
+
#This function will be called when user installed x-ui out of sercurity
config_after_install() {
echo -e "${yellow}Install/update finished! For security it's recommended to modify panel settings ${plain}"
diff --git a/media/enable-traffic+block-IR-IP.txt b/media/enable-traffic+block-IR-IP.txt
index b1a1178f..919bef03 100644
--- a/media/enable-traffic+block-IR-IP.txt
+++ b/media/enable-traffic+block-IR-IP.txt
@@ -1,6 +1,6 @@
{
"log": {
- "loglevel": "warning",
+ "loglevel": "warning",
"access": "./access.log"
},
"api": {
@@ -56,17 +56,23 @@
"type": "field"
},
{
- "ip": [
- "geoip:private",
- "geoip:ir"
+ "outboundTag": "blocked",
+ "protocol": [
+ "bittorrent"
],
+ "type": "field"
+ },
+ {
"outboundTag": "blocked",
+ "ip": [
+ "geoip:private"
+ ],
"type": "field"
},
{
"outboundTag": "blocked",
- "protocol": [
- "bittorrent"
+ "ip": [
+ "geoip:ir"
],
"type": "field"
}
diff --git a/media/enable-traffic+block-IR-domain.txt b/media/enable-traffic+block-IR-domain.txt
index efd548c0..4fcf3ee7 100644
--- a/media/enable-traffic+block-IR-domain.txt
+++ b/media/enable-traffic+block-IR-domain.txt
@@ -46,6 +46,7 @@
}
},
"routing": {
+ "domainStrategy": "IPIfNonMatch",
"rules": [
{
"inboundTag": [
@@ -55,8 +56,8 @@
"type": "field"
},
{
- "domain": [
- "regexp:.+.ir$"
+ "ip": [
+ "geoip:private"
],
"outboundTag": "blocked",
"type": "field"
@@ -70,8 +71,10 @@
},
{
"outboundTag": "blocked",
- "ip": [
- "geoip:private"
+ "domain": [
+ "regexp:.+.ir$",
+ "ext:iran.dat:ir",
+ "ext:iran.dat:other"
],
"type": "field"
}
diff --git a/media/enable-traffic.txt b/media/enable-traffic.txt
index 0acbd3aa..34e2038f 100644
--- a/media/enable-traffic.txt
+++ b/media/enable-traffic.txt
@@ -1,6 +1,6 @@
{
"log": {
- "loglevel": "warning",
+ "loglevel": "warning",
"access": "./access.log"
},
"api": {
@@ -46,6 +46,7 @@
}
},
"routing": {
+ "domainStrategy": "IPIfNonMatch",
"rules": [
{
"inboundTag": [
@@ -55,10 +56,10 @@
"type": "field"
},
{
+ "outboundTag": "blocked",
"ip": [
"geoip:private"
],
- "outboundTag": "blocked",
"type": "field"
},
{
diff --git a/web/assets/favicon.ico b/web/assets/favicon.ico
new file mode 100644
index 00000000..99b108ab
--- /dev/null
+++ b/web/assets/favicon.ico
Binary files differ
diff --git a/web/html/login.html b/web/html/login.html
index 5138f15e..4218793c 100644
--- a/web/html/login.html
+++ b/web/html/login.html
@@ -63,25 +63,21 @@
<a-form-item>
<a-row justify="center" class="selectLang">
- <a-col :span="4"><span>Language : </span></a-col>
+ <a-col :span="5"><span>Language :</span></a-col>
- <a-col :span="6">
+ <a-col :span="7">
<a-select
ref="selectLang"
v-model="lang"
@change="setLang(lang)"
>
- <a-select-option :value="l.value" label="China" v-for="l in supportLangs" >
+ <a-select-option :value="l.value" label="English" v-for="l in supportLangs" >
<span role="img" aria-label="l.name" v-text="l.icon"></span>
&nbsp;&nbsp;<span v-text="l.name"></span>
</a-select-option>
</a-select>
</a-col>
-
</a-row>
-
-
-
</a-form-item>
</a-form>
</a-col>
diff --git a/web/html/xui/setting.html b/web/html/xui/setting.html
index 7acab065..b4a974eb 100644
--- a/web/html/xui/setting.html
+++ b/web/html/xui/setting.html
@@ -345,7 +345,7 @@
if(this.templateSettings != null){
this.templateSettings.routing.rules.forEach(routingRule => {
if(routingRule.hasOwnProperty("domain")){
- if (routingRule.domain[0] === "regexp:.+.ir$" && routingRule.outboundTag == "blocked"){
+ if ((routingRule.domain[0] === "regexp:.+.ir$" || routingRule.domain[0] === "ext:iran.dat:ir" || routingRule.domain[0] === "ext:iran.dat:other") && routingRule.outboundTag == "blocked") {
localdomainFilter = true
}
}
@@ -356,13 +356,13 @@
set: function (newValue) {
newTemplateSettings = JSON.parse(this.allSetting.xrayTemplateConfig);
if (newValue){
- newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"domain\": [\"regexp:.+.ir$\"],\"type\": \"field\"}"))
+ newTemplateSettings.routing.rules.push(JSON.parse("{\"outboundTag\": \"blocked\",\"domain\": [\"regexp:.+.ir$\", \"ext:iran.dat:ir\", \"ext:iran.dat:other\"],\"type\": \"field\"}"))
}
else {
newTemplateSettings.routing.rules = [];
this.templateSettings.routing.rules.forEach(routingRule => {
if (routingRule.hasOwnProperty('domain')){
- if (routingRule.domain[0] === "regexp:.+.ir$" && routingRule.outboundTag == "blocked"){
+ if ((routingRule.domain[0] === "regexp:.+.ir$" || routingRule.domain[0] === "ext:iran.dat:ir" || routingRule.domain[0] === "ext:iran.dat:other") && routingRule.outboundTag == "blocked"){
return;
}
}
diff --git a/web/service/config.json b/web/service/config.json
index 5370fcf4..34e2038f 100644
--- a/web/service/config.json
+++ b/web/service/config.json
@@ -1,9 +1,8 @@
{
"log": {
- "loglevel": "warning",
+ "loglevel": "warning",
"access": "./access.log"
},
-
"api": {
"services": [
"HandlerService",
@@ -47,6 +46,7 @@
}
},
"routing": {
+ "domainStrategy": "IPIfNonMatch",
"rules": [
{
"inboundTag": [
@@ -56,10 +56,10 @@
"type": "field"
},
{
+ "outboundTag": "blocked",
"ip": [
"geoip:private"
],
- "outboundTag": "blocked",
"type": "field"
},
{
@@ -72,4 +72,4 @@
]
},
"stats": {}
-}
+} \ No newline at end of file
diff --git a/web/web.go b/web/web.go
index 1c692598..b38cb3cd 100644
--- a/web/web.go
+++ b/web/web.go
@@ -156,6 +156,9 @@ func (s *Server) initRouter() (*gin.Engine, error) {
}
engine := gin.Default()
+
+ // Add favicon
+ engine.StaticFile("/favicon.ico", "web/assets/favicon.ico")
secret, err := s.settingService.GetSecret()
if err != nil {
diff --git a/x-ui.sh b/x-ui.sh
index 341e8a02..b2a1f8fa 100644
--- a/x-ui.sh
+++ b/x-ui.sh
@@ -454,6 +454,64 @@ ssl_cert_issue() {
fi
}
+open_ports() {
+
+ # Check if the firewall is inactive
+ if sudo ufw status | grep -q "Status: active"; then
+ echo "firewall is already active"
+ else
+ # Open the necessary ports
+ sudo ufw allow ssh
+ sudo ufw allow http
+ sudo ufw allow https
+ sudo ufw allow 2053/tcp
+
+ # Enable the firewall
+ sudo ufw --force enable
+ fi
+
+ # Prompt the user to enter a list of ports
+ read -p "Enter the ports you want to open (e.g. 80,443,2053 or range 400-500): " ports
+
+ # Check if the input is valid
+ if ! [[ $ports =~ ^([0-9]+|[0-9]+-[0-9]+)(,([0-9]+|[0-9]+-[0-9]+))*$ ]]; then
+ echo "Error: Invalid input. Please enter a comma-separated list of ports or a range of ports (e.g. 80,443,2053 or 400-500)." >&2; exit 1
+ fi
+
+ # Open the specified ports using ufw
+ IFS=',' read -ra PORT_LIST <<< "$ports"
+ for port in "${PORT_LIST[@]}"; do
+ if [[ $port == *-* ]]; then
+ # Split the range into start and end ports
+ start_port=$(echo $port | cut -d'-' -f1)
+ end_port=$(echo $port | cut -d'-' -f2)
+ # Loop through the range and open each port
+ for ((i=start_port; i<=end_port; i++)); do
+ sudo ufw allow $i
+ done
+ else
+ sudo ufw allow "$port"
+ fi
+ done
+
+ # Confirm that the ports are open
+ sudo ufw status | grep $ports
+}
+
+
+
+update_geo(){
+ systemctl stop x-ui
+ cd /usr/local/x-ui/bin
+ rm -f geoip.dat geosite.dat iran.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 -N https://github.com/bootmortis/iran-hosted-domains/releases/latest/download/iran.dat
+ systemctl start x-ui
+ echo -e "${green}Geosite and Geoip have been updated successfully!${plain}"
+before_show_menu
+}
+
install_acme() {
cd ~
LOGI "install acme..."
@@ -490,14 +548,7 @@ ssl_cert_issue_standalone() {
else
LOGI "install socat succeed..."
fi
- #creat a directory for install cert
- certPath=/root/cert
- if [ ! -d "$certPath" ]; then
- mkdir $certPath
- else
- rm -rf $certPath
- mkdir $certPath
- fi
+
#get the domain here,and we need verify it
local domain=""
read -p "please input your domain:" domain
@@ -512,6 +563,16 @@ ssl_cert_issue_standalone() {
else
LOGI "your domain is ready for issuing cert now..."
fi
+
+ #create a directory for install cert
+ certPath="/root/cert/${domain}"
+ if [ ! -d "$certPath" ]; then
+ mkdir -p "$certPath"
+ else
+ rm -rf "$certPath"
+ mkdir -p "$certPath"
+ fi
+
#get needed port here
local WebPort=80
read -p "please choose which port do you use,default will be 80 port:" WebPort
@@ -531,9 +592,9 @@ ssl_cert_issue_standalone() {
LOGE "issue certs succeed,installing certs..."
fi
#install cert
- ~/.acme.sh/acme.sh --installcert -d ${domain} --ca-file /root/cert/ca.cer \
- --cert-file /root/cert/${domain}.cer --key-file /root/cert/${domain}.key \
- --fullchain-file /root/cert/fullchain.cer
+ ~/.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"
@@ -542,17 +603,18 @@ ssl_cert_issue_standalone() {
else
LOGI "install certs succeed,enable auto renew..."
fi
- ~/.acme.sh/acme.sh --upgrade --auto-upgrade
- if [ $? -ne 0 ]; then
- LOGE "auto renew failed,certs details:"
- ls -lah cert
- chmod 755 $certPath
- exit 1
- else
- LOGI "auto renew succeed,certs details:"
- ls -lah cert
- chmod 755 $certPath
- fi
+
+ ~/.acme.sh/acme.sh --upgrade --auto-upgrade
+ if [ $? -ne 0 ]; then
+ LOGE "auto renew failed, certs details:"
+ ls -lah cert/*
+ chmod 755 $certPath/*
+ exit 1
+ else
+ LOGI "auto renew succeed, certs details:"
+ ls -lah cert/*
+ chmod 755 $certPath/*
+ fi
}
@@ -573,13 +635,7 @@ ssl_cert_issue_by_cloudflare() {
CF_Domain=""
CF_GlobalKey=""
CF_AccountEmail=""
- certPath=/root/cert
- if [ ! -d "$certPath" ]; then
- mkdir $certPath
- else
- rm -rf $certPath
- mkdir $certPath
- fi
+
LOGD "please input your domain:"
read -p "Input your domain here:" CF_Domain
LOGD "your domain is:${CF_Domain},check it..."
@@ -593,6 +649,16 @@ ssl_cert_issue_by_cloudflare() {
else
LOGI "your domain is ready for issuing cert now..."
fi
+
+ #create a directory for install cert
+ certPath="/root/cert/${CF_Domain}"
+ if [ ! -d "$certPath" ]; then
+ mkdir -p "$certPath"
+ else
+ rm -rf "$certPath"
+ mkdir -p "$certPath"
+ fi
+
LOGD "please inout your cloudflare global API key:"
read -p "Input your key here:" CF_GlobalKey
LOGD "your cloudflare global API key is:${CF_GlobalKey}"
@@ -611,34 +677,72 @@ ssl_cert_issue_by_cloudflare() {
LOGE "issue cert failed,exit"
rm -rf ~/.acme.sh/${CF_Domain}
exit 1
- else
- 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
- if [ $? -ne 0 ]; then
- LOGE "install cert failed,exit"
- rm -rf ~/.acme.sh/${CF_Domain}
- exit 1
- else
- LOGI "Certificate installed Successfully,Turning on automatic updates..."
- fi
- ~/.acme.sh/acme.sh --upgrade --auto-upgrade
- if [ $? -ne 0 ]; then
- LOGE "Auto update setup Failed, script exiting..."
- ls -lah cert
- chmod 755 $certPath
- exit 1
- else
- LOGI "The certificate is installed and auto-renewal is turned on, Specific information is as follows"
- ls -lah cert
- chmod 755 $certPath
- fi
+ else
+ LOGI "Certificate issued Successfully, Installing..."
+ fi
+ ~/.acme.sh/acme.sh --installcert -d ${CF_Domain} -d *.${CF_Domain} \
+ --key-file /root/cert/${CF_Domain}/privkey.pem \
+ --fullchain-file /root/cert/${CF_Domain}/fullchain.pem
+
+ if [ $? -ne 0 ]; then
+ LOGE "install cert failed,exit"
+ rm -rf ~/.acme.sh/${CF_Domain}
+ exit 1
+ else
+ LOGI "Certificate installed Successfully,Turning on automatic updates..."
+ fi
+ ~/.acme.sh/acme.sh --upgrade --auto-upgrade
+ if [ $? -ne 0 ]; then
+ LOGE "auto renew failed, certs details:"
+ ls -lah cert/*
+ chmod 755 $certPath/*
+ exit 1
+ else
+ LOGI "auto renew succeed, certs details:"
+ ls -lah cert/*
+ chmod 755 $certPath/*
+ fi
else
show_menu
fi
}
+google_recaptcha() {
+ curl -O https://raw.githubusercontent.com/jinwyp/one_click_script/master/install_kernel.sh && chmod +x ./install_kernel.sh && ./install_kernel.sh
+ echo ""
+ before_show_menu
+}
+
+run_speedtest() {
+ # Check if Speedtest is already installed
+ if ! command -v speedtest &> /dev/null; then
+ # If not installed, install it
+ if command -v dnf &> /dev/null; then
+ sudo dnf install -y curl
+ curl -s https://install.speedtest.net/app/cli/install.rpm.sh | sudo bash
+ sudo dnf install -y speedtest
+ elif command -v yum &> /dev/null; then
+ sudo yum install -y curl
+ curl -s https://install.speedtest.net/app/cli/install.rpm.sh | sudo bash
+ sudo yum install -y speedtest
+ elif command -v apt-get &> /dev/null; then
+ sudo apt-get update && sudo apt-get install -y curl
+ curl -s https://install.speedtest.net/app/cli/install.deb.sh | sudo bash
+ sudo apt-get install -y speedtest
+ elif command -v apt &> /dev/null; then
+ sudo apt update && sudo apt install -y curl
+ curl -s https://install.speedtest.net/app/cli/install.deb.sh | sudo bash
+ sudo apt install -y speedtest
+ else
+ echo "Error: Package manager not found. You may need to install Speedtest manually."
+ return 1
+ fi
+ fi
+
+ # Run Speedtest
+ speedtest
+}
+
+
show_usage() {
echo "x-ui control menu usages: "
@@ -681,10 +785,14 @@ show_menu() {
${green}14.${plain} Disabel x-ui On System Startup
————————————————
${green}15.${plain} Enable BBR
- ${green}16.${plain} Issuse Certs
+ ${green}16.${plain} Apply for an SSL Certificate
+ ${green}17.${plain} Update Geo Files
+ ${green}18.${plain} Active Firewall and open ports
+ ${green}19.${plain} Fixing Google reCAPTCHA
+ ${green}20.${plain} Speedtest by Ookla
"
show_status
- echo && read -p "Please enter your selection [0-16]: " num
+ echo && read -p "Please enter your selection [0-20]: " num
case "${num}" in
0)
@@ -738,8 +846,20 @@ show_menu() {
16)
ssl_cert_issue
;;
+ 17)
+ update_geo
+ ;;
+ 18)
+ open_ports
+ ;;
+ 19)
+ google_recaptcha
+ ;;
+ 20)
+ run_speedtest
+ ;;
*)
- LOGE "Please enter the correct number [0-16]"
+ LOGE "Please enter the correct number [0-20]"
;;
esac
}