Knowledge Archive
Summary · AI

VPS代理节点部署手册

AI 2026-06-05 · 26 min read · 1 backlinks
VPS部署代理XrayHysteria2Trojan运维

VPS 代理节点部署手册

从零部署一个三协议代理节点(VLESS Reality + Hysteria2 + Trojan)的完整 SOP。 最新实践:2026-06-05 部署 vps(xTom 圣何塞,CN2 GIA)。蓝本:zgo-la / bytevirt-la-cn2。

架构总览

text
客户端
   │
   ├─ TCP :443 ──→ nginx stream ──→ Xray VLESS Reality (127.0.0.1:10443)
   │                                  伪装 www.microsoft.com,无需自有证书
   │
   ├─ TCP :8444 ─→ Xray Trojan (TLS, Let's Encrypt 证书)
   │
   └─ UDP :8443 ─→ Hysteria2 (QUIC, Let's Encrypt 证书)
                    + iptables 端口跳跃 65000-65442 → 8443

端口分工:

端口协议监听说明
443/tcpnginx stream0.0.0.0转发到 Reality
10443/tcpVLESS Reality127.0.0.1Xray,伪装 microsoft
8444/tcpTrojan0.0.0.0Xray inbound,TLS
8443/udpHysteria20.0.0.0QUIC
65000-65442/udp端口跳跃iptables REDIRECT → 8443
80/tcpnginx http0.0.0.0certbot HTTP-01 验证 + 跳转
10085/tcpXray stats API127.0.0.1流量统计

协议选择理由:

  • VLESS Reality — 抗检测最强,借用大厂域名 SNI(microsoft),无需自有证书
  • Hysteria2 — QUIC 协议,低延迟(比 TCP 少 1 个 RTT),抗丢包,日常首选;UDP 被封时靠端口跳跃续命
  • Trojan — TCP+TLS 保底,HY2 全挂时的回落方案;Surge 唯一能用的自建协议(Surge 不支持 VLESS)

前置条件

  1. 域名解析proxy-<别名>.seesaw.icu → VPS IP,Cloudflare DNS Only(不开橙色云,certbot HTTP-01 需要直连)
  2. SSH 配置~/.ssh/config 加好别名,公钥已上机
  3. 系统:Ubuntu 22.04 / 24.04

部署步骤

1. 装基础软件包

bash
export DEBIAN_FRONTEND=noninteractive
apt-get update

# iptables-persistent 会弹交互框,先预设答案
echo 'iptables-persistent iptables-persistent/autosave_v4 boolean true' | debconf-set-selections
echo 'iptables-persistent iptables-persistent/autosave_v6 boolean true' | debconf-set-selections

apt-get install -y nginx libnginx-mod-stream ufw fail2ban \
  certbot python3-certbot-nginx curl mtr bc iptables-persistent

坑 1:Ubuntu 的 nginx 不自带 stream 模块,必须装 libnginx-mod-stream,否则 nginx -tunknown directive "stream"坑 2iptables-persistent 不预设 debconf 会卡交互框导致整批 apt 失败。 坑 3:若机器之前残留 ufwrc 状态(dpkg -l 显示 rc),需 apt-get install --reinstall ufw

2. 开启 BBR

bash
cat >> /etc/sysctl.conf << 'EOF'
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
sysctl -p
sysctl net.ipv4.tcp_congestion_control   # 确认输出 bbr

BBR 是跨境黄金组合的一半。不开 BBR,晚高峰高 RTT+丢包下 CUBIC 会让 Hy2 崩溃。

3. 装 Xray + Hysteria2

bash
# Xray 官方脚本
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install

# Hysteria2 官方脚本
bash <(curl -fsSL https://get.hy2.sh/)

# 验证
/usr/local/bin/xray version
/usr/local/bin/hysteria version

4. 签 TLS 证书(HY2 + Trojan 需要)

bash
# 临时 nginx 占 80 端口给 certbot 验证
cat > /etc/nginx/sites-available/default << 'EOF'
server {
    listen 80 default_server;
    server_name proxy-<别名>.seesaw.icu;
    location /.well-known/acme-challenge/ { root /var/www/html; }
    location / { return 200 'ok'; }
}
EOF
mkdir -p /var/www/html
nginx -t && systemctl restart nginx && systemctl enable nginx

certbot certonly --webroot -w /var/www/html \
  -d proxy-<别名>.seesaw.icu \
  --non-interactive --agree-tos -m admin@seesaw.icu

坑 4(关键):Xray 以 nobody、Hysteria 以 hysteria 用户运行,默认读不了 /etc/letsencrypt/live/(权限 700)。必须放权限,否则服务启动报 permission denied

bash
chmod -R 755 /etc/letsencrypt/live /etc/letsencrypt/archive

5. 生成 Reality 密钥 + UUID

bash
/usr/local/bin/xray x25519   # 得到 PrivateKey / Password(PublicKey)
/usr/local/bin/xray uuid     # 得到 UUID

记下:PrivateKey(服务端用)、PublicKey(客户端用)、UUID

6. 写 Xray 配置

/usr/local/etc/xray/config.json(替换 <别名>):

json
{
  "log": { "loglevel": "warning", "access": "/var/log/xray/access.log", "error": "/var/log/xray/error.log" },
  "stats": {},
  "api": { "tag": "api", "services": ["StatsService"] },
  "policy": { "system": { "statsInboundUplink": true, "statsInboundDownlink": true } },
  "inbounds": [
    {
      "tag": "proxy-in",
      "listen": "127.0.0.1", "port": 10443,
      "protocol": "vless",
      "settings": { "clients": [ { "id": "", "flow": "xtls-rprx-vision" } ], "decryption": "none" },
      "streamSettings": {
        "network": "tcp", "security": "reality",
        "realitySettings": { "dest": "www.microsoft.com:443", "serverNames": ["www.microsoft.com"], "privateKey": "", "shortIds": ["abcd1234"] }
      },
      "sniffing": { "enabled": true, "destOverride": ["http","tls","quic"] }
    },
    { "listen": "127.0.0.1", "port": 10085, "protocol": "dokodemo-door", "settings": { "address": "127.0.0.1" }, "tag": "api" },
    {
      "tag": "trojan-in",
      "listen": "0.0.0.0", "port": 8444, "protocol": "trojan",
      "settings": { "clients": [ { "password": "seesaw-trojan-2026" } ] },
      "streamSettings": {
        "network": "tcp", "security": "tls",
        "tlsSettings": { "certificates": [ { "certificateFile": "/etc/letsencrypt/live/proxy-<别名>.seesaw.icu/fullchain.pem", "keyFile": "/etc/letsencrypt/live/proxy-<别名>.seesaw.icu/privkey.pem" } ] }
      }
    }
  ],
  "outbounds": [ { "protocol": "freedom", "tag": "direct" } ],
  "routing": { "rules": [ { "inboundTag": ["api"], "outboundTag": "api", "type": "field" } ] }
}

# 测试
/usr/local/bin/xray -test -config /usr/local/etc/xray/config.json

Reality 监听非 443 端口(10443)会有 warning,无害——因为前面有 nginx 在 443 分流。

7. 写 Hysteria2 配置

/etc/hysteria/config.yaml

yaml
listen: :8443

tls:
  cert: /etc/letsencrypt/live/proxy-<别名>.seesaw.icu/fullchain.pem
  key: /etc/letsencrypt/live/proxy-<别名>.seesaw.icu/privkey.pem

auth:
  type: password
  password: seesaw-hy2-2026

masquerade:
  type: proxy
  proxy:
    url: https://www.bing.com
    rewriteHost: true

8. 配置 nginx stream(443 转发到 Reality)

/etc/nginx/nginx.conf 末尾追加(与 http {} 同级):

nginx
stream {
    server {
        listen 443 reuseport;
        proxy_pass 127.0.0.1:10443;
    }
}

说明:纯代理节点不托管订阅,无需 SNI 分流,443 直接全转发给 Reality 即可。 若该机还要在 443 上托管订阅(订阅服务器场景),才需要 map $ssl_preread_server_name 按 SNI 分流到 nginx http(10444) 或 xray(10443)。纯节点不需要 10444。

/etc/nginx/sites-available/default 只保留 80(给 certbot 续签):

nginx
server {
    listen 80 default_server;
    server_name proxy-<别名>.seesaw.icu;
    location /.well-known/acme-challenge/ { root /var/www/html; }
    location / { return 301 https://$host$request_uri; }
}

9. 启动所有服务

bash
nginx -t
systemctl restart nginx && systemctl enable nginx
systemctl restart xray && systemctl enable xray
systemctl restart hysteria-server && systemctl enable hysteria-server

# 确认全 active
for s in nginx xray hysteria-server; do systemctl is-active $s; done

10. HY2 端口跳跃(抗 UDP 封锁)

bash
iptables -t nat -A PREROUTING -p udp --dport 65000:65442 -j REDIRECT --to-ports 8443
iptables-save > /etc/iptables/rules.v4

晚高峰部分宽带运营商封 UDP,端口跳跃让运营商难以精准封杀。客户端 HY2 端口字段写 65000-65442

11. 安全加固

bash
# UFW
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
for r in 22/tcp 80/tcp 443/tcp 8444/tcp 8443/udp 65000:65442/udp; do ufw allow $r; done
ufw --force enable

# fail2ban
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
maxretry = 5
bantime = 3600
findtime = 600
EOF
systemctl restart fail2ban && systemctl enable fail2ban

12. 证书续签自动化(关键)

证书续签后会重置 live/ 目录权限,导致 Xray/HY2 读不了。装 deploy hook 自动修复 + 重启:

bash
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
cat > /etc/letsencrypt/renewal-hooks/deploy/restart-proxy.sh << 'EOF'
#!/bin/bash
chmod -R 755 /etc/letsencrypt/live /etc/letsencrypt/archive
systemctl restart xray hysteria-server nginx
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-proxy.sh

13. SSH 端口加固(可选)

把 SSH 从 22 改到非标端口,挡掉绝大多数自动化扫描/爆破。保留密码登录作兜底(失联时可用初始密码从机房 VNC 救回)。

坑 5(Ubuntu 22.04+ socket 激活):Ubuntu 新版用 ssh.socket 管端口(socket activation),直接改 sshd_config 的 Port 不生效。而且有个 systemd generator(/run/systemd/generator/ssh.socket.d/addresses.conf)会读 sshd_config 的 Port 自动生成 socket 监听——所以改端口要让 generator 按 sshd_config 重新生成,而不是手动改 socket。

安全步骤(全程不切断现有连接,先双端口验证再关旧口):

bash
NEWPORT=<非标端口>   # 自己选,别写进公网文档

# 1. UFW 先放行新端口(旧 22 暂留)
ufw allow ${NEWPORT}/tcp

# 2. sshd drop-in 配置(只写新端口,不要保留 Port 22,否则 generator 会把 22 加回来)
cat > /etc/ssh/sshd_config.d/99-custom-port.conf << EOF
Port ${NEWPORT}
PasswordAuthentication yes
PubkeyAuthentication yes
EOF
sshd -t   # 测试语法

# 3. 重启 socket(generator 会按新 Port 重新生成监听)
systemctl daemon-reload
systemctl restart ssh.socket
ss -tlnp | grep ssh   # 确认监听新端口

# 4. 【关键】另开一个终端用新端口登录测试,确认能进
#    ssh -p <新端口> root@   ← 必须成功再继续!

# 5. 验证通过后撤掉 22 的 UFW 放行
ufw delete allow 22/tcp

铁律:关旧端口前,务必保持一个活着的 SSH 连接 + 用新端口实测登录成功。万一改崩,活连接是救命通道。本地 ~/.ssh/config 给该 Host 加 Port <新端口>,之后 ssh <别名> 直连。

14. 哪吒探针(监控)

agent 上报到哪吒面板(本项目面板在 tc-sv,域名 monitor.seesaw.icu)。哪吒 v1 用 client_secret 自动注册:

bash
curl -L https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.sh -o /tmp/nezha-install.sh
NZ_SERVER='<面板IP>:8008' \
NZ_CLIENT_SECRET='<面板密钥>' \
NZ_UUID="$(cat /proc/sys/kernel/random/uuid)" \
NZ_TLS=false \
NZ_DISABLE_COMMAND_EXECUTE=true \
bash /tmp/nezha-install.sh

NZ_DISABLE_COMMAND_EXECUTE=true 关掉面板对 agent 的远程命令执行,更安全。client_secret 从面板现有 agent 的 /opt/nezha/agent/config.yml 取,或面板后台「设置」里看。

加入订阅

订阅文件托管在 tc-sv(主)+ zgo-la(备),路径 /var/www/sub//。 clash.yaml 加 3 个节点(全协议),surge.conf 只加 HY2 + Trojan(Surge 不支持 VLESS)。

clash.yaml 节点格式

yaml
- name: <别名>-VLESS
  type: vless
  server: 
  port: 443
  uuid: 
  network: tcp
  udp: true
  tls: true
  flow: xtls-rprx-vision
  client-fingerprint: chrome
  reality-opts:
    public-key: 
    short-id: abcd1234
  servername: www.microsoft.com

- name: <别名>-HY2
  type: hysteria2
  server: 
  port: 8443
  password: seesaw-hy2-2026
  sni: proxy-<别名>.seesaw.icu
  skip-cert-verify: false
  alpn: [h3]
  up: 200 mbps
  down: 200 mbps

- name: <别名>-Trojan
  type: trojan
  server: 
  port: 8444
  password: seesaw-trojan-2026
  sni: proxy-<别名>.seesaw.icu
  skip-cert-verify: false
  udp: true

记得把节点名加进 proxy-groupsProxy 选择组。

surge.conf 节点格式

ini
<别名>-HY2 = hysteria2, , 8443, password=seesaw-hy2-2026, sni=proxy-<别名>.seesaw.icu
<别名>-Trojan = trojan, , 8444, password=seesaw-trojan-2026, sni=proxy-<别名>.seesaw.icu

部署到双订阅服务器

bash
# clash.yaml 改动建议在本地用 python yaml 处理(保留全局配置/sniffer/规则),再 scp
for host in tc-sv zgo-la; do
  scp clash_new.yaml $host:/tmp/clash.yaml
  scp surge_new.conf $host:/tmp/surge.conf
  ssh $host "sudo cp /tmp/clash.yaml /var/www/sub//clash.yaml && \
             sudo cp /tmp/surge.conf /var/www/sub//surge.conf && \
             sudo chown www-data:www-data /var/www/sub//{clash.yaml,surge.conf}"
done

zgo-la 的 nginx 把订阅服务放在 conf.d/sub.conf,但其 nginx.conf 默认不 include conf.d,需手动在 http{} 块加 include /etc/nginx/conf.d/*.conf;

验证

bash
# 1. 订阅含新节点
curl -s "https://sub.seesaw.icu//clash.yaml" | grep -c "<别名>"

# 2. Reality 443 TCP 连通
timeout 5 bash -c "echo > /dev/tcp//443" && echo "443 OPEN"

# 3. Trojan 8444 TLS 握手(应 Verify return code: 0)
echo | openssl s_client -connect :8444 -servername proxy-<别名>.seesaw.icu 2>/dev/null | grep "Verify return"

客户端刷新订阅后,挨个测三个节点连通 + 访问 ip.sb 确认出口 IP。

客户端注意事项

  • Clash Verge Rev (mihomo):支持全部三协议
  • Surge:仅 HY2 + Trojan(无 VLESS)
  • TUN 模式 snifferoverride-destination: true 会把节点 server IP 覆盖成 SNI 域名解析的 IP——若用 CF 优选 IP 做 server,需在 sniffer 加 skip-domain。纯 Reality/HY2/Trojan 节点用真实 IP 不受影响。
  • 日常默认挂 HY2,不要挂 VLESS:跨境高 RTT+丢包环境下,HY2(QUIC + Brutal 拥塞控制,无视丢包硬怼带宽)实测带宽是 VLESS(TCP,拥塞控制保守)的 4-5 倍(实测同台节点 265M vs 56M,见 个人服务器资产清单 实测带宽对比)。VLESS-Reality 的价值在抗检测/抗封锁(伪装大厂 SNI),留作 HY2 被封(UDP 被运营商掐)时的兜底,不是日常首选。

常见坑速查

现象原因解决
nginx -t 报 unknown directive "stream"缺 stream 模块apt install libnginx-mod-stream
xray/hysteria 启动 permission denied证书目录 700chmod -R 755 /etc/letsencrypt/{live,archive}
apt 安装卡住/brokeniptables-persistent 交互debconf-set-selections 预设
ufw: command not foundrc 残留状态apt install --reinstall ufw
续签后节点全挂续签重置权限deploy hook 自动 chmod+重启
晚高峰 HY2 超时UDP 被封 / CUBIC 崩端口跳跃 + 开 BBR

关联