#!/usr/bin/env bash # gost sidecar 一键安装 (Ubuntu/Debian) # 本机 127.0.0.1:28888 明文 HTTP 代理 -> mtls 加密隧道 -> 出口 64.186.233.238 # # 用法: # curl -fsSL https://claude.dahe2016.com/sidecar.sh | sudo bash -s -- <密码> # curl -fsSL https://claude.dahe2016.com/sidecar.sh | sudo bash -s -- <密码> <用户名> # # 二进制与脚本托管在 claude.dahe2016.com;出口仍是 238:9444(不动)。 set -euo pipefail PASS="${1:-}"; USER_NAME="${2:-pxzm33ufi}" # 隧道用户名(默认 pxzm33ufi);密码运行时传第1参数 if [ -z "$PASS" ]; then echo "用法: curl -fsSL https://claude.dahe2016.com/sidecar.sh | sudo bash -s -- <密码>" >&2 exit 1 fi UPSTREAM_ADDR="64.186.233.238:9444" # 落地机 mtls 端点(出口,不动) UPSTREAM_SNI="us.dahe2017.com" # 238 的证书 CN,用于 SNI 校验(不动) LISTEN="127.0.0.1:28888" # 本地监听(只绑 loopback) MIRROR="https://claude.dahe2016.com" # 二进制/脚本镜像(本站) MIRROR_HOST="claude.dahe2016.com" # DNS 兜底用 MIRROR_IP="8.140.35.255" # DNS 不可用时 --resolve 到这个 IP [ "$(id -u)" -eq 0 ] || { echo "请用 root 或 sudo 运行" >&2; exit 1; } command -v systemctl >/dev/null || { echo "需要 systemd" >&2; exit 1; } command -v curl >/dev/null || { echo "需要 curl" >&2; exit 1; } # ---------- 1. 二进制 ---------- if [ -x /usr/local/bin/gost3 ]; then echo "[1/4] gost3 已存在,跳过下载" else case "$(uname -m)" in x86_64|amd64) ARCH=amd64 ;; aarch64|arm64) ARCH=arm64 ;; *) echo "不支持的架构: $(uname -m)" >&2; exit 1 ;; esac TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT echo "[1/4] 下载 gost (${ARCH})..." if ! curl -fsSL --max-time 180 "${MIRROR}/gost3-${ARCH}" -o "$TMP/gost3"; then echo " 域名方式失败,改用 IP 直连..." curl -fsSL --max-time 180 --resolve "${MIRROR_HOST}:443:${MIRROR_IP}" \ "${MIRROR}/gost3-${ARCH}" -o "$TMP/gost3" || { echo "下载失败。请手动放置 gost3 到 /usr/local/bin/gost3 后重跑。" >&2; exit 1; } fi install -m 755 "$TMP/gost3" /usr/local/bin/gost3 fi /usr/local/bin/gost3 -V >/dev/null 2>&1 || { echo "gost3 无法执行" >&2; exit 1; } # ---------- 2. 非特权账号 ---------- echo "[2/4] 创建运行账号 gost..." id gost >/dev/null 2>&1 || useradd -r -s /usr/sbin/nologin -M gost # ---------- 3. 配置 ---------- echo "[3/4] 写入 /etc/gost/sidecar.yaml..." mkdir -p /etc/gost cat > /etc/gost/sidecar.yaml < /etc/systemd/system/gost-sidecar.service <<'EOF' [Unit] Description=gost sidecar: localhost plain HTTP -> encrypted tunnel to exit node After=network-online.target Wants=network-online.target [Service] Type=simple User=gost ExecStart=/usr/local/bin/gost3 -C /etc/gost/sidecar.yaml Restart=always RestartSec=3 LimitNOFILE=65536 NoNewPrivileges=true PrivateTmp=true [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable gost-sidecar >/dev/null 2>&1 systemctl restart gost-sidecar sleep 3 # ---------- 验证 ---------- echo if ! systemctl is-active --quiet gost-sidecar; then echo "❌ 服务未启动。排查: journalctl -u gost-sidecar -n 30 --no-pager" >&2 exit 1 fi echo "服务: active 监听: ${LISTEN}" # mtls 隧道刚重启是冷的,头一两发可能慢/空 —— 重试几次,热了就秒过 EXIT_IP="" for _try in 1 2 3 4 5 6; do EXIT_IP=$(curl -s --max-time 15 -x "http://${LISTEN}" https://api.ipify.org 2>/dev/null || true) [ -n "$EXIT_IP" ] && break sleep 2 done if [ "$EXIT_IP" = "64.186.233.238" ]; then echo "✅ 出口 IP = ${EXIT_IP} 安装成功" else AUTHFAIL=$(journalctl -u gost-sidecar -n 40 --no-pager 2>/dev/null \ | grep -ci 'auth' || true) cat >&2 <