From 7f703f927ec26f77d91225b56efc76c2023cd64f Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Fri, 8 May 2026 00:51:28 +0200 Subject: [PATCH] fix(scripts): harden server-IP detection with multi-provider + manual fallback Try six IPv4 providers in turn, accept only HTTP 200 + IPv4-shaped body, and prompt the user to enter their IP if every provider fails. Co-Authored-By: Claude Opus 4.7 --- install.sh | 16 +++++++++-- update.sh | 22 +++++++++------ x-ui.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 99 insertions(+), 22 deletions(-) diff --git a/install.sh b/install.sh index 4a0ce55d..9eb1011b 100644 --- a/install.sh +++ b/install.sh @@ -678,13 +678,25 @@ config_after_install() { for ip_address in "${URL_lists[@]}"; do local response=$(curl -s -w "\n%{http_code}" --max-time 3 "${ip_address}" 2> /dev/null) local http_code=$(echo "$response" | tail -n1) - local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]') - if [[ "${http_code}" == "200" && -n "${ip_result}" ]]; then + local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]"') + if [[ "${http_code}" == "200" && "${ip_result}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then server_ip="${ip_result}" break fi done + if [[ -z "$server_ip" ]]; then + echo -e "${yellow}Could not auto-detect server IP from any provider.${plain}" + while [[ -z "$server_ip" ]]; do + read -rp "Please enter your server's public IPv4 address: " server_ip + server_ip="${server_ip// /}" + if [[ ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo -e "${red}Invalid IPv4 address. Please try again.${plain}" + server_ip="" + fi + done + fi + if [[ ${#existing_webBasePath} -lt 4 ]]; then if [[ "$existing_hasDefaultCredential" == "true" ]]; then local config_webBasePath=$(gen_random_string 18) diff --git a/update.sh b/update.sh index 8336518b..1c9f1ae9 100755 --- a/update.sh +++ b/update.sh @@ -711,13 +711,25 @@ config_after_update() { for ip_address in "${URL_lists[@]}"; do local response=$(curl -s -w "\n%{http_code}" --max-time 3 "${ip_address}" 2> /dev/null) local http_code=$(echo "$response" | tail -n1) - local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]') - if [[ "${http_code}" == "200" && -n "${ip_result}" ]]; then + local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]"') + if [[ "${http_code}" == "200" && "${ip_result}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then server_ip="${ip_result}" break fi done + if [[ -z "$server_ip" ]]; then + echo -e "${yellow}Could not auto-detect server IP from any provider.${plain}" + while [[ -z "$server_ip" ]]; do + read -rp "Please enter your server's public IPv4 address: " server_ip + server_ip="${server_ip// /}" + if [[ ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo -e "${red}Invalid IPv4 address. Please try again.${plain}" + server_ip="" + fi + done + fi + # Handle missing/short webBasePath if [[ ${#existing_webBasePath} -lt 4 ]]; then echo -e "${yellow}WebBasePath is missing or too short. Generating a new one...${plain}" @@ -737,12 +749,6 @@ config_after_update() { echo -e "${yellow}Let's Encrypt now supports both domains and IP addresses!${plain}" echo "" - if [[ -z "${server_ip}" ]]; then - echo -e "${red}Failed to detect server IP${plain}" - echo -e "${yellow}Please configure SSL manually using: x-ui${plain}" - return - fi - # Prompt and setup SSL (domain or IP) prompt_and_setup_ssl "${existing_port}" "${existing_webBasePath}" "${server_ip}" diff --git a/x-ui.sh b/x-ui.sh index 31ecc683..ce1dfea1 100644 --- a/x-ui.sh +++ b/x-ui.sh @@ -292,9 +292,35 @@ check_config() { local existing_webBasePath=$(echo "$info" | grep -Eo 'webBasePath: .+' | awk '{print $2}') local existing_port=$(echo "$info" | grep -Eo 'port: .+' | awk '{print $2}') local existing_cert=$(${xui_folder}/x-ui setting -getCert true | grep 'cert:' | awk -F': ' '{print $2}' | tr -d '[:space:]') - local server_ip=$(curl -s --max-time 3 https://api.ipify.org) - if [ -z "$server_ip" ]; then - server_ip=$(curl -s --max-time 3 https://4.ident.me) + local URL_lists=( + "https://api4.ipify.org" + "https://ipv4.icanhazip.com" + "https://v4.api.ipinfo.io/ip" + "https://ipv4.myexternalip.com/raw" + "https://4.ident.me" + "https://check-host.net/ip" + ) + local server_ip="" + for ip_address in "${URL_lists[@]}"; do + local response=$(curl -s -w "\n%{http_code}" --max-time 3 "${ip_address}" 2> /dev/null) + local http_code=$(echo "$response" | tail -n1) + local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]"') + if [[ "${http_code}" == "200" && "${ip_result}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + server_ip="${ip_result}" + break + fi + done + + if [[ -z "$server_ip" ]]; then + echo -e "${yellow}Could not auto-detect server IP from any provider.${plain}" + while [[ -z "$server_ip" ]]; do + read -rp "Please enter your server's public IPv4 address: " server_ip + server_ip="${server_ip// /}" + if [[ ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo -e "${red}Invalid IPv4 address. Please try again.${plain}" + server_ip="" + fi + done fi if [[ -n "$existing_cert" ]]; then @@ -1139,14 +1165,35 @@ ssl_cert_issue_for_ip() { local existing_port=$(${xui_folder}/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}') # Get server IP - local server_ip=$(curl -s --max-time 3 https://api.ipify.org) - if [ -z "$server_ip" ]; then - server_ip=$(curl -s --max-time 3 https://4.ident.me) - fi + local URL_lists=( + "https://api4.ipify.org" + "https://ipv4.icanhazip.com" + "https://v4.api.ipinfo.io/ip" + "https://ipv4.myexternalip.com/raw" + "https://4.ident.me" + "https://check-host.net/ip" + ) + local server_ip="" + for ip_address in "${URL_lists[@]}"; do + local response=$(curl -s -w "\n%{http_code}" --max-time 3 "${ip_address}" 2> /dev/null) + local http_code=$(echo "$response" | tail -n1) + local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]"') + if [[ "${http_code}" == "200" && "${ip_result}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + server_ip="${ip_result}" + break + fi + done - if [ -z "$server_ip" ]; then - LOGE "Failed to get server IP address" - return 1 + if [[ -z "$server_ip" ]]; then + LOGI "Could not auto-detect server IP from any provider." + while [[ -z "$server_ip" ]]; do + read -rp "Please enter your server's public IPv4 address: " server_ip + server_ip="${server_ip// /}" + if [[ ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + LOGE "Invalid IPv4 address. Please try again." + server_ip="" + fi + done fi LOGI "Server IP detected: ${server_ip}" @@ -2104,13 +2151,25 @@ SSH_port_forwarding() { for ip_address in "${URL_lists[@]}"; do local response=$(curl -s -w "\n%{http_code}" --max-time 3 "${ip_address}" 2> /dev/null) local http_code=$(echo "$response" | tail -n1) - local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]') - if [[ "${http_code}" == "200" && -n "${ip_result}" ]]; then + local ip_result=$(echo "$response" | head -n-1 | tr -d '[:space:]"') + if [[ "${http_code}" == "200" && "${ip_result}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then server_ip="${ip_result}" break fi done + if [[ -z "$server_ip" ]]; then + echo -e "${yellow}Could not auto-detect server IP from any provider.${plain}" + while [[ -z "$server_ip" ]]; do + read -rp "Please enter your server's public IPv4 address: " server_ip + server_ip="${server_ip// /}" + if [[ ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo -e "${red}Invalid IPv4 address. Please try again.${plain}" + server_ip="" + fi + done + fi + local existing_webBasePath=$(${xui_folder}/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}') local existing_port=$(${xui_folder}/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}') local existing_listenIP=$(${xui_folder}/x-ui setting -getListen true | grep -Eo 'listenIP: .+' | awk '{print $2}')