抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >
海灵 · 文章导读
00:00 / 00:00
听一听这篇文章

先说结论

三步走:DD 脚本重装最新 Debian 13,装 AimiliVPN 与 WARP 两条出口隧道,最后上 Hysteria2 三个实例并封装成一份可直接分发的 Clash 订阅。

前言

一台甲骨文东京区小鸡(1G 内存),目标三个出口:本机直连、VPNGate 志愿节点中转、Cloudflare WARP,最后封装成一条 Clash 订阅地址。全文三步:

  1. DD 重装脚本换最新系统
  2. 装两条出口隧道(AimiliVPN + WARP)
  3. 装 Hysteria2,生成订阅

准备

  • 一台能 SSH 登录的 VPS,root 权限
  • 确认 TUN 可用:ls /dev/net/tun 存在即可
  • 心理准备:跨境 SSH 偶发「TCP 通但 banner 读不到」,是链路抖动不是机器挂了,脚本加重试或等一分钟再试

第一步:DD 脚本重装最新系统

用 bin456789/reinstall,走官方安装器,对甲骨文这类机器会自动选 cloud 内核变体、自动配网络:

curl -O https://raw.githubusercontent.com/bin456789/reinstall/main/reinstall.sh
bash reinstall.sh debian 13 --username root --password <你的密码>
reboot

重启后机器进入无人值守安装,SSH 断开,等 10~30 分钟再连。注意重装会清空整块系统盘,重要配置先备份到本机。

到这里算成功:

cat /etc/os-release   # 显示 13 (trixie)
uname -r # 6.x.x-cloud-amd64
ss -tlnp # 只有 sshd 在监听

第二步:装两条出口隧道

AimiliVPN(VPNGate 出口)

AimiliVPN 管理 VPNGate 公共节点,装好后在本地起一个代理,流量从 OpenVPN 隧道出站,出口 IP 就是当前志愿节点:

AIMILIVPN_NONINTERACTIVE=1 bash <(curl -Ls https://raw.githubusercontent.com/baoweise-bot/aimili-vpngate/main/install.sh)

装完终端会输出三样东西:Web 面板地址(8787 端口 + 随机路径)、面板账号密码、本地代理端口 127.0.0.1:7928。

验证出口已切换:

curl -s -x http://127.0.0.1:7928 https://api.ipify.org   # 应返回志愿节点 IP,不是本机 IP

日常管理用 ml 命令:ml status(状态)、ml logs(日志)、ml password(改面板密码,装完建议改)。它的切换策略是故障切换——当前节点失效自动换下一个,不追逐「更快」的节点,平时不用管。

WARP(Cloudflare 出口)

用 fscarmen/warp-sh,选 c 方案(Socks5 代理模式)——只在本地开代理、不动系统路由,这样才不会和 AimiliVPN 的策略路由打架:

curl -fsSL https://gitlab.com/fscarmen/warp/-/raw/main/menu.sh -o /root/warp.sh
bash /root/warp.sh c

新版客户端需要手工激活三连(缺一不可,非交互环境必须带 --accept-tos):

systemctl enable --now warp-svc
warp-cli --accept-tos mode proxy
warp-cli --accept-tos registration new
warp-cli --accept-tos connect

验证:

warp-cli --accept-tos status   # Connected
curl -s -x socks5h://127.0.0.1:40000 https://api.ipify.org # 应返回 Cloudflare IP

日常开关:warp r(断开/重连)、warp i jp(刷指定地区的出口 IP)、warp u(卸载)。

到这里算成功: 7928 和 40000 两个本地代理分别返回两个不同的出口 IP。

第三步:装 Hysteria2,生成订阅

三个出口都用 Hysteria2 承载,架构:

客户端 ──Hysteria2──> VPS
├─ UDP 443 直连出口(本机 IP)
├─ UDP 8443 中转出口(→ 127.0.0.1:7928 → VPNGate)
└─ UDP 9443 WARP出口(→ 127.0.0.1:40000 → Cloudflare)

3.1 安装与证书

curl -fsSL https://get.hy2.sh/ | bash
openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-keyout /etc/hysteria/server.key -out /etc/hysteria/server.crt \
-days 3650 -subj "/CN=www.bing.com"

3.2 直连实例

/etc/hysteria/config.yaml(完整模板见附录):

listen: :443

tls:
cert: /etc/hysteria/server.crt
key: /etc/hysteria/server.key

obfs:
type: salamander
salamander:
password: <你的混淆口令>

auth:
type: password
password: <你的密码>

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

官方 systemd 单元以 hysteria 用户运行,配置默认 root 600 会读不了,必须改属主再启动:

chown hysteria:hysteria /etc/hysteria/config.yaml /etc/hysteria/server.key /etc/hysteria/server.crt
systemctl enable --now hysteria-server.service

3.3 两个链式实例

中转实例 /etc/hysteria/config-vpngate.yaml(WARP 实例同理,只是出站地址和端口换掉):

listen: :8443
# tls / obfs / auth 同上,换一组凭据

outbounds:
- name: vpngate
type: socks5
socks5:
addr: 127.0.0.1:7928 # WARP 实例这里是 127.0.0.1:40000

acl:
inline:
- vpngate(all) # v2.12 函数式语法,出站名(all)

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

两个高频坑都在这:

  1. Hysteria2 v2.12 起 ACL 必须包在 inline: 下,规则改成函数式 出站名(all)。网上老教程的 acl: [all,vpngate] 逗号写法会直接 FATAL;
  2. 每个实例的配置都要 chown hysteria:hysteria,否则服务起不来。

第二个实例的 systemd 单元(hysteria-server-warp.service 同理,记得 Wants=warp-svc.service):

[Service]
ExecStart=/usr/local/bin/hysteria server --config /etc/hysteria/config-vpngate.yaml
WorkingDirectory=/etc/hysteria
User=hysteria
Group=hysteria
Restart=on-failure
RestartSec=5

验证三个出口:本地各起一个 hysteria client 指向 443/8443/9443,socks5 出口 curl api.ipify.org,看到三个不同的 IP 就成了。

3.4 生成订阅

三个出口封装成一条订阅。一个几十行的 Python 小服务挂在 8788 端口:随机路径防扫描,按路径返回 Clash YAML 和 base64 通用格式两份文件,systemd 守护(完整代码见附录)。

订阅内容就是一份完整 Clash 配置:proxies 写三个节点(443 直连 udp: true;8443/9443 两个链式节点因为上游 SOCKS5 只支持 TCP,标 udp: false),proxy-groups 放节点选择/自动选择(url-test)/故障转移(fallback) 加几个服务组,rules 用 MetaCubeX 规则集 做国内外分流。

一个值得做的细节:订阅名是从响应头读的,加上两行,用户导入时自动显示你想要的名字:

self.send_header("Content-Disposition", "attachment; filename=<订阅名>")
self.send_header("profile-title", "<订阅名>")

最后提醒一个客户端侧的坑:Clash Party / Verge 类客户端的**「覆写」功能会把你订阅里的分组整个重写**(冒出一堆「香港节点/台湾节点」占位组)。导入后分组数量对不上,就去客户端覆写页面停用脚本再刷新订阅。

踩坑汇总

现象 原因 处理
SSH 偶发 banner 超时 跨境链路抖动 加重试,等一分钟再试
hysteria 起不来,日志 permission denied 官方单元以 hysteria 用户跑,配置是 root 600 配置/证书 chown 给 hysteria
FATAL: ‘acl’ expected a map or struct v2.12 ACL 必须包在 inline 下 acl: inline: + 列表
FATAL: invalid syntax: all,vpngate 旧逗号语法废弃 函数式 - 出站名(all)
warp-cli 报 Registration Missing 新版要先注册设备 warp-cli --accept-tos registration new
导入订阅冒出几十个分组 客户端「覆写」脚本改写订阅 停用覆写,刷新订阅
重装后服务全没了 重装本来就是全盘清空 重要配置先备份到本机

总结

三步走完:一台 1G 小鸡上跑起三个出口加一条可分发的订阅,内存占用不到 300MB。两条经验:链式出站的本质是「本地代理串联」,任何能开本地 socks5 的工具都能变成 Hysteria2 的一个出站;订阅名、分组这类小体验决定了分发成本,两个响应头就能让用户导入即用,值得做。

附录

直连实例完整配置见 3.2,链式实例见 3.3,密码与混淆口令全部换成自己的随机串(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 20)。

订阅服务 server.py 完整代码:

#!/usr/bin/env python3
import http.server, socketserver, os

TOKEN = "<随机16位hex,防扫描>"
BASE = "/opt/clash-sub"
SUB_NAME = "<你的订阅名>"

FILES = {
TOKEN + "/clash.yaml": ("clash.yaml", "text/plain; charset=utf-8", SUB_NAME),
TOKEN + "/v2ray.txt": ("v2ray.txt", "text/plain; charset=utf-8", SUB_NAME),
}

class H(http.server.BaseHTTPRequestHandler):
def do_GET(self):
path = self.path.split("?")[0].strip("/")
if path in FILES:
fn, ct, name = FILES[path]
data = open(os.path.join(BASE, fn), "rb").read()
self.send_response(200)
self.send_header("Content-Type", ct)
self.send_header("Content-Length", str(len(data)))
self.send_header("Content-Disposition", "attachment; filename=" + name)
self.send_header("profile-title", name)
self.end_headers()
self.wfile.write(data)
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"not found")

def log_message(self, *a):
pass

socketserver.ThreadingTCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer(("0.0.0.0", 8788), H) as httpd:
httpd.serve_forever()

配套 systemd 单元:

[Unit]
Description=Clash subscription server
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/clash-sub/server.py
Restart=always

[Install]
WantedBy=multi-user.target

参考

评论




站点访问量 Loading… 站点访客数 Loading…