想自己搭一个代理节点,很多人会卡在”不知道从哪开始”:用什么系统?怎么连上服务器?连上之后怎么让 Clash 用起来?这篇教程把整条线一次讲透——选系统、SSH 登录、装 Xray、配好节点、再把配置做成订阅链接导入 Clash,一步不落。我用的是 Ubuntu 24.04 LTS,同样的方法也适用于几乎所有主流 Linux 发行版。
本文由 宝藏库 整理发布,站内还有更多 Ubuntu 服务器运维、自建节点、Clash 使用与避坑教程,欢迎收藏、方便随时查阅。

一、先选系统:服务器和本机各用什么
服务器端推荐 Ubuntu 22.04 / 24.04 LTS(本教程以 24.04 为例)。理由很简单:包新、文档多、用 systemd 管理服务顺手;Debian 12/11、Rocky、AlmaLinux 也完全可以,只是个别命令略有差异。选机提醒:如果你会用比较旧的 CentOS 7,建议直接换新的,免得后面依赖版本和命令都对不上。
本机(你用来连接和跑 Clash 的那台)不限系统:Windows、macOS、Linux 都行,只要自带 SSH 客户端。Windows 用 PowerShell 或终端即可,也可以用 Xshell;macOS/Linux 直接开终端。
有一点要先明确:如果目的是访问境外服务,服务器必须位于海外;而且线路好坏直接决定”快不快”——想长期稳定高速,优先选日本 IIJ/SoftBank 或带 CN2 GIA 回程的线路。
二、准备清单:开工前确认四样东西
- 一台海外 Ubuntu 服务器,记下公网 IP 和 root 密码;
- 一个能连服务器的 SSH 工具(PowerShell、macOS 终端、Xshell 任选其一);
- 本地装好 Clash Meta 客户端,推荐 Clash Verge Rev;
- 会复制粘贴命令,能看懂简单报错就可以了。
三、第一步:用 SSH 连接服务器
在 Windows PowerShell、macOS 或 Linux 终端里输入(把 IP 换成你的):
ssh root@你的服务器IP
第一次连接会提示是否信任主机指纹,输入 yes 回车;接着输入密码(输入时屏幕不显示是正常的)。看到 [root@xxx ~]# 这样的提示符,就说明登录成功了。常见报错:
Connection refused/ 超时:IP 或端口不对,或服务器防火墙没放行 22;Permission denied (publickey,password):密码错误,或服务器没开启密码登录(需要PasswordAuthentication yes)。
四、第二步:基础准备与环境检查
先更新软件源(Ubuntu/Debian 用 apt;Rocky/Alma 用 dnf):
apt update && apt upgrade -y
再确认端口占用、防火墙和磁盘,避免和后续服务冲突:
ss -tlnp # 查看当前监听的端口
ufw status # 查看防火墙状态
df -h / # 查看磁盘剩余
which xray v2ray sing-box # 是否装过别的代理
只要 443 端口空闲,下一步直接用 443 最理想。
五、第三步:安装 Xray-core
用 XTLS 官方安装脚本,一条命令装好二进制、GeoIP/GeoSite 数据和 systemd 服务:
curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh -o /tmp/install-release.sh
bash /tmp/install-release.sh install
装完确认版本:
/usr/local/bin/xray version
看到 Xray ... (Xray, Penetrates Everything.) 即成功。配置文件在 /usr/local/etc/xray/config.json,日志在 /var/log/xray/,这两个位置后面会用到。
六、第四步:生成 UUID 与 Reality 密钥
这一步产出三样东西:UUID、Reality 私钥、Reality 公钥。都靠 Xray 自带命令生成:
/usr/local/bin/xray uuid
/usr/local/bin/xray x25519
输出类似:
PrivateKey: 服务端私钥
Password (PublicKey): 服务端公钥
Hash32: ......
PrivateKey(私钥)只准留在服务器;PublicKey(公钥)是写进 Clash 客户端给人看的。弄反了所有客户端都连不上,务必分开保存。
坑 1:不同版本的 xray,密钥输出格式不一样。
老版本(如 v1.8.x)输出
Private key:、Public key:;新版输出PrivateKey:、Password (PublicKey):。写脚本自动解析前,先手动跑一次xray x25519看格式;取错列会得到空字符串,启动报empty "privateKey"。
七、第五步:编写 VLESS+Reality 服务端配置
编辑配置文件:
vim /usr/local/etc/xray/config.json
写入以下内容(占位符替换成第六步生成的值):
{
"log": {
"loglevel": "warning",
"error": "/var/log/xray/error.log",
"access": "/var/log/xray/access.log"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "你的UUID",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"dest": "cp.cloudflare.com:443",
"xver": 0,
"serverNames": ["cp.cloudflare.com"],
"privateKey": "你的服务端私钥",
"shortIds": ["你的shortId"]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
}
]
}
7.1 关键字段逐个说明
port: 443:对外端口,长得最像正常 HTTPS 流量;flow: xtls-rprx-vision:XTLS Vision 流控,客户端必须填一样的 flow;dest与serverNames:伪装目标,客户端 SNI 必须包含在serverNames里;privateKey:服务器私钥,只填写在这里;shortIds:短 ID,用openssl rand -hex 4生成 8 位十六进制;sniffing:流量嗅探,便于后续做国内/国外分流。
7.2 最关键的坑:伪装目标不要选 www.microsoft.com
坑 2:参数全对也连不上?先换 dest 站点。
我最初把
dest和serverNames配成www.microsoft.com,UUID、密钥、shortId 全部核对无误,客户端却始终连不上,日志反复出现:REALITY: processed invalid connection from 127.0.0.1:xxxxx: handshake did not complete successfully用服务器上同一个 Xray 做回环测试、换版本也都一样。定位后发现是微软 CDN(Akamai)拒绝数据中心 IP 的这类握手。把伪装目标换成
cp.cloudflare.com或www.apple.com后立刻恢复。排障顺序记住:先核对参数 → 再换 dest 站点 → 最后才怀疑版本。
八、第六步:校验、启动并设为开机自启
先做语法校验,看到 Configuration OK. 再启动:
/usr/local/bin/xray run -test -config /usr/local/etc/xray/config.json
通过后重启、设自启、确认 443 在监听:
systemctl restart xray
systemctl enable xray
systemctl is-active xray
ss -lntp | grep :443
排障提示:默认日志级别 warning,连接失败可能不落盘。排查时把
loglevel临时改成 debug 并指定 error 日志路径,重启再测就能看到REALITY: processed invalid connection这类原因;查完改回 warning。
九、第七步:放行防火墙端口
启用防火墙前必须先放行 SSH,否则可能把自己锁在门外:
ufw allow OpenSSH
ufw allow 443/tcp
ufw --force enable
ufw status verbose
注意:VPS 商家控制面板若有云防火墙,也要放行 443/TCP。
十、第八步:先在本机用 Clash 跑通(再去做订阅)
在动手做订阅链接前,先用本地配置文件确认节点可用。
proxies:
- name: "我的Reality节点"
type: vless
server: 你的服务器IP
port: 443
uuid: 你的UUID
network: tcp
udp: true
tls: true
flow: xtls-rprx-vision
servername: cp.cloudflare.com
client-fingerprint: chrome
reality-opts:
public-key: 你的服务端公钥
short-id: 你的shortId
proxy-groups:
- name: "节点选择"
type: select
proxies:
- "我的Reality节点"
- "自动选择"
- name: "自动选择"
type: url-test
url: "http://www.gstatic.com/generate_204"
interval: 300
proxies:
- "我的Reality节点"
rules:
- DOMAIN-SUFFIX,openai.com,节点选择
- DOMAIN-SUFFIX,chatgpt.com,节点选择
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- GEOSITE,cn,DIRECT
- GEOIP,CN,DIRECT
- MATCH,节点选择
要点:public-key 填公钥、uuid 和 short-id 与服务器一致;servername 等于 serverNames 的域名;要”国内直连、国外走节点”就把运行模式选规则而不是全局。测一遍延迟、验证出口 IP 是服务器 IP,确认能用,再进行下一步。
十一、第九步:把配置做成订阅链接,导入 Clash
本地能跑通之后,把同一份配置放到服务器,用一个常驻服务按随机路径提供,就得到类似 http://你的服务器IP:8088/你的订阅令牌/你的配置文件.yaml 的订阅链接。Clash 导入后,以后改配置上传覆盖、点”更新”即可同步。
11.1 在服务器上放配置文件
先建目录并把配置文件放进去(用你上面那段 YAML):
mkdir -p /var/www/sub
# 把上面的 YAML 保存为 /var/www/sub/你的配置文件.yaml
# 或直接本地编辑好后用 scp 上传:
scp 你的配置文件.yaml root@你的服务器IP:/var/www/sub/
11.2 起一个常驻的订阅服务
为保证只有”随机路径”能访问、且不列目录,用下面的单文件服务(仅提供你指定的那个路径)。把它保存为 /opt/sub-server/sub-server.py:
#!/usr/bin/env python3
# 订阅文件服务:只提供 /令牌/文件名 这一个路径,其它一律 404
import http.server
TOKEN = "你的订阅令牌" # 换成一段随机字符串,如 12 位十六进制
FILE = "/var/www/sub/你的配置文件.yaml"
PORT = 8088
class Handler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path in ("/" + TOKEN + "/你的配置文件.yaml",
"/" + TOKEN + "/你的配置文件.yaml/"):
data = open(FILE, "rb").read()
self.send_response(200)
self.send_header("Content-Type", "text/yaml; charset=utf-8")
self.send_header("Content-Length", str(len(data)))
self.send_header("Cache-Control", "no-cache")
self.end_headers()
self.wfile.write(data)
else:
self.send_response(404)
self.end_headers()
def log_message(self, *a):
pass
http.server.ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
注册为 systemd 服务并启动:
cat > /etc/systemd/system/sub-server.service <<'EOF'
[Unit]
Description=Subscription file server
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/sub-server/sub-server.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable sub-server
systemctl restart sub-server
ufw allow 8088/tcp
ss -lntp | grep :8088
看到服务 active、8088 在监听即成功。
11.3 得到订阅链接并导入 Clash
你的订阅链接就是:
http://你的服务器IP:8088/你的订阅令牌/你的配置文件.yaml
在 Clash Verge Rev 里:左侧「订阅 / Profiles」→ 右上角 + 新建 → 粘贴上面的链接 → 导入 → 激活该配置。以后要更新,右键这条订阅点「更新」即可;服务器端改了配置,重新上传覆盖同名文件、再更新一次就能同步。
安全提示:订阅链接里的随机令牌相当于一把钥匙——链接一旦公开,你的节点就等于公之于众了。所以不要把订阅链接发到群里、截图到博客,路径要足够长、足够随机。
十二、第十步:整体验证
本地用代理访问外网,确认出口 IP 是服务器:
curl -x http://127.0.0.1:7897 "http://ip-api.com/json/?fields=query,country,city,isp"
返回里的 query 等于服务器 IP,即链路正常。再直接访问订阅链接应返回 200:
curl -s -o /dev/null -w "%{http_code}\n" "http://你的服务器IP:8088/你的订阅令牌/你的配置文件.yaml"
十三、可选:启用 BBR 加速
Ubuntu 24.04 默认已启用,可先确认;若不是 bbr 和 fq,手动开启并写入持久配置:
sysctl net.ipv4.tcp_congestion_control net.core.default_qdisc
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq
echo 'net.core.default_qdisc = fq' > /etc/sysctl.d/99-bbr.conf
echo 'net.ipv4.tcp_congestion_control = bbr' >> /etc/sysctl.d/99-bbr.conf
十四、常见问题排查
- SSH 连接被拒或超时:核对 IP/端口、服务器防火墙、VPS 云防火墙是否放行 22;
- SSH 提示 Permission denied:密码错误,或服务器未开启
PasswordAuthentication; - 纯 VLESS 能通、加 Reality 连不上:优先换 dest 站点为
cp.cloudflare.com或www.apple.com; - 日志报
empty "privateKey":密钥字段解析出错,先跑xray x25519看格式; - Clash 测延迟成功但打不开网页:检查是否全局模式导致规则失效,必要时开 TUN;
- 导入订阅后节点没刷新:确认订阅链接可访问、允许自动更新,或手动点「更新」。
十五、安全提醒
- 节点参数(UUID、公钥、订阅令牌)就是代理的钥匙,不要发到博客、截图或公开群聊——这也是本文全程使用占位符的原因;
- 服务器 root 密码若被多方接触过,建议改用 SSH 密钥登录并关闭密码登录;
- 自建节点请遵守服务器所在地法律与商家服务条款,仅供自己设备使用。
至此,一台 Ubuntu 服务器从选系统到 Clash 订阅链接的完整流程就通了。最值得记住的两点:先在本机把节点跑通、再去做订阅链接;订阅令牌就是钥匙,别外传。照这条线走,基本不会卡在中间某一步。
如果你按本教程搭好了自己的节点,欢迎回到 宝藏库 留言反馈;更多 Ubuntu 服务器、自建节点与 Clash 相关教程也会持续更新,记得收藏,不错过下一篇。



暂无评论内容