AC2100/vps_optimize.sh

606 lines
22 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ============================================================
# VPS 一键优化脚本
# 适用: Debian 12 + VLESS + WS + TLS + Cloudflare CDN
# 功能: BBR / 内核参数 / 文件描述符 / Nginx / CF IP 白名单
# ============================================================
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warning() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[ERR]${NC} $1"; exit 1; }
step() { echo -e "\n${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n${BOLD}${YELLOW} $1${NC}\n${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }
# ── 记录优化结果供最终报告用 ──────────────────────────────────
RESULTS=()
add_result() { RESULTS+=("$1"); }
# ============================================================
# 0. 前置检查
# ============================================================
check_root() {
[[ $EUID -eq 0 ]] || error "请使用 root 用户运行: sudo bash vps_optimize.sh"
}
check_debian() {
[[ -f /etc/debian_version ]] || error "此脚本仅支持 Debian / Ubuntu 系统"
info "系统: $(lsb_release -d 2>/dev/null | cut -f2)"
info "内核: $(uname -r)"
}
print_banner() {
clear
echo -e "${CYAN}"
echo "╔══════════════════════════════════════════════════════╗"
echo "║ VPS 一键优化脚本 ║"
echo "║ VLESS + WS + TLS + Cloudflare CDN ║"
echo "╚══════════════════════════════════════════════════════╝"
echo -e "${NC}"
}
# ============================================================
# 1. 收集配置参数
# ============================================================
NGINX_PORT=""
WS_PATH=""
DOMAIN=""
ENABLE_CF_WHITELIST="y"
detect_existing_config() {
step "🔍 检测现有配置"
# 从 nginx 配置自动读取端口和路径
local nginx_conf
nginx_conf=$(find /etc/nginx/sites-enabled/ -type f 2>/dev/null | xargs grep -l "proxy_pass" 2>/dev/null | head -1)
if [[ -n "$nginx_conf" ]]; then
local detected_port detected_path detected_domain
detected_port=$(grep -E 'listen\s+[0-9]+\s+ssl' "$nginx_conf" 2>/dev/null | grep -oE '[0-9]+' | head -1)
detected_path=$(grep -E 'location\s+/' "$nginx_conf" 2>/dev/null | awk '{print $2}' | head -1)
detected_domain=$(grep 'server_name' "$nginx_conf" 2>/dev/null | awk '{print $2}' | tr -d ';' | head -1)
[[ -n "$detected_port" ]] && NGINX_PORT="$detected_port"
[[ -n "$detected_path" ]] && WS_PATH="$detected_path"
[[ -n "$detected_domain" ]] && DOMAIN="$detected_domain"
info "$nginx_conf 读取到:"
[[ -n "$NGINX_PORT" ]] && info " 端口: $NGINX_PORT"
[[ -n "$WS_PATH" ]] && info " 路径: $WS_PATH"
[[ -n "$DOMAIN" ]] && info " 域名: $DOMAIN"
else
warning "未检测到现有 nginx 配置"
fi
}
collect_params() {
step "⚙️ 配置参数确认"
# 端口
if [[ -z "$NGINX_PORT" ]]; then
read -rp " 请输入 Nginx 对外监听端口 [默认 2053]: " input
NGINX_PORT="${input:-2053}"
else
read -rp " 检测到端口 ${NGINX_PORT},直接回车确认或输入新值: " input
[[ -n "$input" ]] && NGINX_PORT="$input"
fi
# WS 路径
if [[ -z "$WS_PATH" ]]; then
read -rp " 请输入 WebSocket 路径 [默认 /stickrouter]: " input
WS_PATH="${input:-/stickrouter}"
else
read -rp " 检测到 WS 路径 ${WS_PATH},直接回车确认或输入新值: " input
[[ -n "$input" ]] && WS_PATH="$input"
fi
# 域名CF 白名单需要)
if [[ -z "$DOMAIN" ]]; then
read -rp " 请输入域名(用于 CF 白名单,留空跳过): " DOMAIN
else
read -rp " 检测到域名 ${DOMAIN},直接回车确认或输入新值: " input
[[ -n "$input" ]] && DOMAIN="$input"
fi
# 是否开启 CF IP 白名单
read -rp " 是否开启 Cloudflare IP 白名单限制 2053 端口? (Y/n): " input
input="${input:-y}"
[[ "$input" =~ ^[Nn]$ ]] && ENABLE_CF_WHITELIST="n" || ENABLE_CF_WHITELIST="y"
echo ""
echo -e " ${BOLD}确认配置:${NC}"
echo -e " Nginx 端口 : ${GREEN}${NGINX_PORT}${NC}"
echo -e " WS 路径 : ${GREEN}${WS_PATH}${NC}"
echo -e " 域名 : ${GREEN}${DOMAIN:-(跳过)}${NC}"
echo -e " CF 白名单 : ${GREEN}${ENABLE_CF_WHITELIST}${NC}"
echo ""
read -rp " 确认以上信息,按 Enter 继续,输入 n 重填: " confirm
[[ "$confirm" =~ ^[Nn]$ ]] && collect_params
}
# ============================================================
# 2. BBR 拥塞控制
# ============================================================
optimize_bbr() {
step "🚀 BBR 拥塞控制"
local current
current=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null)
info "当前拥塞算法: $current"
# 检查内核是否支持 BBR
if ! modprobe tcp_bbr 2>/dev/null && ! lsmod | grep -q bbr; then
warning "内核不支持 BBR跳过建议升级内核"
add_result "❌ BBR: 内核不支持"
return
fi
# 写入 sysctl先去重再追加
local sysctl_file="/etc/sysctl.d/99-bbr.conf"
cat > "$sysctl_file" << 'EOF'
# BBR 拥塞控制
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
EOF
sysctl -p "$sysctl_file" &>/dev/null
local after
after=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null)
if [[ "$after" == "bbr" ]]; then
success "BBR 已启用"
add_result "✅ BBR: 已启用"
else
warning "BBR 写入成功但未立即生效,重启后生效"
add_result "⚠️ BBR: 重启后生效"
fi
}
# ============================================================
# 3. 内核网络参数
# ============================================================
optimize_sysctl() {
step "🔧 内核网络参数调优"
local sysctl_file="/etc/sysctl.d/99-vps-optimize.conf"
cat > "$sysctl_file" << 'EOF'
# ── 接收/发送缓冲区WebSocket 长连接)────────────────────────
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.core.netdev_max_backlog = 250000
# ── 连接队列(并发连接)────────────────────────────────────────
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 16384
# ── TIME_WAIT 优化 ─────────────────────────────────────────────
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_tw_buckets = 5000
# ── WebSocket 保活 ─────────────────────────────────────────────
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
# ── 其他 ───────────────────────────────────────────────────────
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_mtu_probing = 1
net.ipv4.ip_local_port_range = 10000 65535
EOF
if sysctl -p "$sysctl_file" &>/dev/null; then
success "内核参数写入: $sysctl_file"
add_result "✅ 内核参数: 已优化"
else
warning "部分内核参数应用失败,请检查 $sysctl_file"
add_result "⚠️ 内核参数: 部分失败"
fi
}
# ============================================================
# 4. 文件描述符
# ============================================================
optimize_nofile() {
step "📁 文件描述符限制"
local limits_file="/etc/security/limits.d/99-nofile.conf"
cat > "$limits_file" << 'EOF'
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535
EOF
success "limits.conf 写入: $limits_file"
# systemd 服务单独设置
for svc in sing-box nginx xray; do
if systemctl list-unit-files "${svc}.service" &>/dev/null 2>&1 | grep -q "$svc"; then
local override_dir="/etc/systemd/system/${svc}.service.d"
mkdir -p "$override_dir"
cat > "${override_dir}/limits.conf" << 'EOF'
[Service]
LimitNOFILE=65535
EOF
success "systemd override 写入: ${svc}.service"
fi
done
systemctl daemon-reload 2>/dev/null || true
# 立即对当前 session 生效
ulimit -n 65535 2>/dev/null || true
add_result "✅ 文件描述符: 已设置为 65535"
}
# ============================================================
# 5. Nginx 优化
# ============================================================
optimize_nginx() {
step "🌐 Nginx 配置优化"
if ! command -v nginx &>/dev/null; then
warning "未检测到 nginx跳过"
add_result "❌ Nginx: 未安装"
return
fi
# 找到 sing-box/vless 相关的 nginx 配置
local nginx_conf
nginx_conf=$(find /etc/nginx/sites-available/ -type f 2>/dev/null | \
xargs grep -l "proxy_pass" 2>/dev/null | head -1)
if [[ -z "$nginx_conf" ]]; then
warning "未找到反代配置文件,跳过 Nginx 优化"
add_result "⚠️ Nginx: 未找到配置"
return
fi
info "目标配置文件: $nginx_conf"
# 备份原配置
local backup="${nginx_conf}.bak.$(date +%Y%m%d%H%M%S)"
cp "$nginx_conf" "$backup"
info "已备份至: $backup"
# ── 5a. 全局 nginx.conf 优化 ──────────────────────────────
local nginx_main="/etc/nginx/nginx.conf"
# worker_processes 改为 auto
sed -i 's/worker_processes\s\+[0-9]\+/worker_processes auto/' "$nginx_main" 2>/dev/null || true
# worker_connections 提升(在 events 块内)
sed -i '/events\s*{/,/}/{s/worker_connections\s\+[0-9]\+/worker_connections 65535/}' "$nginx_main" 2>/dev/null || true
# 写入 nginx 全局调优 snippet不覆盖主配置
cat > /etc/nginx/conf.d/99-optimize.conf << 'EOF'
# ── TCP 优化 ───────────────────────────────────────────────────
tcp_nopush on;
tcp_nodelay on;
sendfile on;
# ── 连接超时 ───────────────────────────────────────────────────
keepalive_timeout 300s;
keepalive_requests 10000;
client_header_timeout 30s;
client_body_timeout 30s;
send_timeout 30s;
# ── 缓冲 ───────────────────────────────────────────────────────
client_body_buffer_size 128k;
client_max_body_size 10m;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
EOF
# ── 5b. 站点配置优化(替换/追加关键指令)──────────────────
# 用 python3 做精确修改,避免 sed 处理多行的麻烦
python3 - "$nginx_conf" "$NGINX_PORT" "$WS_PATH" << 'PYEOF'
import sys, re
conf_path = sys.argv[1]
port = sys.argv[2]
ws_path = sys.argv[3]
with open(conf_path) as f:
content = f.read()
# ── SSL 优化 ───────────────────────────────────────────────────
# 替换 ssl_protocols
content = re.sub(r'ssl_protocols\s+[^;]+;',
'ssl_protocols TLSv1.2 TLSv1.3;', content)
# 替换 ssl_ciphers
content = re.sub(r'ssl_ciphers\s+[^;]+;',
'ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;',
content)
# ssl_prefer_server_ciphers offTLS1.3 客户端优先)
content = re.sub(r'ssl_prefer_server_ciphers\s+\w+;',
'ssl_prefer_server_ciphers off;', content)
# session 复用
for old, new in [
(r'ssl_session_cache\s+[^;]+;', 'ssl_session_cache shared:SSL:20m;'),
(r'ssl_session_timeout\s+[^;]+;', 'ssl_session_timeout 1d;'),
]:
if re.search(old, content):
content = re.sub(old, new, content)
# 追加 ssl_session_tickets 和 ssl_buffer_size如果没有
ssl_block_end = content.rfind('ssl_session')
if 'ssl_session_tickets' not in content:
content = re.sub(r'(ssl_session_timeout\s+[^;]+;)',
r'\1\n ssl_session_tickets off;\n ssl_buffer_size 4k;', content)
# ── WebSocket location 块优化 ──────────────────────────────────
def patch_location(m):
block = m.group(0)
patches = {
r'proxy_read_timeout\s+[^;]+;': 'proxy_read_timeout 600s;',
r'proxy_send_timeout\s+[^;]+;': 'proxy_send_timeout 600s;',
r'proxy_connect_timeout\s+[^;]+;': 'proxy_connect_timeout 10s;',
}
for pattern, replacement in patches.items():
if re.search(pattern, block):
block = re.sub(pattern, replacement, block)
else:
# 在 proxy_buffering off; 后面追加
block = block.replace('proxy_buffering off;',
f'proxy_buffering off;\n {replacement}')
# 确保有 tcp_nodelay
if 'tcp_nodelay' not in block:
block = block.replace('proxy_buffering off;',
'proxy_buffering off;\n tcp_nodelay on;')
return block
content = re.sub(
r'location\s+' + re.escape(ws_path) + r'\s*\{[^}]+\}',
patch_location,
content,
flags=re.DOTALL
)
with open(conf_path, 'w') as f:
f.write(content)
print(" Nginx 站点配置已更新")
PYEOF
# 测试配置
if nginx -t 2>/dev/null; then
systemctl reload nginx
success "Nginx 优化完成并重载"
add_result "✅ Nginx: 已优化并重载"
else
warning "Nginx 配置测试失败,正在回滚..."
cp "$backup" "$nginx_conf"
systemctl reload nginx 2>/dev/null || true
add_result "❌ Nginx: 优化失败已回滚"
fi
}
# ============================================================
# 6. sing-box / xray 服务优化
# ============================================================
optimize_proxy_service() {
step "⚡ 代理服务优化"
local found=0
for svc in sing-box xray; do
if systemctl is-active --quiet "$svc" 2>/dev/null; then
info "检测到运行中的服务: $svc"
systemctl restart "$svc"
success "$svc 已重启(文件描述符 override 生效)"
add_result "${svc}: 已重启"
found=1
fi
done
[[ $found -eq 0 ]] && warning "未检测到运行中的 sing-box 或 xray 服务"
}
# ============================================================
# 7. 防火墙 + Cloudflare IP 白名单
# ============================================================
setup_cf_whitelist() {
step "🛡️ Cloudflare IP 白名单"
if [[ "$ENABLE_CF_WHITELIST" != "y" ]]; then
info "已跳过 CF 白名单配置"
add_result "⏭️ CF 白名单: 已跳过"
return
fi
if ! command -v ufw &>/dev/null; then
info "安装 ufw..."
apt-get install -y -qq ufw
fi
# 保证 SSH 不被锁
ufw allow 22/tcp comment 'SSH' &>/dev/null
ufw allow 80/tcp comment 'HTTP' &>/dev/null
info "拉取 Cloudflare IP 段..."
local cf_v4 cf_v6
cf_v4=$(curl -sf --max-time 10 https://www.cloudflare.com/ips-v4/ 2>/dev/null)
cf_v6=$(curl -sf --max-time 10 https://www.cloudflare.com/ips-v6/ 2>/dev/null)
if [[ -z "$cf_v4" ]]; then
warning "拉取 CF IP 失败,使用内置 IP 段(可能不是最新)"
cf_v4="173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22"
fi
# 先删除旧的 CF 规则
ufw status numbered 2>/dev/null | grep -E "CF|Cloudflare" | \
awk -F'[][]' '{print $2}' | sort -rn | \
xargs -I{} ufw --force delete {} 2>/dev/null || true
# 先拒绝所有访问该端口
ufw deny "${NGINX_PORT}/tcp" comment 'deny-direct' &>/dev/null || true
local count=0
while IFS= read -r ip; do
[[ -z "$ip" ]] && continue
ufw allow from "$ip" to any port "$NGINX_PORT" proto tcp comment 'CF' &>/dev/null && ((count++)) || true
done <<< "$cf_v4"
while IFS= read -r ip; do
[[ -z "$ip" ]] && continue
ufw allow from "$ip" to any port "$NGINX_PORT" proto tcp comment 'CF' &>/dev/null && ((count++)) || true
done <<< "$cf_v6"
# 开启 ufw如果未启用
if ! ufw status | grep -q "Status: active"; then
ufw --force enable &>/dev/null
else
ufw reload &>/dev/null
fi
success "已添加 ${count} 条 CF IP 规则,端口 ${NGINX_PORT} 仅允许 CF 回源"
add_result "✅ CF 白名单: ${count} 条规则,端口 ${NGINX_PORT} 已锁定"
# 保存 CF IP 更新脚本,供定期执行
cat > /usr/local/bin/update-cf-whitelist.sh << CFEOF
#!/bin/bash
# 更新 Cloudflare IP 白名单
PORT="${NGINX_PORT}"
cf_v4=\$(curl -sf --max-time 10 https://www.cloudflare.com/ips-v4/ 2>/dev/null)
cf_v6=\$(curl -sf --max-time 10 https://www.cloudflare.com/ips-v6/ 2>/dev/null)
[[ -z "\$cf_v4" ]] && exit 1
# 删除旧规则
ufw status numbered | grep 'CF' | awk -F'[][]' '{print \$2}' | sort -rn | \\
xargs -I{} ufw --force delete {} 2>/dev/null || true
# 重新添加
for ip in \$cf_v4 \$cf_v6; do
[[ -n "\$ip" ]] && ufw allow from "\$ip" to any port "\$PORT" proto tcp comment 'CF' &>/dev/null
done
ufw reload
echo "\$(date): CF 白名单已更新"
CFEOF
chmod +x /usr/local/bin/update-cf-whitelist.sh
# 每月更新一次
echo "0 4 1 * * root /usr/local/bin/update-cf-whitelist.sh >> /var/log/cf-whitelist.log 2>&1" \
> /etc/cron.d/update-cf-whitelist
success "CF IP 自动更新任务已配置每月1号凌晨4点"
}
# ============================================================
# 8. 时间同步
# ============================================================
optimize_time() {
step "🕐 时间同步"
if systemctl is-active --quiet systemd-timesyncd 2>/dev/null; then
timedatectl set-ntp true 2>/dev/null || true
success "systemd-timesyncd 已运行"
add_result "✅ 时间同步: 正常"
elif command -v ntpd &>/dev/null; then
success "ntpd 已运行"
add_result "✅ 时间同步: ntpd"
else
apt-get install -y -qq systemd-timesyncd 2>/dev/null
timedatectl set-ntp true 2>/dev/null || true
success "systemd-timesyncd 已安装并启用"
add_result "✅ 时间同步: 已安装"
fi
info "当前时间: $(date '+%Y-%m-%d %H:%M:%S %Z')"
}
# ============================================================
# 9. 最终报告
# ============================================================
print_report() {
step "📋 优化报告"
echo ""
for r in "${RESULTS[@]}"; do
echo -e " $r"
done
echo ""
echo -e " ${BOLD}当前服务状态:${NC}"
for svc in nginx sing-box xray; do
if systemctl list-unit-files "${svc}.service" &>/dev/null 2>&1 | grep -q "$svc"; then
local status
if systemctl is-active --quiet "$svc" 2>/dev/null; then
echo -e " ${GREEN}${NC} ${svc} 运行中"
else
echo -e " ${RED}${NC} ${svc} 未运行"
fi
fi
done
echo ""
echo -e " ${BOLD}BBR 验证:${NC}"
echo -e " 拥塞算法: ${GREEN}$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null)${NC}"
echo -e " 队列算法: ${GREEN}$(sysctl -n net.core.default_qdisc 2>/dev/null)${NC}"
echo ""
echo -e " ${BOLD}文件描述符:${NC}"
echo -e " 当前 session: ${GREEN}$(ulimit -n)${NC}"
if [[ "$ENABLE_CF_WHITELIST" == "y" ]]; then
echo ""
echo -e " ${BOLD}防火墙状态:${NC}"
ufw status | grep -E "Status|${NGINX_PORT}" | sed 's/^/ /'
fi
echo ""
echo -e " ${CYAN}备份文件位置: /etc/nginx/sites-available/*.bak.*${NC}"
echo -e " ${CYAN}CF 白名单更新: /usr/local/bin/update-cf-whitelist.sh${NC}"
echo -e " ${CYAN}手动更新 CF IP: bash /usr/local/bin/update-cf-whitelist.sh${NC}"
echo ""
warning "建议执行: reboot 使所有内核参数完全生效"
echo ""
}
# ============================================================
# 主流程
# ============================================================
main() {
check_root
print_banner
check_debian
detect_existing_config
collect_params
optimize_bbr
optimize_sysctl
optimize_nofile
optimize_nginx
optimize_proxy_service
setup_cf_whitelist
optimize_time
print_report
}
main