#!/usr/bin/env bash set -euo pipefail # ============================================ # Xray VPS 一键部署脚本 # 支持模式:reality (VLESS-Reality) / fast (VLESS TCP 无 TLS) # 适用于 Debian 11+ / Ubuntu 20.04+ # ============================================ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' log() { echo -e "${GREEN}[INFO]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } step() { echo -e "\n${CYAN}========== $* ==========${NC}"; } # ===== 使用说明 ===== usage() { echo "用法: bash deploy.sh [选项]" echo "" echo "选项:" echo " --mode reality VLESS-Reality 模式(默认,推荐,抗封锁)" echo " --mode fast VLESS TCP 模式(无 TLS,极速但易被检测)" echo " -h, --help 显示帮助" exit 0 } # ===== 解析参数 ===== MODE="reality" while [[ $# -gt 0 ]]; do case $1 in --mode) MODE="$2"; shift 2 ;; -h|--help) usage ;; *) error "未知参数: $1"; usage ;; esac done if [[ "$MODE" != "reality" && "$MODE" != "fast" ]]; then error "无效模式: $MODE(支持 reality / fast)" exit 1 fi # ===== 检查 root ===== if [ "$(id -u)" -ne 0 ]; then error "请使用 root 用户运行: sudo bash deploy.sh" exit 1 fi # ===== 加载现有配置(如存在)===== if [ -f .env ]; then sed -i 's/\r$//' .env set -a; source .env; set +a fi XRAY_PORT="${XRAY_PORT:-443}" # ===== 1. 安装 Xray ===== install_xray() { step "1/5 安装 Xray" if command -v xray &>/dev/null || [ -x /usr/local/bin/xray ]; then log "Xray 已安装: $(/usr/local/bin/xray version | head -1)" log "将更新到最新版本..." fi bash <(curl -fsSL https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh) log "Xray 安装完成: $(/usr/local/bin/xray version | head -1)" } # ===== 2. 生成密钥 ===== generate_keys() { step "2/5 生成密钥" XRAY_UUID=$(cat /proc/sys/kernel/random/uuid) log "UUID: ${XRAY_UUID}" if [ "$MODE" = "reality" ]; then local keys keys=$(/usr/local/bin/xray x25519 2>&1) XRAY_PRIVATE_KEY=$(echo "$keys" | grep -i 'private' | awk -F': ' '{print $2}' | tr -d '[:space:]') XRAY_PUBLIC_KEY=$(echo "$keys" | grep -i 'public' | awk -F': ' '{print $2}' | tr -d '[:space:]') XRAY_SHORT_ID=$(openssl rand -hex 8) if [ -z "$XRAY_PRIVATE_KEY" ] || [ -z "$XRAY_PUBLIC_KEY" ]; then error "密钥生成失败!xray x25519 输出:" echo "$keys" exit 1 fi log "x25519 密钥对已生成" log "ShortId: ${XRAY_SHORT_ID}" fi } # ===== 3. 选择 Reality 伪装目标 ===== select_reality_dest() { if [ "$MODE" != "reality" ]; then return fi step "3/5 选择 Reality 伪装目标" local candidates=("www.microsoft.com" "dl.google.com" "www.apple.com" "www.amazon.com") REALITY_DEST="${REALITY_DEST:-}" REALITY_SNI="${REALITY_SNI:-}" if [ -n "$REALITY_DEST" ] && [ -n "$REALITY_SNI" ]; then log "使用 .env 中指定的伪装目标: ${REALITY_DEST}" return fi local best_dest="www.microsoft.com" local best_ms=9999 for site in "${candidates[@]}"; do local ms ms=$(curl -so /dev/null -w '%{time_connect}' --max-time 3 "https://${site}" 2>/dev/null \ | awk '{printf "%d", $1*1000}') || true if [ -n "$ms" ] && [ "$ms" -lt "$best_ms" ] 2>/dev/null; then best_ms=$ms best_dest=$site fi done REALITY_DEST="$best_dest" REALITY_SNI="$best_dest" log "伪装目标: ${REALITY_DEST} (延迟 ${best_ms}ms)" } # ===== 4. 写入 Xray 配置 ===== write_config() { if [ "$MODE" = "reality" ]; then write_config_reality else write_config_fast fi } write_config_reality() { step "3/5 写入 Xray 配置 (Reality)" cat > /usr/local/etc/xray/config.json << EOF { "log": { "loglevel": "warning" }, "inbounds": [ { "listen": "0.0.0.0", "port": ${XRAY_PORT}, "protocol": "vless", "settings": { "clients": [ { "id": "${XRAY_UUID}", "flow": "xtls-rprx-vision" } ], "decryption": "none" }, "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "show": false, "dest": "${REALITY_DEST}:443", "xver": 0, "serverNames": [ "${REALITY_SNI}" ], "privateKey": "${XRAY_PRIVATE_KEY}", "shortIds": [ "${XRAY_SHORT_ID}" ] } }, "sniffing": { "enabled": true, "destOverride": ["http", "tls", "quic"], "routeOnly": true } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct" }, { "protocol": "blackhole", "tag": "block" } ], "routing": { "rules": [ { "type": "field", "outboundTag": "block", "protocol": ["bittorrent"] } ] } } EOF log "配置已写入: /usr/local/etc/xray/config.json" } write_config_fast() { step "3/5 写入 Xray 配置 (Fast TCP)" cat > /usr/local/etc/xray/config.json << EOF { "log": { "loglevel": "warning" }, "inbounds": [ { "listen": "0.0.0.0", "port": ${XRAY_PORT}, "protocol": "vless", "settings": { "clients": [ { "id": "${XRAY_UUID}" } ], "decryption": "none" }, "streamSettings": { "network": "tcp", "security": "none" }, "sniffing": { "enabled": true, "destOverride": ["http", "tls", "quic"], "routeOnly": true } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct" }, { "protocol": "blackhole", "tag": "block" } ], "routing": { "rules": [ { "type": "field", "outboundTag": "block", "protocol": ["bittorrent"] } ] } } EOF log "配置已写入: /usr/local/etc/xray/config.json" } # ===== 5. 防火墙 ===== configure_firewall() { step "4/5 配置防火墙" if command -v ufw &>/dev/null; then ufw allow "${XRAY_PORT}/tcp" ufw allow 22/tcp ufw --force enable log "ufw 已放行端口 ${XRAY_PORT}/tcp" elif command -v firewall-cmd &>/dev/null; then firewall-cmd --permanent --add-port="${XRAY_PORT}/tcp" firewall-cmd --reload log "firewalld 已放行端口 ${XRAY_PORT}/tcp" else warn "未检测到防火墙工具,请手动放行端口 ${XRAY_PORT}/tcp" fi } # ===== 6. BBR + 网络调优 ===== tune_network() { step "5/5 BBR + 网络调优" cat > /etc/sysctl.d/99-xray-turbo.conf << 'SYSEOF' # BBR 拥塞控制 net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr # TCP 缓冲区(提升大文件 / 视频流吞吐量) net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.ipv4.tcp_rmem=4096 87380 16777216 net.ipv4.tcp_wmem=4096 65536 16777216 # 连接优化 net.ipv4.tcp_fastopen=3 net.ipv4.tcp_slow_start_after_idle=0 net.ipv4.tcp_mtu_probing=1 net.ipv4.tcp_fin_timeout=15 net.ipv4.tcp_keepalive_time=300 net.ipv4.tcp_keepalive_intvl=30 net.ipv4.tcp_keepalive_probes=5 net.ipv4.tcp_max_tw_buckets=5000 net.ipv4.tcp_max_syn_backlog=8192 net.core.somaxconn=8192 net.core.netdev_max_backlog=8192 SYSEOF sysctl --system > /dev/null 2>&1 log "BBR 已启用,网络参数已优化" } # ===== 7. 启动服务 ===== start_service() { systemctl daemon-reload systemctl restart xray systemctl enable xray sleep 2 if systemctl is-active --quiet xray; then log "Xray 服务已启动 ✅" else error "Xray 启动失败,请检查: journalctl -u xray -f" exit 1 fi } # ===== 8. 保存配置到 .env ===== save_env() { cat > "$SCRIPT_DIR/.env" << EOF # Xray 部署配置(由 deploy.sh 自动生成) # 生成时间: $(date '+%Y-%m-%d %H:%M:%S') XRAY_MODE=${MODE} XRAY_PORT=${XRAY_PORT} XRAY_UUID=${XRAY_UUID} EOF if [ "$MODE" = "reality" ]; then cat >> "$SCRIPT_DIR/.env" << EOF XRAY_PRIVATE_KEY=${XRAY_PRIVATE_KEY} XRAY_PUBLIC_KEY=${XRAY_PUBLIC_KEY} XRAY_SHORT_ID=${XRAY_SHORT_ID} REALITY_DEST=${REALITY_DEST} REALITY_SNI=${REALITY_SNI} EOF fi chmod 600 "$SCRIPT_DIR/.env" log "配置已保存到 .env(权限 600)" } # ===== 9. 输出连接信息 ===== print_result() { local server_ip server_ip=$(curl -s --max-time 5 ipv4.ip.sb || curl -s --max-time 5 ifconfig.me || echo "获取失败") echo "" echo "==========================================================" if [ "$MODE" = "reality" ]; then echo " Xray VLESS-Reality 部署完成 ✅" echo "==========================================================" echo "" echo " IP : ${server_ip}" echo " 端口 : ${XRAY_PORT}" echo " 协议 : VLESS" echo " UUID : ${XRAY_UUID}" echo " 流控 : xtls-rprx-vision" echo " 传输 : tcp" echo " 安全 : reality" echo " SNI : ${REALITY_SNI}" echo " Fingerprint : chrome" echo " PublicKey : ${XRAY_PUBLIC_KEY}" echo " ShortId : ${XRAY_SHORT_ID}" echo "" echo "==========================================================" echo "" echo ">>> VLESS 分享链接(可直接导入客户端):" echo "" echo "vless://${XRAY_UUID}@${server_ip}:${XRAY_PORT}?encryption=none&flow=xtls-rprx-vision&security=reality&sni=${REALITY_SNI}&fp=chrome&pbk=${XRAY_PUBLIC_KEY}&sid=${XRAY_SHORT_ID}&type=tcp#VPS-Reality" else echo " Xray VLESS TCP 部署完成 ✅" echo "==========================================================" echo "" echo " IP : ${server_ip}" echo " 端口 : ${XRAY_PORT}" echo " 协议 : VLESS" echo " UUID : ${XRAY_UUID}" echo " 传输 : tcp" echo " 安全 : none" fi echo "" echo "==========================================================" echo "" echo "⚠️ 请妥善保存以上信息!" echo " 配置文件: /usr/local/etc/xray/config.json" echo " 凭据备份: ${SCRIPT_DIR}/.env" echo " 查看日志: journalctl -u xray -f" echo " 重启服务: systemctl restart xray" echo "==========================================================" } # ===== 主流程 ===== main() { echo "" log "部署模式: ${MODE}" [ "$MODE" = "reality" ] && log "VLESS-Reality(推荐,抗封锁)" || log "VLESS TCP(极速,无 TLS)" echo "" install_xray generate_keys select_reality_dest write_config configure_firewall tune_network start_service save_env print_result } main