添加 install.sh
This commit is contained in:
+725
@@ -0,0 +1,725 @@
|
||||
#!/bin/bash
|
||||
# ================================================================
|
||||
# 🚀 终极四合一 代理管理面板 克劳德魔改版
|
||||
# 支持 amd64 / arm64,Ubuntu / Debian / CentOS
|
||||
# 集成: Xray(Vision/Reality) + NaïveProxy + Sing-box(SS-TLS) + AnyTLS
|
||||
# ================================================================
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_info() { echo -e "${BLUE}[信息]${NC} $1"; }
|
||||
print_success() { echo -e "${GREEN}[成功]${NC} $1"; }
|
||||
print_warning() { echo -e "${YELLOW}[警告]${NC} $1"; }
|
||||
print_error() { echo -e "${RED}[错误]${NC} $1"; }
|
||||
step() { echo -e "${CYAN} ▶ $1${NC}"; }
|
||||
|
||||
askline() {
|
||||
local prompt="$1"
|
||||
local varname="$2"
|
||||
echo -e -n "${YELLOW} ➤ ${prompt}${NC} "
|
||||
read -r "$varname"
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
print_error "请使用 root 权限运行此脚本 (sudo bash $0)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64) echo "amd64" ;;
|
||||
aarch64|arm64) echo "arm64" ;;
|
||||
*) echo "unsupported" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
rand_str() { cat /dev/urandom | tr -dc 'A-Za-z0-9' | head -c "$1"; }
|
||||
|
||||
urlencode() {
|
||||
local string="$1"
|
||||
if command -v python3 &>/dev/null; then
|
||||
python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$string"
|
||||
elif command -v python &>/dev/null; then
|
||||
python -c "import urllib, sys; print(urllib.quote(sys.argv[1], safe=''))" "$string"
|
||||
else
|
||||
local strlen=${#string}
|
||||
local encoded="" pos c o
|
||||
for (( pos=0; pos<strlen; pos++ )); do
|
||||
c=${string:$pos:1}
|
||||
case "$c" in
|
||||
[-_.~a-zA-Z0-9]) o="${c}" ;;
|
||||
*) printf -v o '%%%02X' "'$c" ;;
|
||||
esac
|
||||
encoded+="${o}"
|
||||
done
|
||||
echo "${encoded}"
|
||||
fi
|
||||
}
|
||||
|
||||
enable_bbr() {
|
||||
if ! sysctl net.ipv4.tcp_congestion_control 2>/dev/null | grep -q "bbr"; then
|
||||
print_info "开启 BBR 加速..."
|
||||
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
|
||||
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
|
||||
sysctl -p >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
print_info "安装系统依赖..."
|
||||
if [ -f /etc/debian_version ]; then
|
||||
apt-get update -qq -y
|
||||
apt-get install -y -qq curl wget openssl jq socat cron ufw tar lsof ca-certificates
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
yum install -y -q epel-release
|
||||
yum install -y -q curl wget openssl jq socat cronie tar lsof ca-certificates
|
||||
fi
|
||||
}
|
||||
|
||||
check_port() {
|
||||
local port=$1
|
||||
if lsof -Pi :"$port" -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||
print_error "端口 $port 已被占用!请更换端口或先停止占用该端口的服务。"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
open_ports() {
|
||||
local port=$1
|
||||
if command -v ufw &>/dev/null; then
|
||||
ufw allow 80/tcp >/dev/null 2>&1
|
||||
ufw allow "$port"/tcp >/dev/null 2>&1
|
||||
ufw allow "$port"/udp >/dev/null 2>&1
|
||||
fi
|
||||
if command -v firewall-cmd &>/dev/null; then
|
||||
firewall-cmd --zone=public --add-port=80/tcp --permanent >/dev/null 2>&1
|
||||
firewall-cmd --zone=public --add-port="$port"/tcp --permanent >/dev/null 2>&1
|
||||
firewall-cmd --zone=public --add-port="$port"/udp --permanent >/dev/null 2>&1
|
||||
firewall-cmd --reload >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 通用 SSL 证书申请 (使用 Let's Encrypt)
|
||||
# ================================================================
|
||||
apply_cert() {
|
||||
local domain=$1
|
||||
local cert_dir=$2
|
||||
mkdir -p "$cert_dir"
|
||||
|
||||
local acme_bin="$HOME/.acme.sh/acme.sh"
|
||||
|
||||
print_info "正在为域名 $domain 申请 SSL 证书 (CA: Let's Encrypt)..."
|
||||
print_info "需确保 80 端口未被占用且域名已正确解析到本机 IP"
|
||||
|
||||
# 安装 acme.sh(若尚未安装)
|
||||
if [ ! -f "$acme_bin" ]; then
|
||||
curl https://get.acme.sh | sh
|
||||
fi
|
||||
export PATH="$HOME/.acme.sh:$PATH"
|
||||
|
||||
# 强制切换到 Let's Encrypt
|
||||
"$acme_bin" --set-default-ca --server letsencrypt >/dev/null 2>&1
|
||||
|
||||
# 释放 80 端口
|
||||
systemctl stop nginx 2>/dev/null || true
|
||||
systemctl stop apache2 2>/dev/null || true
|
||||
systemctl stop caddy 2>/dev/null || true
|
||||
systemctl stop caddy-naive 2>/dev/null || true
|
||||
|
||||
# 申请证书
|
||||
"$acme_bin" --issue -d "$domain" --standalone -k ec-256 --force \
|
||||
--server letsencrypt
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
print_success "证书申请成功!"
|
||||
"$acme_bin" --installcert -d "$domain" \
|
||||
--fullchainpath "$cert_dir/fullchain.pem" \
|
||||
--keypath "$cert_dir/privkey.pem" \
|
||||
--ecc
|
||||
chmod 755 "$cert_dir"
|
||||
chmod 644 "$cert_dir/fullchain.pem" "$cert_dir/privkey.pem"
|
||||
return 0
|
||||
else
|
||||
print_error "证书申请失败!请检查:"
|
||||
print_error " 1. 域名 $domain 是否已解析到本机公网 IP"
|
||||
print_error " 2. 80 端口是否可以从外部访问(Oracle 安全组需放行 80)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 1. 部署 Xray (Vision/Reality)
|
||||
# ================================================================
|
||||
do_install_xray() {
|
||||
clear
|
||||
echo -e "${BLUE} ── 部署 Xray (VLESS-Reality / Vision-TLS) ────────${NC}"
|
||||
install_dependencies
|
||||
|
||||
echo "1. VLESS-Reality (无需域名,适合无域名用户 - 推荐)"
|
||||
echo "2. VLESS-Vision-TLS (需要自有域名并解析到本机)"
|
||||
askline "请选择 [1-2]: " mode
|
||||
askline "请输入 Xray 端口 [留空默认 443]: " PORT
|
||||
PORT=${PORT:-443}
|
||||
|
||||
if ! check_port "$PORT"; then sleep 2; return; fi
|
||||
open_ports "$PORT"
|
||||
|
||||
if ! command -v xray &>/dev/null; then
|
||||
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
|
||||
fi
|
||||
|
||||
local UUID
|
||||
UUID=$(xray uuid)
|
||||
local CONFIG_FILE="/usr/local/etc/xray/config.json"
|
||||
|
||||
if [ "$mode" == "2" ]; then
|
||||
askline "请输入你的域名 (如 s1.example.com): " USER_DOMAIN
|
||||
if ! apply_cert "$USER_DOMAIN" "/usr/local/etc/xray/cert"; then return; fi
|
||||
cat > "$CONFIG_FILE" << EOF
|
||||
{
|
||||
"inbounds": [{
|
||||
"port": $PORT, "protocol": "vless",
|
||||
"settings": { "clients": [ { "id": "$UUID", "flow": "xtls-rprx-vision" } ], "decryption": "none" },
|
||||
"streamSettings": {
|
||||
"network": "tcp", "security": "tls",
|
||||
"tlsSettings": { "certificates": [ {
|
||||
"certificateFile": "/usr/local/etc/xray/cert/fullchain.pem",
|
||||
"keyFile": "/usr/local/etc/xray/cert/privkey.pem"
|
||||
} ] }
|
||||
},
|
||||
"sniffing": { "enabled": true, "destOverride": ["http", "tls"] }
|
||||
}],
|
||||
"outbounds": [{ "protocol": "freedom", "tag": "direct" }]
|
||||
}
|
||||
EOF
|
||||
LINK_ADDR="$USER_DOMAIN"
|
||||
LINK_SNI="$USER_DOMAIN"
|
||||
LINK_TYPE="tls"
|
||||
LINK_EXTRA=""
|
||||
SHOW_MSG="Vision-TLS"
|
||||
else
|
||||
local KEYS
|
||||
KEYS=$(xray x25519)
|
||||
local PRIVATE_KEY
|
||||
PRIVATE_KEY=$(echo "$KEYS" | grep -i "PrivateKey" | awk -F': ' '{print $2}' | tr -d ' ')
|
||||
local PUBLIC_KEY
|
||||
PUBLIC_KEY=$(echo "$KEYS" | grep -i "PublicKey" | awk -F': ' '{print $2}' | tr -d ' ')
|
||||
|
||||
echo "选择伪装域名:"
|
||||
echo " 1. dl.google.com"
|
||||
echo " 2. www.apple.com"
|
||||
echo " 3. www.microsoft.com"
|
||||
askline "请选择 [留空默认 1]: " dest_choice
|
||||
case $dest_choice in
|
||||
2) DEST="www.apple.com:443"; SNI="www.apple.com" ;;
|
||||
3) DEST="www.microsoft.com:443"; SNI="www.microsoft.com" ;;
|
||||
*) DEST="dl.google.com:443"; SNI="dl.google.com" ;;
|
||||
esac
|
||||
|
||||
local SHORT_ID
|
||||
SHORT_ID=$(openssl rand -hex 8)
|
||||
cat > "$CONFIG_FILE" << EOF
|
||||
{
|
||||
"inbounds": [{
|
||||
"port": $PORT, "protocol": "vless",
|
||||
"settings": { "clients": [ { "id": "$UUID", "flow": "xtls-rprx-vision" } ], "decryption": "none" },
|
||||
"streamSettings": {
|
||||
"network": "tcp", "security": "reality",
|
||||
"realitySettings": {
|
||||
"show": false, "dest": "$DEST", "xver": 0,
|
||||
"serverNames": ["$SNI"],
|
||||
"privateKey": "$PRIVATE_KEY",
|
||||
"shortIds": ["", "$SHORT_ID"]
|
||||
}
|
||||
},
|
||||
"sniffing": { "enabled": true, "destOverride": ["http", "tls"] }
|
||||
}],
|
||||
"outbounds": [{ "protocol": "freedom", "tag": "direct" }]
|
||||
}
|
||||
EOF
|
||||
LINK_ADDR=$(curl -s4 ifconfig.me 2>/dev/null || curl -s6 ifconfig.me)
|
||||
LINK_SNI="$SNI"
|
||||
LINK_TYPE="reality"
|
||||
LINK_EXTRA="&pbk=${PUBLIC_KEY}&sid=${SHORT_ID}"
|
||||
SHOW_MSG="Reality"
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl restart xray
|
||||
systemctl enable xray
|
||||
|
||||
local ALIAS
|
||||
ALIAS=$(urlencode "Xray-${SHOW_MSG}-${PORT}")
|
||||
local VLESS_LINK="vless://${UUID}@${LINK_ADDR}:${PORT}?security=${LINK_TYPE}&encryption=none&type=tcp&flow=xtls-rprx-vision&sni=${LINK_SNI}&fp=chrome${LINK_EXTRA}#${ALIAS}"
|
||||
|
||||
echo "=========================================="
|
||||
print_success "Xray ($SHOW_MSG) 部署成功!"
|
||||
echo -e "${YELLOW}【VLESS 分享链接 (直接导入)】${NC}"
|
||||
echo -e "${GREEN}${VLESS_LINK}${NC}"
|
||||
echo "=========================================="
|
||||
read -n 1 -s -r -p "按任意键返回..."
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 2. 部署 NaïveProxy (Caddy + 网盘伪装)
|
||||
# ================================================================
|
||||
generate_fake_site() {
|
||||
local site_name="$1"
|
||||
local domain="$2"
|
||||
local webroot="/var/www/naive-disguise"
|
||||
mkdir -p "$webroot"
|
||||
cat > "$webroot/index.html" <<HTMLEOF
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${site_name}Drive — Private Cloud</title><style>*{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#0f0f14;min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:1.5rem}.logo-wrap{display:flex;align-items:center;gap:10px;margin-bottom:2rem}.logo-icon{width:38px;height:38px;border-radius:9px;background:#1e1b4b;border:1px solid #312e81;display:flex;align-items:center;justify-content:center}.logo-icon svg{width:20px;height:20px}.logo-text{font-size:17px;font-weight:600;color:#e2e8f0;letter-spacing:-0.3px}.logo-text span{color:#818cf8}.badge{display:inline-flex;align-items:center;gap:3px;font-size:10px;padding:2px 7px;border-radius:99px;background:#1e1b4b;color:#a5b4fc;margin-left:7px;font-weight:500;border:1px solid #312e81}.card{background:#16161f;border:1px solid #232336;border-radius:14px;padding:2rem;width:100%;max-width:380px}.card-title{font-size:18px;font-weight:600;color:#e2e8f0;margin-bottom:4px}.card-sub{font-size:13px;color:#64748b;margin-bottom:1.5rem;line-height:1.5}.field{margin-bottom:1rem}.field label{display:block;font-size:11px;font-weight:600;color:#475569;margin-bottom:6px;text-transform:uppercase;letter-spacing:0.6px}.field input{width:100%;padding:9px 12px;font-size:14px;border:1px solid #232336;border-radius:8px;background:#0f0f14;color:#e2e8f0;outline:none}.btn{width:100%;padding:10px;font-size:14px;font-weight:600;color:#fff;background:#6366f1;border:none;border-radius:8px;cursor:pointer;margin-top:.5rem}.alert{padding:10px 12px;border-radius:8px;font-size:13px;margin-bottom:1rem;display:none;align-items:center;gap:8px;background:#2d1515;color:#f87171;border:1px solid #7f1d1d}.alert.show{display:flex}</style></head><body><div class="logo-wrap"><div class="logo-icon"><svg viewBox="0 0 24 24" fill="none" stroke="#818cf8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="12" rx="10" ry="10"/><path d="M12 2C8.5 7 8.5 17 12 22"/><path d="M12 2C15.5 7 15.5 17 12 22"/><path d="M2 12h20"/></svg></div><div class="logo-text">${site_name}<span>Drive</span> <span class="badge">Private</span></div></div><div class="card"><p class="card-title">Sign in to your vault</p><p class="card-sub">Access is restricted to authorized accounts only.</p><div class="alert" id="alert"><span id="alert-msg">Invalid credentials.</span></div><div class="field"><label>Email address</label><input type="email" id="email" placeholder="you@${domain}" autocomplete="email"/></div><div class="field"><label>Password</label><input type="password" id="password" placeholder="••••••••••••" autocomplete="current-password"/></div><button class="btn" onclick="doLogin()">Sign in</button></div><script>function doLogin(){const a=document.getElementById('alert');document.getElementById('alert-msg').textContent='Authentication failed.';a.classList.add('show');setTimeout(()=>a.classList.remove('show'),3000);}</script></body></html>
|
||||
HTMLEOF
|
||||
}
|
||||
|
||||
do_install_naive() {
|
||||
clear
|
||||
echo -e "${BLUE} ── 部署 NaïveProxy (带 Vault 私有网盘伪装) ────────${NC}"
|
||||
local arch
|
||||
arch=$(detect_arch)
|
||||
[ "$arch" = "unsupported" ] && { print_error "不支持的 CPU 架构"; return; }
|
||||
install_dependencies
|
||||
|
||||
askline "请输入代理域名 (DNS需提前解析到本机): " domain
|
||||
askline "请输入 Naive 端口 [留空默认 443]: " PORT
|
||||
PORT=${PORT:-443}
|
||||
|
||||
if ! check_port "$PORT"; then sleep 2; return; fi
|
||||
|
||||
askline "网盘名称 [留空默认 Vault]: " sitename
|
||||
sitename=${sitename:-Vault}
|
||||
|
||||
local username="naive_$(rand_str 6 | tr '[:upper:]' '[:lower:]')"
|
||||
local password
|
||||
password=$(rand_str 18)
|
||||
|
||||
open_ports "$PORT"
|
||||
|
||||
if ! apply_cert "$domain" "/etc/caddy/cert"; then return; fi
|
||||
|
||||
step "下载 Caddy (含 forwardproxy)..."
|
||||
local caddy_url
|
||||
if [ "$arch" = "arm64" ]; then
|
||||
caddy_url="https://github.com/Michaol/caddy-naive/releases/latest/download/caddy-linux-arm64"
|
||||
else
|
||||
caddy_url="https://github.com/Michaol/caddy-naive/releases/latest/download/caddy-linux-amd64"
|
||||
fi
|
||||
if ! wget -q --show-progress -O /usr/local/bin/caddy "$caddy_url"; then
|
||||
print_error "下载 Caddy 失败,请检查网络。"
|
||||
return
|
||||
fi
|
||||
chmod +x /usr/local/bin/caddy
|
||||
setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy 2>/dev/null || true
|
||||
|
||||
mkdir -p /etc/caddy /var/lib/caddy /var/log/caddy
|
||||
id caddy &>/dev/null || useradd --system --home /var/lib/caddy --shell /usr/sbin/nologin caddy
|
||||
|
||||
generate_fake_site "$sitename" "$domain"
|
||||
chown -R caddy:caddy /var/www/naive-disguise /etc/caddy /var/lib/caddy /var/log/caddy
|
||||
|
||||
cat > /etc/caddy/Caddyfile <<EOF
|
||||
{
|
||||
admin off
|
||||
}
|
||||
$domain:$PORT {
|
||||
tls /etc/caddy/cert/fullchain.pem /etc/caddy/cert/privkey.pem {
|
||||
protocols tls1.2 tls1.3
|
||||
}
|
||||
route {
|
||||
forward_proxy {
|
||||
basic_auth ${username} ${password}
|
||||
hide_ip
|
||||
hide_via
|
||||
probe_resistance
|
||||
}
|
||||
file_server {
|
||||
root /var/www/naive-disguise
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
cat > /etc/systemd/system/caddy-naive.service <<EOF
|
||||
[Unit]
|
||||
Description=Caddy NaiveProxy
|
||||
After=network.target
|
||||
[Service]
|
||||
Type=notify
|
||||
User=caddy
|
||||
ExecStart=/usr/local/bin/caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||
Restart=on-failure
|
||||
LimitNOFILE=1048576
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart caddy-naive
|
||||
systemctl enable caddy-naive
|
||||
|
||||
local uri="naive+https://${username}:${password}@${domain}:${PORT}"
|
||||
echo "=========================================="
|
||||
print_success "NaïveProxy 部署成功!"
|
||||
echo "=========================================="
|
||||
echo " 协议 : naive+https"
|
||||
echo " 域名 : $domain"
|
||||
echo " 端口 : $PORT"
|
||||
echo " 用户名 : $username"
|
||||
echo " 密码 : $password"
|
||||
echo "=========================================="
|
||||
echo -e "${YELLOW}【一键导入 URI】${NC}"
|
||||
echo -e "${GREEN}${uri}${NC}"
|
||||
read -n 1 -s -r -p "按任意键返回..."
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 3. 部署 Sing-box (Shadowsocks + TLS)
|
||||
# ================================================================
|
||||
do_install_sstls() {
|
||||
clear
|
||||
echo -e "${BLUE} ── 部署 Sing-box (Shadowsocks + TLS 协议) ─────────${NC}"
|
||||
install_dependencies
|
||||
|
||||
local arch
|
||||
arch=$(detect_arch)
|
||||
local sb_arch
|
||||
case "$arch" in
|
||||
amd64) sb_arch="amd64" ;;
|
||||
arm64) sb_arch="arm64" ;;
|
||||
*) print_error "架构不支持"; return ;;
|
||||
esac
|
||||
|
||||
askline "请输入绑定域名 (DNS需解析到本机): " USER_DOMAIN
|
||||
askline "请输入 SS-TLS 监听端口 [留空默认 443]: " PORT
|
||||
PORT=${PORT:-443}
|
||||
|
||||
if ! check_port "$PORT"; then sleep 2; return; fi
|
||||
open_ports "$PORT"
|
||||
|
||||
if ! command -v sing-box &>/dev/null; then
|
||||
step "下载 Sing-box Core..."
|
||||
local version
|
||||
version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest \
|
||||
| grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
|
||||
if [ -z "$version" ]; then
|
||||
print_error "无法获取 sing-box 最新版本,请检查网络。"
|
||||
return
|
||||
fi
|
||||
wget -q --show-progress -O /tmp/sing-box.tar.gz \
|
||||
"https://github.com/SagerNet/sing-box/releases/download/v${version}/sing-box-${version}-linux-${sb_arch}.tar.gz"
|
||||
tar -xzf /tmp/sing-box.tar.gz -C /tmp/
|
||||
mv "/tmp/sing-box-${version}-linux-${sb_arch}/sing-box" /usr/local/bin/
|
||||
chmod +x /usr/local/bin/sing-box
|
||||
rm -rf /tmp/sing-box.tar.gz "/tmp/sing-box-${version}-linux-${sb_arch}"
|
||||
fi
|
||||
|
||||
if ! apply_cert "$USER_DOMAIN" "/usr/local/etc/sing-box/cert"; then return; fi
|
||||
|
||||
local ss_pass
|
||||
ss_pass="$(rand_str 16)"
|
||||
|
||||
mkdir -p /usr/local/etc/sing-box
|
||||
cat > /usr/local/etc/sing-box/config.json <<EOF
|
||||
{
|
||||
"log": { "level": "warn" },
|
||||
"inbounds": [
|
||||
{
|
||||
"type": "shadowsocks",
|
||||
"tag": "ss-tls-in",
|
||||
"listen": "::",
|
||||
"listen_port": $PORT,
|
||||
"method": "aes-256-gcm",
|
||||
"password": "$ss_pass",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"server_name": "$USER_DOMAIN",
|
||||
"certificate_path": "/usr/local/etc/sing-box/cert/fullchain.pem",
|
||||
"key_path": "/usr/local/etc/sing-box/cert/privkey.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{ "type": "direct", "tag": "direct" }
|
||||
]
|
||||
}
|
||||
EOF
|
||||
cat > /etc/systemd/system/sing-box.service <<EOF
|
||||
[Unit]
|
||||
Description=sing-box Service
|
||||
After=network.target
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json
|
||||
Restart=on-failure
|
||||
LimitNOFILE=infinity
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart sing-box
|
||||
systemctl enable sing-box
|
||||
|
||||
echo "=========================================="
|
||||
print_success "Sing-box (SS-TLS) 部署成功!"
|
||||
echo "=========================================="
|
||||
echo " 域名 (Server) : $USER_DOMAIN"
|
||||
echo " 端口 (Port) : $PORT"
|
||||
echo " 密码 (Password) : $ss_pass"
|
||||
echo " 加密 (Method) : aes-256-gcm"
|
||||
echo "=========================================="
|
||||
echo -e "${YELLOW}【sing-box 客户端配置片段】${NC}"
|
||||
cat <<SBEOF
|
||||
{
|
||||
"type": "shadowsocks",
|
||||
"tag": "SS-TLS-Node",
|
||||
"server": "$USER_DOMAIN",
|
||||
"server_port": $PORT,
|
||||
"method": "aes-256-gcm",
|
||||
"password": "$ss_pass",
|
||||
"tls": { "enabled": true, "server_name": "$USER_DOMAIN" }
|
||||
}
|
||||
SBEOF
|
||||
echo "=========================================="
|
||||
read -n 1 -s -r -p "按任意键返回..."
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 4. 部署 AnyTLS (sing-box)
|
||||
# ================================================================
|
||||
do_install_anytls() {
|
||||
clear
|
||||
echo -e "${BLUE} ── 部署 AnyTLS (sing-box,抗流量检测) ─────────────${NC}"
|
||||
install_dependencies
|
||||
|
||||
local arch
|
||||
arch=$(detect_arch)
|
||||
local sb_arch
|
||||
case "$arch" in
|
||||
amd64) sb_arch="amd64" ;;
|
||||
arm64) sb_arch="arm64" ;;
|
||||
*) print_error "架构不支持"; return ;;
|
||||
esac
|
||||
|
||||
askline "请输入绑定域名 (DNS需解析到本机): " USER_DOMAIN
|
||||
askline "请输入 AnyTLS 监听端口 [留空默认 443]: " PORT
|
||||
PORT=${PORT:-443}
|
||||
|
||||
if ! check_port "$PORT"; then sleep 2; return; fi
|
||||
open_ports "$PORT"
|
||||
|
||||
local need_install=0
|
||||
if ! command -v sing-box &>/dev/null; then
|
||||
need_install=1
|
||||
else
|
||||
local sb_ver
|
||||
sb_ver=$(sing-box version 2>/dev/null | grep -E '^sing-box version' | awk '{print $3}' | head -1)
|
||||
local sb_major=${sb_ver%%.*}
|
||||
local sb_minor
|
||||
sb_minor=$(echo "$sb_ver" | awk -F. '{print $2}')
|
||||
if [ "${sb_major:-0}" -lt 1 ] || { [ "${sb_major:-0}" -eq 1 ] && [ "${sb_minor:-0}" -lt 11 ]; }; then
|
||||
print_warning "当前 sing-box 版本 ($sb_ver) 不支持 AnyTLS,需要 1.11+,将重新安装最新版..."
|
||||
need_install=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$need_install" -eq 1 ]; then
|
||||
step "下载 Sing-box Core (最新版)..."
|
||||
local version
|
||||
version=$(curl -s https://api.github.com/repos/SagerNet/sing-box/releases/latest \
|
||||
| grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
|
||||
if [ -z "$version" ]; then
|
||||
print_error "无法获取 sing-box 最新版本,请检查网络。"
|
||||
return
|
||||
fi
|
||||
wget -q --show-progress -O /tmp/sing-box.tar.gz \
|
||||
"https://github.com/SagerNet/sing-box/releases/download/v${version}/sing-box-${version}-linux-${sb_arch}.tar.gz"
|
||||
tar -xzf /tmp/sing-box.tar.gz -C /tmp/
|
||||
mv "/tmp/sing-box-${version}-linux-${sb_arch}/sing-box" /usr/local/bin/sing-box
|
||||
chmod +x /usr/local/bin/sing-box
|
||||
rm -rf /tmp/sing-box.tar.gz "/tmp/sing-box-${version}-linux-${sb_arch}"
|
||||
fi
|
||||
|
||||
if ! apply_cert "$USER_DOMAIN" "/usr/local/etc/sing-box-anytls/cert"; then return; fi
|
||||
|
||||
local password
|
||||
password="$(rand_str 32)"
|
||||
|
||||
mkdir -p /usr/local/etc/sing-box-anytls
|
||||
cat > /usr/local/etc/sing-box-anytls/config.json <<EOF
|
||||
{
|
||||
"log": { "level": "warn" },
|
||||
"inbounds": [
|
||||
{
|
||||
"type": "anytls",
|
||||
"tag": "anytls-in",
|
||||
"listen": "::",
|
||||
"listen_port": $PORT,
|
||||
"users": [
|
||||
{ "name": "user1", "password": "$password" }
|
||||
],
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"server_name": "$USER_DOMAIN",
|
||||
"certificate_path": "/usr/local/etc/sing-box-anytls/cert/fullchain.pem",
|
||||
"key_path": "/usr/local/etc/sing-box-anytls/cert/privkey.pem"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{ "type": "direct", "tag": "direct" }
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/sing-box-anytls.service <<EOF
|
||||
[Unit]
|
||||
Description=sing-box AnyTLS Service
|
||||
After=network.target
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box-anytls/config.json
|
||||
Restart=on-failure
|
||||
LimitNOFILE=infinity
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart sing-box-anytls
|
||||
systemctl enable sing-box-anytls
|
||||
|
||||
echo "=========================================="
|
||||
print_success "AnyTLS 部署成功!"
|
||||
echo "=========================================="
|
||||
echo " 域名 (Server) : $USER_DOMAIN"
|
||||
echo " 端口 (Port) : $PORT"
|
||||
echo " 密码 (Password) : $password"
|
||||
echo "=========================================="
|
||||
echo -e "${YELLOW}【sing-box 客户端配置片段】${NC}"
|
||||
cat <<SBEOF
|
||||
{
|
||||
"type": "anytls",
|
||||
"tag": "AnyTLS-Node",
|
||||
"server": "$USER_DOMAIN",
|
||||
"server_port": $PORT,
|
||||
"password": "$password",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"server_name": "$USER_DOMAIN"
|
||||
}
|
||||
}
|
||||
SBEOF
|
||||
echo "=========================================="
|
||||
echo -e "${YELLOW}【Hiddify / 小火箭填写方式】${NC}"
|
||||
echo " 类型 : AnyTLS"
|
||||
echo " 地址 : $USER_DOMAIN"
|
||||
echo " 端口 : $PORT"
|
||||
echo " 密码 : $password"
|
||||
echo " TLS : 开启"
|
||||
echo " SNI : $USER_DOMAIN"
|
||||
echo "=========================================="
|
||||
read -n 1 -s -r -p "按任意键返回..."
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 服务管理
|
||||
# ================================================================
|
||||
manage_service() {
|
||||
local svc_name=$1
|
||||
local display_name=$2
|
||||
local uninstall_func=$3
|
||||
|
||||
clear
|
||||
echo -e "${BLUE} ── 管理 ${display_name} ────────────────────────${NC}"
|
||||
echo " 1) 启动/重启"
|
||||
echo " 2) 停止"
|
||||
echo " 3) 查看实时日志 (按 Ctrl+C 退出)"
|
||||
echo " 4) 完全卸载 ${display_name}"
|
||||
echo " 0) 返回主菜单"
|
||||
echo ""
|
||||
askline "请选择: " sel
|
||||
case $sel in
|
||||
1) systemctl restart "$svc_name"; systemctl enable "$svc_name"; print_success "已启动/重启" ;;
|
||||
2) systemctl stop "$svc_name"; print_info "已停止" ;;
|
||||
3) journalctl -u "$svc_name" -f --no-pager ;;
|
||||
4) $uninstall_func ;;
|
||||
*) return ;;
|
||||
esac
|
||||
sleep 2
|
||||
}
|
||||
|
||||
un_xray() {
|
||||
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ remove
|
||||
rm -rf /usr/local/etc/xray
|
||||
print_success "Xray 已卸载"
|
||||
}
|
||||
|
||||
un_naive() {
|
||||
systemctl stop caddy-naive 2>/dev/null || true
|
||||
systemctl disable caddy-naive 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/caddy-naive.service /usr/local/bin/caddy
|
||||
rm -rf /etc/caddy /var/lib/caddy /var/www/naive-disguise
|
||||
print_success "NaïveProxy 已卸载"
|
||||
}
|
||||
|
||||
un_singbox() {
|
||||
systemctl stop sing-box 2>/dev/null || true
|
||||
systemctl disable sing-box 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/sing-box.service /usr/local/bin/sing-box
|
||||
rm -rf /usr/local/etc/sing-box
|
||||
print_success "Sing-box 已卸载"
|
||||
}
|
||||
|
||||
un_anytls() {
|
||||
systemctl stop sing-box-anytls 2>/dev/null || true
|
||||
systemctl disable sing-box-anytls 2>/dev/null || true
|
||||
rm -f /etc/systemd/system/sing-box-anytls.service
|
||||
rm -rf /usr/local/etc/sing-box-anytls
|
||||
print_success "AnyTLS 已卸载"
|
||||
}
|
||||
|
||||
# ================================================================
|
||||
# 主菜单
|
||||
# ================================================================
|
||||
while true; do
|
||||
clear
|
||||
echo -e "${BLUE} ╔════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE} ║ 🚀 终极四合一 代理管理面板 ║${NC}"
|
||||
echo -e "${BLUE} ║ Xray(Reality/Vision) + NaïveProxy + SS-TLS + AnyTLS ║${NC}"
|
||||
echo -e "${BLUE} ╚════════════════════════════════════════════════════╝${NC}"
|
||||
echo -e " ${YELLOW}注意: 同时部署多个协议请使用不同端口!(如 443, 8443, 9443)${NC}"
|
||||
echo ""
|
||||
echo -e " ${CYAN}[安装 & 部署]${NC}"
|
||||
echo -e " ${YELLOW}1)${NC} 部署 Xray ${GREEN}(VLESS-Reality / Vision-TLS)${NC}"
|
||||
echo -e " ${YELLOW}2)${NC} 部署 NaïveProxy ${GREEN}(含 Vault 网盘伪装 - 究极隐蔽)${NC}"
|
||||
echo -e " ${YELLOW}3)${NC} 部署 Sing-box ${GREEN}(Shadowsocks + TLS 协议)${NC}"
|
||||
echo -e " ${YELLOW}4)${NC} 部署 AnyTLS ${GREEN}(sing-box,抗流量检测 - 推荐)${NC}"
|
||||
echo ""
|
||||
echo -e " ${CYAN}[管理 & 卸载]${NC}"
|
||||
echo -e " ${YELLOW}5)${NC} 管理 Xray"
|
||||
echo -e " ${YELLOW}6)${NC} 管理 NaïveProxy"
|
||||
echo -e " ${YELLOW}7)${NC} 管理 Sing-box (SS-TLS)"
|
||||
echo -e " ${YELLOW}8)${NC} 管理 AnyTLS"
|
||||
echo ""
|
||||
echo -e " ${YELLOW}0)${NC} 退出"
|
||||
echo ""
|
||||
askline "请输入选项: " choice
|
||||
case "$choice" in
|
||||
1) check_root; enable_bbr; do_install_xray ;;
|
||||
2) check_root; enable_bbr; do_install_naive ;;
|
||||
3) check_root; enable_bbr; do_install_sstls ;;
|
||||
4) check_root; enable_bbr; do_install_anytls ;;
|
||||
5) check_root; manage_service "xray" "Xray" "un_xray" ;;
|
||||
6) check_root; manage_service "caddy-naive" "NaïveProxy" "un_naive" ;;
|
||||
7) check_root; manage_service "sing-box" "Sing-box" "un_singbox" ;;
|
||||
8) check_root; manage_service "sing-box-anytls" "AnyTLS" "un_anytls" ;;
|
||||
0|q|Q) echo -e "\n${BLUE}向开源生态致敬!再见 🫡${NC}\n"; exit 0 ;;
|
||||
*) print_warning "无效选项"; sleep 1 ;;
|
||||
esac
|
||||
done
|
||||
Reference in New Issue
Block a user