上传文件至 /

This commit is contained in:
2025-11-30 15:38:12 +08:00
parent 9d1fae41e3
commit a19fc13c38

678
install.sh Normal file
View File

@@ -0,0 +1,678 @@
set -e
SCRIPT_VERSION="V1.0.0"
xray_config_path="/usr/local/etc/xray/config.json"
xray_binary_path="/usr/local/bin/xray"
xray_install_script_url="https://github.com/XTLS/Xray-install/raw/main/install-release.sh"
xray_status_info=""
is_quiet=false
PKG_MANAGER=""
C_RESET='\033[0m'
C_RED='\033[0;31m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[0;33m'
C_BLUE='\033[0;34m'
C_PURPLE='\033[0;35m'
C_CYAN='\033[0;36m'
if [ -t 1 ]; then
use_color=true
else
use_color=false
fi
cecho() {
local color_name="$1"
local message="$2"
if [ "$use_color" = true ] && [ -n "$color_name" ]; then
echo -e "${color_name}${message}${C_RESET}"
else
echo "$message"
fi
}
error() {
cecho "$C_RED" "[✖] $1" >&2
}
info() {
if [ "$is_quiet" = false ]; then
cecho "$C_BLUE" "[!] $1" >&2
fi
}
success() {
if [ "$is_quiet" = false ]; then
cecho "$C_GREEN" "[✔] $1" >&2
fi
}
get_public_ip_v4() {
local ip
local sources=(
"https://api-ipv4.ip.sb/ip"
"https://api.ipify.org"
"https://ip.seeip.org"
)
for source in "${sources[@]}"; do
ip=$(curl -4s --max-time 5 "$source" 2>/dev/null)
if echo "$ip" | grep -qE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'; then
echo "$ip"
return
fi
done
echo ""
}
get_public_ip_v6() {
local ip
local sources=(
"https://api-ipv6.ip.sb/ip"
"https://api64.ipify.org"
)
for source in "${sources[@]}"; do
ip=$(curl -6s --max-time 5 "$source" 2>/dev/null)
if echo "$ip" | grep -q ':'; then
echo "$ip"
return
fi
done
echo ""
}
execute_official_script() {
local args="$1"
local script_content
info "正在下载官方安装脚本..."
script_content=$(curl -sL "$xray_install_script_url")
if [[ -z "$script_content" || ! "$script_content" =~ "install-release" ]]; then
error "下载 Xray 官方安装脚本失败或内容异常!请检查网络连接。"
return 1
fi
info "正在执行官方安装脚本 ( $args )..."
echo "$script_content" | bash -s -- $args
}
check_xray_version() {
if [ ! -f "$xray_binary_path" ]; then
return 1
fi
if ! $xray_binary_path help 2>/dev/null | grep -q "vlessenc"; then
return 1
fi
return 0
}
check_os_and_dependencies() {
info "正在检查操作系统和依赖..."
if command -v apt >/dev/null 2>&1; then
PKG_MANAGER="apt"
elif command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
elif command -v yum >/dev/null 2>&1; then
PKG_MANAGER="yum"
else
error "错误: 未知的包管理器, 此脚本仅支持 apt, dnf, yum."
exit 1
fi
if ! command -v jq >/dev/null 2>&1 || ! command -v curl >/dev/null 2>&1; then
info "检测到缺失的依赖 (jq/curl),正在尝试自动安装..."
case "$PKG_MANAGER" in
apt)
apt-get update >/dev/null 2>&1
apt-get install -y jq curl >/dev/null 2>&1
;;
dnf | yum)
"$PKG_MANAGER" install -y jq curl >/dev/null 2>&1
;;
esac
if ! command -v jq >/dev/null 2>&1 || ! command -v curl >/dev/null 2>&1; then
error "依赖 (jq/curl) 自动安装失败。请手动安装后重试。"
exit 1
fi
success "依赖已成功安装。"
fi
}
pre_check() {
if [ "$(id -u)" != "0" ]; then
error "错误: 您必须以root用户身份运行此脚本"
exit 1
fi
check_os_and_dependencies
}
check_xray_status() {
if [ ! -f "$xray_binary_path" ]; then
xray_status_info="$(cecho "$C_YELLOW" "Xray 状态: 未安装")"
return
fi
local xray_version=$($xray_binary_path version 2>/dev/null | head -n 1 | awk '{print $2}' || echo "未知")
local service_status
if systemctl is-active --quiet xray 2>/dev/null; then
service_status="$(cecho "$C_GREEN" "运行中")"
else
service_status="$(cecho "$C_RED" "未运行")"
fi
local encryption_support
if check_xray_version; then
encryption_support=" | $(cecho "$C_GREEN" "支持 VLESS Encryption")"
else
encryption_support=" | $(cecho "$C_RED" "不支持 VLESS Encryption")"
fi
xray_status_info="Xray 状态: $(cecho "$C_GREEN" "已安装") | ${service_status} | 版本: $(cecho "$C_CYAN" "$xray_version")${encryption_support}"
}
is_valid_port() {
local port="$1"
if echo "$port" | grep -q '^[0-9]\+$' && [ "$port" -ge 1 ] && [ "$port" -le 65535 ]; then
return 0
else
return 1
fi
}
generate_uuid() {
if [ -f "$xray_binary_path" ] && [ -x "$xray_binary_path" ]; then
$xray_binary_path uuid
else
cat /proc/sys/kernel/random/uuid
fi
}
generate_vless_encryption_config() {
info "正在生成 VLESS Encryption 配置 (native + 0-RTT + ML-KEM-768)..."
local vlessenc_output
vlessenc_output=$($xray_binary_path vlessenc 2>/dev/null)
if [ -z "$vlessenc_output" ]; then
error "生成 VLESS Encryption 配置失败"
return 1
fi
local decryption_config=""
local encryption_config=""
local in_mlkem_section=false
local parsing_encryption=false
while IFS= read -r line; do
if [ "$in_mlkem_section" = true ] && [[ "$line" != *'"decryption":'* ]] && [[ "$line" != *'"encryption":'* ]] && [[ "$parsing_encryption" = false ]] && [ -n "$decryption_config" ] && [ -n "$encryption_config" ]; then
if [[ ! "$line" =~ ^[[:space:]]*"\"" ]]; then
break
fi
fi
if [[ "$line" == *"Authentication: ML-KEM-768, Post-Quantum"* ]]; then
in_mlkem_section=true
continue
fi
if [ "$in_mlkem_section" = false ]; then
continue
fi
if [ "$parsing_encryption" = true ]; then
encryption_config+="${line}"
if [[ "$line" == *"\"" ]]; then
parsing_encryption=false
encryption_config=$(echo "$encryption_config" | sed 's/"$//' | tr -d '[:space:]')
fi
continue
fi
if [[ "$line" == *'"decryption":'* ]]; then
decryption_config=$(echo "$line" | sed 's/.*"decryption": "\([^"]*\)".*/\1/')
continue
fi
if [[ "$line" == *'"encryption":'* ]]; then
parsing_encryption=true
encryption_config=$(echo "$line" | sed 's/.*"encryption": "\([^"]*\).*/\1/')
if [[ "$line" == *"\"" ]]; then
parsing_encryption=false
encryption_config=$(echo "$encryption_config" | sed 's/"$//' | tr -d '[:space:]')
fi
fi
done <<< "$vlessenc_output"
if [ -z "$decryption_config" ] || [ -z "$encryption_config" ]; then
error "无法解析 VLESS Encryption 配置。请确保您的 Xray 版本支持此功能。"
return 1
fi
echo "${decryption_config}|${encryption_config}"
}
install_xray() {
if [ -f "$xray_binary_path" ]; then
if ! check_xray_version; then
info "检测到已安装的 Xray 版本不支持 VLESS Encryption需要更新。"
else
info "检测到 Xray 已安装。继续操作将覆盖现有配置。"
fi
echo -n "是否继续?[y/N]: "
read -r confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
info "操作已取消。"
return
fi
fi
info "开始配置 VLESS Encryption (native + 0-RTT + ML-KEM-768)..."
local port uuid
while true; do
echo -n "请输入端口 [1-65535] (默认: 443): "
read -r port
[ -z "$port" ] && port=443
if is_valid_port "$port"; then
break
else
error "端口无效请输入一个1-65535之间的数字。"
fi
done
echo -n "请输入UUID (留空将默认生成随机UUID): "
read -r uuid
if [ -z "$uuid" ]; then
uuid=$(generate_uuid)
info "已为您生成随机UUID: ${uuid}"
fi
run_install "$port" "$uuid"
}
update_xray() {
if [ ! -f "$xray_binary_path" ]; then
error "错误: Xray 未安装,无法执行更新。请先选择安装选项。"
return
fi
info "正在检查最新版本..."
local current_version latest_version
current_version=$($xray_binary_path version | head -n 1 | awk '{print $2}' | sed 's/v//')
latest_version=$(curl -s https://api.github.com/repos/XTLS/Xray-core/releases/latest | jq -r '.tag_name' | sed 's/v//' 2>/dev/null || echo "")
if [ -z "$latest_version" ]; then
error "获取最新版本号失败,请检查网络或稍后再试。"
return
fi
info "当前版本: ${current_version},最新版本: ${latest_version}"
if [ "$current_version" = "$latest_version" ] && check_xray_version; then
success "您的 Xray 已是最新版本且支持 VLESS Encryption无需更新。"
return
fi
info "开始更新..."
if ! execute_official_script "install"; then
error "Xray 核心更新失败!"
return
fi
info "正在更新 GeoIP 和 GeoSite 数据文件..."
execute_official_script "install-geodata"
if ! restart_xray; then return; fi
success "Xray 更新成功!"
}
restart_xray() {
if [ ! -f "$xray_binary_path" ]; then
error "错误: Xray 未安装,无法重启。"
return 1
fi
info "正在重启 Xray 服务..."
if ! systemctl restart xray; then
error "错误: Xray 服务重启失败, 请使用菜单 5 查看日志检查具体原因。"
return 1
fi
sleep 1
if ! systemctl is-active --quiet xray; then
error "错误: Xray 服务启动失败, 请使用菜单 5 查看日志检查具体原因。"
return 1
fi
success "Xray 服务已成功重启!"
return 0
}
uninstall_xray() {
if [ ! -f "$xray_binary_path" ]; then
error "错误: Xray 未安装,无需卸载。"
return
fi
echo -n "您确定要卸载 Xray 吗?这将删除所有相关文件。[Y/n]: "
read -r confirm
if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]; then
info "卸载操作已取消。"
return
fi
info "正在卸载 Xray..."
if execute_official_script "remove --purge"; then
rm -f ~/xray_vless_encryption_link.txt ~/xray_encryption_info.txt
success "Xray 已成功卸载。"
else
error "Xray 卸载失败!"
return 1
fi
}
view_xray_log() {
if [ ! -f "$xray_binary_path" ]; then
error "错误: Xray 未安装,无法查看日志。"
return
fi
info "正在显示 Xray 实时日志... 按 Ctrl+C 退出。"
journalctl -u xray -f --no-pager
}
modify_config() {
if [ ! -f "$xray_config_path" ]; then
error "错误: Xray 未安装,无法修改配置。"
return
fi
info "读取当前配置..."
local current_port current_uuid
current_port=$(jq -r '.inbounds[0].port' "$xray_config_path")
current_uuid=$(jq -r '.inbounds[0].settings.clients[0].id' "$xray_config_path")
info "请输入新配置,直接回车则保留当前值。"
local port uuid
while true; do
echo -n "端口 (当前: ${current_port}): "
read -r port
[ -z "$port" ] && port=$current_port
if is_valid_port "$port"; then
break
else
error "端口无效请输入一个1-65535之间的数字。"
fi
done
echo -n "UUID (当前: ${current_uuid}): "
read -r uuid
[ -z "$uuid" ] && uuid=$current_uuid
local encryption_info
encryption_info=$(generate_vless_encryption_config)
if [ -z "$encryption_info" ]; then
return 1
fi
local decryption_config encryption_config
decryption_config=$(echo "$encryption_info" | cut -d'|' -f1)
encryption_config=$(echo "$encryption_info" | cut -d'|' -f2)
write_config "$port" "$uuid" "$decryption_config" "$encryption_config"
if ! restart_xray; then return; fi
success "配置修改成功!"
view_subscription_info
}
view_subscription_info() {
if [ ! -f "$xray_config_path" ]; then
error "错误: 配置文件不存在, 请先安装。"
return
fi
local ip4 ip6
ip4=$(get_public_ip_v4)
ip6=$(get_public_ip_v6)
if [ -z "$ip4" ] && [ -z "$ip6" ]; then
error "无法获取任何公网 IP 地址 (IPv4 或 IPv6),无法生成订阅链接。"
return 1
fi
local display_ip=${ip4:-$ip6}
if [ -z "$display_ip" ]; then
error "无法获取有效的公网IP地址。"
return 1
fi
local uuid port encryption
uuid=$(jq -r '.inbounds[0].settings.clients[0].id' "$xray_config_path")
port=$(jq -r '.inbounds[0].port' "$xray_config_path")
if [ ! -f ~/xray_encryption_info.txt ]; then
error "缺少客户端 encryption 信息文件,请重新安装以修复。"
return
fi
encryption=$(cat ~/xray_encryption_info.txt 2>/dev/null)
if [ -z "$encryption" ]; then
error "缺少客户端 encryption 信息,可能是旧版配置,请重新安装以修复。"
return
fi
local link_name_encoded
link_name_encoded="$(hostname)%20VLESS-E"
local address_for_url=$display_ip
if [[ $display_ip == *":"* ]]; then
address_for_url="[${display_ip}]"
fi
local vless_url="vless://${uuid}@${address_for_url}:${port}?encryption=${encryption}&flow=xtls-rprx-vision&type=tcp&security=none#${link_name_encoded}"
if [ "$is_quiet" = true ]; then
echo "${vless_url}"
else
echo "${vless_url}" > ~/xray_vless_encryption_link.txt
echo "----------------------------------------------------------------"
cecho "$C_CYAN" " --- Xray VLESS-Encryption 订阅信息 --- "
echo " 名称: $(cecho "$C_GREEN" "$(hostname) VLESS-E")"
if [ -n "$ip4" ]; then
echo " 地址(IPv4): $(cecho "$C_GREEN" "$ip4")"
fi
if [ -n "$ip6" ]; then
echo " 地址(IPv6): $(cecho "$C_GREEN" "$ip6")"
fi
echo " 端口: $(cecho "$C_GREEN" "$port")"
echo " UUID: $(cecho "$C_GREEN" "$uuid")"
echo " 协议: $(cecho "$C_YELLOW" "VLESS Encryption (native + 0-RTT + ML-KEM-768)")"
echo " 流控: $(cecho "$C_YELLOW" "xtls-rprx-vision")"
echo "----------------------------------------------------------------"
cecho "$C_GREEN" " 订阅链接 (已保存到 ~/xray_vless_encryption_link.txt): "
echo
cecho "$C_GREEN" "$vless_url"
echo "----------------------------------------------------------------"
fi
}
write_config() {
local port="$1" uuid="$2" decryption_config="$3" encryption_config="$4"
echo "$encryption_config" > ~/xray_encryption_info.txt
jq -n \
--argjson port "$port" \
--arg uuid "$uuid" \
--arg decryption "$decryption_config" \
--arg flow "xtls-rprx-vision" \
'{
"log": {"loglevel": "warning"},
"inbounds": [{
"listen": "::",
"port": $port,
"protocol": "vless",
"settings": {
"clients": [{"id": $uuid, "flow": $flow}],
"decryption": $decryption
}
}],
"outbounds": [{
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv4v6"
}
}]
}' > "$xray_config_path"
chmod 644 "$xray_config_path"
chown root:root "$xray_config_path"
}
run_install() {
local port="$1" uuid="$2"
info "正在下载并安装 Xray 核心..."
if ! execute_official_script "install"; then
error "Xray 核心安装失败!请检查网络连接。"
exit 1
fi
info "正在安装/更新 GeoIP 和 GeoSite 数据文件..."
execute_official_script "install-geodata"
if ! check_xray_version; then
error "安装的 Xray 版本不支持 VLESS Encryption请检查安装的版本。"
exit 1
fi
local encryption_info
encryption_info=$(generate_vless_encryption_config)
if [ -z "$encryption_info" ]; then
error "生成 VLESS Encryption 配置失败!"
exit 1
fi
local decryption_config encryption_config
decryption_config=$(echo "$encryption_info" | cut -d'|' -f1)
encryption_config=$(echo "$encryption_info" | cut -d'|' -f2)
info "正在写入 Xray 配置文件..."
write_config "$port" "$uuid" "$decryption_config" "$encryption_config"
if ! restart_xray; then exit 1; fi
success "Xray VLESS Encryption 安装/配置成功!"
view_subscription_info
}
press_any_key_to_continue() {
echo ""
cecho "$C_YELLOW" "按任意键返回主菜单..."
read -r -n 1 -s
}
main_menu() {
while true; do
clear
cecho "$C_CYAN" "--- Xray VLESS-Encryption 一键安装管理脚本 v${SCRIPT_VERSION} ---"
echo
check_xray_status
echo " ${xray_status_info}"
cecho "$C_GREEN" "─────────────────────────────────────────────────────"
cecho "$C_GREEN" " 1. 安装/重装 Xray (VLESS-Encryption)"
cecho "$C_GREEN" " 2. 更新 Xray"
cecho "$C_GREEN" " 3. 重启 Xray"
cecho "$C_GREEN" " 4. 卸载 Xray"
cecho "$C_GREEN" " 5. 查看 Xray 日志"
cecho "$C_GREEN" " 6. 修改节点配置"
cecho "$C_GREEN" " 7. 查看订阅信息"
cecho "$C_GREEN" "─────────────────────────────────────────────────────"
cecho "$C_RED" " 0. 退出脚本"
cecho "$C_GREEN" "─────────────────────────────────────────────────────"
cecho "$C_YELLOW" " 注意: 使用 native + 0-RTT + ML-KEM-768 + xtls-rprx-vision"
cecho "$C_GREEN" "─────────────────────────────────────────────────────"
echo -n " 请输入选项 [0-7]: "
read -r choice
local needs_pause=true
case $choice in
1) install_xray ;;
2) update_xray ;;
3) restart_xray ;;
4) uninstall_xray ;;
5) view_xray_log; needs_pause=false ;;
6) modify_config ;;
7) view_subscription_info ;;
0) success "感谢使用!"; exit 0 ;;
*) error "无效选项,请输入 0-7 之间的数字。" ;;
esac
if [ "$needs_pause" = true ]; then
press_any_key_to_continue
fi
done
}
main() {
pre_check
if [ $# -gt 0 ] && [ "$1" = "install" ]; then
shift
local port="" uuid=""
while [ $# -gt 0 ]; do
case "$1" in
--port) port="$2"; shift 2 ;;
--uuid) uuid="$2"; shift 2 ;;
--quiet|-q) is_quiet=true; shift ;;
*) error "未知参数: $1"; exit 1 ;;
esac
done
[ -z "$port" ] && port=443
if [ -z "$uuid" ]; then
uuid=$(generate_uuid)
fi
if ! is_valid_port "$port"; then
error "参数无效。请检查端口格式。"
exit 1
fi
run_install "$port" "$uuid"
else
main_menu
fi
}
show_help() {
echo "Xray VLESS-Encryption 一键安装管理脚本 $SCRIPT_VERSION"
echo
echo "用法:"
echo " $0 # 交互式菜单"
echo " $0 install [选项] # 静默安装"
echo
echo "安装选项:"
echo " --port <端口> # 监听端口 (默认: 443)"
echo " --uuid <UUID> # 用户UUID (默认: 自动生成)"
echo " --quiet, -q # 静默模式,只输出订阅链接"
echo
echo "固定配置 (最优设置):"
echo " 协议: VLESS Encryption"
echo " 外观: native (原生外观性能最佳支持XTLS完全穿透)"
echo " RTT: 0rtt (密钥复用600秒性能优化)"
echo " 认证: mlkem768 (ML-KEM-768 抗量子加密)"
echo " 流控: xtls-rprx-vision (推荐的流控方式)"
echo
echo "示例:"
echo " $0 install --port 8443"
echo " $0 install --quiet --uuid 12345678-1234-1234-1234-123456789abc"
echo
}
if [ $# -gt 0 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; then
show_help
exit 0
fi
main "$@"