Self-signed SSL (#3611)

This commit is contained in:
Sanaei
2025-12-28 00:03:33 +01:00
committed by GitHub
parent 4c797dc154
commit 69ccdba734
3 changed files with 1136 additions and 43 deletions
+236 -17
View File
@@ -213,6 +213,57 @@ gen_random_string() {
echo "$random_string"
}
# Generate and configure a self-signed SSL certificate
setup_self_signed_certificate() {
local name="$1" # domain or IP to place in SAN
local certDir="/root/cert/selfsigned"
LOGI "Generating a self-signed certificate (not publicly trusted)..."
mkdir -p "$certDir"
local sanExt=""
if [[ "$name" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ || "$name" =~ : ]]; then
sanExt="IP:${name}"
else
sanExt="DNS:${name}"
fi
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout "${certDir}/privkey.pem" \
-out "${certDir}/fullchain.pem" \
-subj "/CN=${name}" \
-addext "subjectAltName=${sanExt}" >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
local tmpCfg="${certDir}/openssl.cnf"
cat > "$tmpCfg" <<EOF
[req]
distinguished_name=req_distinguished_name
req_extensions=v3_req
[req_distinguished_name]
[v3_req]
subjectAltName=${sanExt}
EOF
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
-keyout "${certDir}/privkey.pem" \
-out "${certDir}/fullchain.pem" \
-subj "/CN=${name}" \
-config "$tmpCfg" -extensions v3_req >/dev/null 2>&1
rm -f "$tmpCfg"
fi
if [[ ! -f "${certDir}/fullchain.pem" || ! -f "${certDir}/privkey.pem" ]]; then
LOGE "Failed to generate self-signed certificate"
return 1
fi
chmod 755 ${certDir}/* >/dev/null 2>&1
/usr/local/x-ui/x-ui cert -webCert "${certDir}/fullchain.pem" -webCertKey "${certDir}/privkey.pem" >/dev/null 2>&1
LOGI "Self-signed certificate configured. Browsers will show a warning."
return 0
}
reset_webbasepath() {
echo -e "${yellow}Resetting Web Base Path${plain}"
@@ -256,7 +307,7 @@ 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=$(/usr/local/x-ui/x-ui setting -getCert true | grep -Eo 'cert: .+' | awk '{print $2}')
local existing_cert=$(/usr/local/x-ui/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)
@@ -271,7 +322,22 @@ check_config() {
echo -e "${green}Access URL: https://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
fi
else
echo -e "${green}Access URL: http://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
echo -e "${red}⚠ WARNING: No SSL certificate configured!${plain}"
read -rp "Generate a self-signed SSL certificate now? [y/N]: " gen_self
if [[ "$gen_self" == "y" || "$gen_self" == "Y" ]]; then
stop >/dev/null 2>&1
setup_self_signed_certificate "${server_ip}"
if [[ $? -eq 0 ]]; then
restart >/dev/null 2>&1
echo -e "${green}Access URL: https://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
else
LOGE "Self-signed SSL setup failed."
echo -e "${yellow}You can try again via option 18 (SSL Certificate Management).${plain}"
fi
else
echo -e "${yellow}Access URL: http://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
echo -e "${yellow}For security, please configure SSL certificate using option 18 (SSL Certificate Management)${plain}"
fi
fi
}
@@ -958,6 +1024,7 @@ ssl_cert_issue_main() {
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}\t6.${plain} Auto SSL for Server IP"
echo -e "${green}\t0.${plain} Back to Main Menu"
read -rp "Choose an option: " choice
@@ -1051,6 +1118,16 @@ ssl_cert_issue_main() {
fi
ssl_cert_issue_main
;;
6)
echo -e "${yellow}Automatic SSL Certificate for Server IP${plain}"
echo -e "This will automatically obtain and configure an SSL certificate for your server's IP address."
echo -e "${yellow}Note: Let's Encrypt supports IP certificates. Make sure port 80 is open.${plain}"
confirm "Do you want to proceed?" "y"
if [[ $? == 0 ]]; then
ssl_cert_issue_for_ip
fi
ssl_cert_issue_main
;;
*)
echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
@@ -1059,6 +1136,134 @@ ssl_cert_issue_main() {
esac
}
ssl_cert_issue_for_ip() {
LOGI "Starting automatic SSL certificate generation for server IP..."
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
local existing_port=$(/usr/local/x-ui/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
if [ -z "$server_ip" ]; then
LOGE "Failed to get server IP address"
return 1
fi
LOGI "Server IP detected: ${server_ip}"
# check for acme.sh first
if ! command -v ~/.acme.sh/acme.sh &>/dev/null; then
LOGI "acme.sh not found, installing..."
install_acme
if [ $? -ne 0 ]; then
LOGE "Failed to install acme.sh"
return 1
fi
fi
# install socat
case "${release}" in
ubuntu | debian | armbian)
apt-get update >/dev/null 2>&1 && apt-get install socat -y >/dev/null 2>&1
;;
fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
;;
centos)
if [[ "${VERSION_ID}" =~ ^7 ]]; then
yum -y update >/dev/null 2>&1 && yum -y install socat >/dev/null 2>&1
else
dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
fi
;;
arch | manjaro | parch)
pacman -Sy --noconfirm socat >/dev/null 2>&1
;;
opensuse-tumbleweed | opensuse-leap)
zypper refresh >/dev/null 2>&1 && zypper -q install -y socat >/dev/null 2>&1
;;
alpine)
apk add socat curl openssl >/dev/null 2>&1
;;
*)
LOGW "Unsupported OS for automatic socat installation"
;;
esac
# check if certificate already exists for this IP
local currentCert=$(~/.acme.sh/acme.sh --list | tail -1 | awk '{print $1}')
if [ "${currentCert}" == "${server_ip}" ]; then
LOGI "Certificate already exists for IP: ${server_ip}"
certPath="/root/cert/${server_ip}"
else
# create directory for certificate
certPath="/root/cert/${server_ip}"
if [ ! -d "$certPath" ]; then
mkdir -p "$certPath"
else
rm -rf "$certPath"
mkdir -p "$certPath"
fi
# Use port 80 for certificate issuance
local WebPort=80
LOGI "Using port ${WebPort} to issue certificate for IP: ${server_ip}"
LOGI "Make sure port ${WebPort} is open and not in use..."
# issue the certificate for IP
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
~/.acme.sh/acme.sh --issue -d ${server_ip} --listen-v6 --standalone --httpport ${WebPort} --force
if [ $? -ne 0 ]; then
LOGE "Failed to issue certificate for IP: ${server_ip}"
LOGE "Make sure port ${WebPort} is open and the server is accessible from the internet"
rm -rf ~/.acme.sh/${server_ip}
return 1
else
LOGI "Certificate issued successfully for IP: ${server_ip}"
fi
# install the certificate
~/.acme.sh/acme.sh --installcert -d ${server_ip} \
--key-file /root/cert/${server_ip}/privkey.pem \
--fullchain-file /root/cert/${server_ip}/fullchain.pem \
--reloadcmd "x-ui restart"
if [ $? -ne 0 ]; then
LOGE "Failed to install certificate"
rm -rf ~/.acme.sh/${server_ip}
return 1
else
LOGI "Certificate installed successfully"
fi
# enable auto-renew
~/.acme.sh/acme.sh --upgrade --auto-upgrade >/dev/null 2>&1
chmod 755 $certPath/*
fi
# Set certificate paths for the panel
local webCertFile="/root/cert/${server_ip}/fullchain.pem"
local webKeyFile="/root/cert/${server_ip}/privkey.pem"
if [[ -f "$webCertFile" && -f "$webKeyFile" ]]; then
/usr/local/x-ui/x-ui cert -webCert "$webCertFile" -webCertKey "$webKeyFile"
LOGI "Certificate configured for panel"
LOGI " - Certificate File: $webCertFile"
LOGI " - Private Key File: $webKeyFile"
echo -e "${green}Access URL: https://${server_ip}:${existing_port}${existing_webBasePath}${plain}"
LOGI "Panel will restart to apply SSL certificate..."
restart
return 0
else
LOGE "Certificate files not found after installation"
return 1
fi
}
ssl_cert_issue() {
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
local existing_port=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
@@ -1072,33 +1277,32 @@ ssl_cert_issue() {
fi
fi
# install socat second
# install socat
case "${release}" in
ubuntu | debian | armbian)
apt-get update && apt-get install socat -y
apt-get update >/dev/null 2>&1 && apt-get install socat -y >/dev/null 2>&1
;;
fedora | amzn | virtuozzo | rhel | almalinux | rocky | ol)
dnf -y update && dnf -y install socat
dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
;;
centos)
if [[ "${VERSION_ID}" =~ ^7 ]]; then
yum -y update && yum -y install socat
else
dnf -y update && dnf -y install socat
fi
if [[ "${VERSION_ID}" =~ ^7 ]]; then
yum -y update >/dev/null 2>&1 && yum -y install socat >/dev/null 2>&1
else
dnf -y update >/dev/null 2>&1 && dnf -y install socat >/dev/null 2>&1
fi
;;
arch | manjaro | parch)
pacman -Sy --noconfirm socat
pacman -Sy --noconfirm socat >/dev/null 2>&1
;;
opensuse-tumbleweed | opensuse-leap)
zypper refresh && zypper -q install -y socat
opensuse-tumbleweed | opensuse-leap)
zypper refresh >/dev/null 2>&1 && zypper -q install -y socat >/dev/null 2>&1
;;
alpine)
apk add socat curl openssl
apk add socat curl openssl >/dev/null 2>&1
;;
*)
echo -e "${red}Unsupported operating system. Please check the script and install the necessary packages manually.${plain}\n"
exit 1
LOGW "Unsupported OS for automatic socat installation"
;;
esac
if [ $? -ne 0 ]; then
@@ -1110,7 +1314,22 @@ ssl_cert_issue() {
# get the domain here, and we need to verify it
local domain=""
read -rp "Please enter your domain name: " domain
while true; do
read -rp "Please enter your domain name: " domain
domain="${domain// /}" # Trim whitespace
if [[ -z "$domain" ]]; then
LOGE "Domain name cannot be empty. Please try again."
continue
fi
if ! is_domain "$domain"; then
LOGE "Invalid domain format: ${domain}. Please enter a valid domain name."
continue
fi
break
done
LOGD "Your domain is: ${domain}, checking it..."
# check if there already exists a certificate