文章背景图

从 0 到 1 的 Vless + Reality 代理搭建

2026-11-09
1
- 字
- 分钟
|

转载说明

本文转载自 LINUX DO 论坛「文档共建」板块,作者 heylong,原文链接 linux.do/t/topic/3145198,原标题《从 0 到 1 的 Vless + Reality 代理搭建》。版权归原作者所有,此处仅作技术记录与个人存档;文中服务器 IP、UUID、密钥、域名均沿用原文占位符。

提示:自建代理与账号合规、所在地区网络监管相关,实际使用前请自行确认当地法规与服务条款。

这篇文章记录了我自己自建家宽节点以及学习的过程,参考了许多佬的文章 @STALK,@RyanVan,@deer,@xiaowanzi,有什么错误与不足欢迎佬友直接指出!

写在前面:

本文简单介绍了不同代理协议的区别,国内不同线路,以及基于手写、一键脚本和 S-UI Web 界面从 0 搭建 Vless + Reality 的代理方法

0. 不同的代理协议

代理协议规定客户端和代理服务器之间的消息类型和传输格式等

1. Shadowsocks(SS) 和 ShadowsocksR(SSR)

Socks5 本身不含加密,明文传输代理信息。SS 通常架构为

SS架构

由 SS 客户端(支持 SS 协议的软件)进行加密(AEAD,2022),服务端进行解密。SSR 为 SS 的改进版本。

早期 SS 由于被主动探测特征明显而大面积被墙

2. VLESS

VLESS 使用 UUID 进行身份验证,本身一般不携带加密功能,是 VMESS 的精简版,去除了两端时钟同步等需求,通常配合 TLS 加密隧道。

使用 TLS 代理时,HTTPS数据经过了两层 TLS,外层是代理的 TLS,内层是 HTTPS 的 TLS,外层在代理端解开

什么是 XTLS-Vision 和 XTLS-Reality ?

Vision 是 XTLS 的流控方案,通常写作xtls-rprx-vision,通过特定手段隐藏代理特征,同时完成必要处理后,可以直接转发内层 TLS 密文;Reality 会借用大型域名(比如 Apple、Microsoft 或 Google)的公共数据和 TLS 握手特征,当被主动探测时会返回目标网站的真实响应

3. Trojan

Trojan 不使用自定义的加密协议,它使用 TLS 包装 Trojan 请求,当收到非有效 Trojan 请求,比如受到主动检测时,它不会像 SS 一样断开连接,而是将连接代理到正常的 Web。Trojan 协议流量可以伪装成正常 HTTPS 流量。

Trojan 通常建立在普通 TLS 基础上,和 Reality 有区别

4. Hysteria 2

HTTP/3 使用 QUIC,QUIC 集成了 TLS 1.3 并采用 UDP 进行传输,同时 QUIC 会确认丢失并补发

QUIC

Hysteria 2 基于 QUIC,采用 UDP 传输,通过 HTTP/3 或 Salamander 改变数据包外观(对于限制 QUIC 但不限制 UDP 的场景)进行伪装。Hysteria 2 在 TCP 被限速或不可用 的场景可使用,但也由于采用 UDP 传输,可能遭遇运营商 QoS 限流。

5. AnyTLS

AnyTLS 也采用 TLS in TLS 的形式,通常采用 ECH 和流量填充等方式来隐藏特征,达到伪装目的。

AnyTLS 采用普通 TLS,所以通常需要有自备的域名和 TLS 证书;相比之下 Reality 采用转发进行伪装,通常不需要自备域名

0.1 线路介绍

互联网由不同网络组成。特定 AS(Autonomous System)宣告特定的 IP 地址空间,有对应唯一的 ASN 编号(比如 Cloudflare 的 ASN 是 AS13335),不同运营商可能有多个 ASN,控制不同的 IP 地址空间,BGP(Border Gateway Protocol)负责 AS 之间的路由 (在同个 ASN 内的用户可以直接沟通无需 BGP,不同 ASN 则需通过 BGP 获取对方具体位置)

国内三大运营商常见 ASN:

中国电信:

  • AS4134(163,4134),国内骨干网,IP 以 202.97 开头,基建早,带宽大

  • AS4809(CN2),下一代承载网,IP 以 59.43 开头,独立于 163 建设,带宽小,稳定度高

  • AS23764(CTG),面向企业提供定制化国际线路,与 CN2 相互独立

CN2 分为 CN2GT(Global Transit,又称为半程 CN2,国内走 163,国外走 CN2)和 CN2GIA(Global Internet Access,全程 CN2)

中国联通:

  • AS4837(169,4837),国内骨干网,类似 4134,IP 以 219.158 开头

  • AS9929(CUII,9929),原网通 CNC 骨干,定位类似 CN2,但表现不如 CN2

  • AS10099(CUG),境外网,类似 CTG

中国移动:

  • AS9808(CMNET),国内主干网,同时省级公司大量使用独立 ASN

  • AS58453(CMI),境外网

  • AS58807(CMIN2),境外网

非优化跨运营商线路可能会被 QoS,优先选择本运营商

1. 准备工作

中转机:DMIT LAX.AS3.Pro.TINY,1c2g,双向 1T 流量,带宽 1Gbps

落地机:QQPW Dedicated IP VDS Intern,2c3g,双向 1T 流量,带宽 400Mbps

Pro 系列为电信优质线路 CN2GIA,双向流量代表上行和下行均会计入

SSH 登录工具:Termius

先生成一对密钥供 ssh 登录使用,在终端输入

# -t表示type,-C是Comments,-f是file储存位置
ssh-keygen -t ed25519 -C "dmit" -f ~/.ssh/dmit

之后会提示是否为密钥创建passphrase,直接 Enter 不创建,或者输入passphrase

成功创建之后会有两个文件,带 .pub 的是公钥,另一个是私钥
.ssh/
├── dmit
└── dmit.pub

2. 开始搭建

2.1 ssh 登录服务器

通过 Termius 图形化界面导入密钥,填入对应服务器的 IP 地址,选择刚刚导入的密钥,用户名为 root,新建 New Host

创建密钥
创建newhost

落地机设置白名单接受中转机 IP 直连,并在中转机界面 ssh 密码登录

ssh root@QQPW_IP

2.2.1 一键脚本安装

以下内容基于大厂域名伪装,随机到 CloudFlare 最好手动修改掉,防止被偷流量。若要使用自己的域名,请跳至 2.6* 将 SNI 改为自己的域名

直接使用 233boy 的一键搭建脚本

bash <(wget -qO- -o- https://github.com/233boy/sing-box/raw/main/install.sh)

安装完成后输入

sb
添加配置

选择 1)添加配置

协议选择

选择 18)VLESS-REALITY,之后输入端口(中转机入站最好选择 443 端口进行伪装)

vless协议

脚本会自动生成uuid,密钥,默认不生成 short id。记录 VLESS 协议链接

中转机采用一键脚本在 /etc/sing-box/config.json 设置对应出站(outbounds)即可,可以参考 2.2.2 手动搭建节点 对应部分;或者直接在客户端采用链式代理

2.2.2 手动搭建节点

落地机安装 sing-box

apt update
apt install -y curl
mkdir -p /etc/apt/keyrings #第三方仓库签名密钥存放位置

curl -fsSL https://sing-box.app/gpg.key \
  -o /etc/apt/keyrings/sagernet.asc #存入官方公钥

chmod a+r /etc/apt/keyrings/sagernet.asc #修改权限
# 指定下载地址和密钥
cat >/etc/apt/sources.list.d/sagernet.sources <<'EOF'
Types: deb
URIs: https://deb.sagernet.org/
Suites: *
Components: *
Enabled: yes
Signed-By: /etc/apt/keyrings/sagernet.asc
EOF
apt update
apt install -y sing-box

生成身份验证的 uuid

sing-box generate uuid

生成密钥

sing-box generate reality-keypair

生成short id

openssl rand -hex 8

创建配置文件并写入规则

nano /etc/sing-box/config.json
{
  "log": {
    "level": "info",
    "timestamp": true
  },
  "inbounds": [
    {
      "type": "vless",
      "tag": "VLESS-REALITY-25547",
      "listen": "::",
      "listen_port": 25547,
      "users": [
        {
          "uuid": "<生成的uuid>",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.microsoft.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.microsoft.com",
            "server_port": 443
          },
          "private_key": "<生成的私钥>",
          "short_id": [
            "<生成的short id>"
          ]
        }
      }
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    }
  ],
  "route": {
    "final": "direct"
  }
}

如果选择 Web 管理界面,可以直接跳到 2.3 Web 面板管理

配置中转机,同样安装 sing-box,生成新的密钥、uuid、short id

sing-box generate reality-keypair
sing-box generate uuid
openssl rand -hex 8

配置 config

nano /etc/sing-box/config.json
{
  "log": {
    "level": "info",
    "timestamp": true
  },
  "inbounds": [
    {
      "type": "vless",
      "tag": "VLESS-REALITY-443",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "<新的uuid>",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.microsoft.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.microsoft.com",
            "server_port": 443
          },
          "private_key": "<新的密钥>",
          "short_id": [
            "<新的short id>"
          ]
        }
      }
    }
  ],
  "outbounds":[
    {
      "type": "vless",
      "tag": "VLESS-REALITY-25547",
      "server": "<落地机ip>",
      "server_port": 25547,
      "uuid": "<落地机的uuid>",
      "flow": "xtls-rprx-vision",
      "tls": {
        "enabled": true,
        "server_name": "www.microsoft.com",
        "reality": {
         "enabled": true,
         "public_key": "落地机生成的公钥",
         "short_id": "落地机的short id"
        },
        "utls":{
        "enabled": true,
        "fingerprint": "chrome"
        }
      }
    }
  ],
  "route": {
    "final": "VLESS-REALITY-25547"
  }
}

每次修改完json文件后对语法进行检查

sing-box check -c /etc/sing-box/config.json

无输出则语法正确

重启服务

systemctl restart sing-box
systemctl status sing-box --no-pager

2.3 Web 面板管理

可以采用图形化界面配置,这里选择 S-UI,使用一键脚本

# 语言设置为中文
SUI_LANG=zhcn bash <(curl -Ls https://raw.githubusercontent.com/alireza0/s-ui/master/install.sh)

选择继续修改设置,端口和路径这里采用默认值,修改管理员的账号和密码

sui设置

在本地执行

# -N不执行远程指令,-L本地端口转发
ssh -N -L 2095:127.0.0.1:2095 root@<中转机ip>

之后在浏览器打开

http://127.0.0.1:2095/app

即可看到图形界面,在左侧菜单找到 出站管理,点击上方 添加

出站管理
出站管理2

之后为入站添加 TLS 模板,点击左侧菜单 TLS设置,上方点击 添加,short id采用以下命令生成

openssl rand -hex 8
TLS模板

接下来添加 入站管理

服务端入站

客户端入站点击 多域名,填写中转机 IP,若有 IPv6 可以一起填入,IPv4 TCP不通时可以采用 IPv6

客户端入站

以下内容针对的是订阅获取节点的方式,其他方式可以基于 2.4 手动客户端导入 修改文件

设置分流规则以及防止 DNS 泄露

clash订阅

打开编辑器后复制以下内容,并保存

mixed-port: 7897
allow-lan: false
mode: rule
log-level: info

unified-delay: true
tcp-concurrent: true

dns:
  enable: true
  use-system-hosts: false
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - '*.lan'
    - '*.local'
    - '*.localdomain'
    - '+.localhost'
    - '*.home.arpa'
    - '+.msftconnecttest.com'
    - '+.msftncsi.com'
  ipv6: false
  nameserver:
    - "https://1.1.1.1/dns-query#Proxy"
    - "https://8.8.8.8/dns-query#Proxy"

  nameserver-policy:
    "geosite:cn":
      - "https://223.5.5.5/dns-query#DIRECT"
      - "https://223.6.6.6/dns-query#DIRECT"

sniffer:
  enable: true
  parse-pure-ip: true
  override-destination: false
  sniff:
    HTTP:
      ports: [80, 8080-8880]
    TLS:
      ports: [443, 8443]
    QUIC:
      ports: [443, 8443]

geodata-mode: true
geo-auto-update: true
geo-update-interval: 24
geox-url:
  geoip: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat"
  geosite: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat"

rules:
  - GEOIP,private,DIRECT,no-resolve
  - GEOSITE,CN,DIRECT
  - MATCH,Proxy

WebRTC 泄露不好解决,要么开 TUN 模式,要么浏览器安装插件(比如WebRTC Control)直接禁用

我们已经完成了前置的所有工作,现在只需在左侧菜单栏 用户管理,点击上方 添加,填入对应的信息和入站标签并保存即可

用户管理

通过订阅(默认路径获取得通过隧道)或 vless 链接导入节点

ssh -N -L 2096:127.0.0.1:2096 root@<中转机ip>

2.4 手动客户端导入

以Clash为例,手动创建则在本地写入 yaml 文件

mixed-port: 7897
# 不向局域网开放
allow-lan: false
mode: rule
log-level: info

# 统一节点测速,单节点不用管
unified-delay: true
# 域名解析出多个 IP 时并发拨号,避免首包超时
tcp-concurrent: true

proxies:
  - name: VLESS-REALITY-443
    type: vless
    server: <中转机ip>
    port: 443
    uuid: "<中转机uuid>"
    network: tcp
    tls: true
    udp: true
    flow: xtls-rprx-vision
    servername: www.microsoft.com
    reality-opts:
      public-key: "<中转机公钥>"
      short-id: "<中转机short id>"
    client-fingerprint: chrome

proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - VLESS-REALITY-443

dns:
  enable: true
  # 避免过期 host 干扰解析
  use-system-hosts: false
  listen: 127.0.0.1:1053
  # 本地返回 fake ip,交给服务端解析,防止 dns 泄露
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - '*.lan'
    - '*.local'
    - '*.localdomain'
    - '+.localhost'
    - '*.home.arpa'
    - '+.msftconnecttest.com'
    - '+.msftncsi.com'
  ipv6: false
  nameserver:
    - "https://1.1.1.1/dns-query#PROXY"
    - "https://8.8.8.8/dns-query#PROXY"

  nameserver-policy:
    # 国内域名解析
    "geosite:cn":
      - "https://223.5.5.5/dns-query#DIRECT"
      - "https://223.6.6.6/dns-query#DIRECT"

# sniffer 帮助识别域名,帮助分流
sniffer:
  enable: true
  parse-pure-ip: true
  override-destination: false
  sniff:
    HTTP:
      ports: [80, 8080-8880]
    TLS:
      ports: [443, 8443]
    QUIC:
      ports: [443, 8443]

geodata-mode: true
geo-auto-update: true
geo-update-interval: 24
geox-url:
  geoip: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat"
  geosite: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat"

rules:
  - GEOIP,private,DIRECT,no-resolve
  - GEOSITE,CN,DIRECT
  - MATCH,PROXY

导入节点采用本地文件的形式

Clash导入

2.5* Hysteria2 入站

某些特殊时期,可能 IPv4 直连 TCP 会失败,这时可以采用基于 UDP 的 Hy2 协议入站

一键脚本设置 Hy2 协议,以端口10001为例,设置对应客户端出站,还是以 Clash 为例

- name: Hysteria2-10001
  type: hysteria2
  server: <中转机ip>
  port: 10001
  password: "<hy2密码>"
  sni: www.bing.com
  alpn:
    - h3
  skip-cert-verify: true

下面介绍 S-UI 图形界面设置方法,先点击左侧菜单栏 TLS设置,添加 TLS 模板

hy2tls模板

编辑 入站管理 服务端

hy2入站管理

2.6* 将 SNI 改为自己的域名

这一小节需要有自己的域名,以 www.example.com 为例,托管在 CloudFlare,用 DNS-01 的方式获取证书

创建一个静态页

静态页部署

选择 Upload your static files

静态页部署2

如果之前创建过 www.example.com 的 A/AAAA 记录或 CNAME 会冲突,需要删除原纪录或换一个域名

同时将相同文件放在中转机

/var/www/static/index.html

添加 Cloudflare DNS 插件

caddy add-package github.com/caddy-dns/cloudflare

创建 CloudFlare API Token

apitoken

点击 Create Token,再使用 Edit zone DNS 的模板,这里的 Permission 设置表示给予该 token 编辑 zone 内 dns 以及查看 zone 相关信息的权限

zone

点击 Continue to summary,在中转机添加环境文件,并收紧权限,只有 root 可读写该文件

cat > /etc/caddy/caddy.env <<'EOF'
CF_API_TOKEN=<新创建的 Token>
EOF
chmod 600 /etc/caddy/caddy.env
systemctl edit caddy

写入

[Service]
EnvironmentFile=/etc/caddy/caddy.env
systemctl daemon-reload
systemctl restart caddy

校验

sudo caddy validate --config /etc/caddy/Caddyfile --envfile /etc/caddy/caddy.env
systemctl reload caddy

编辑 Caddyfile

nano /etc/caddy/Caddyfile
https://www.example.com:8443 {
    # 只允许本机访问
    bind 127.0.0.1
    # 自动申请并续期 tls 证书,使用 Cloudflare DNS-01 验证
    tls {
      dns cloudflare {env.CF_API_TOKEN}
    }

    root * /var/www/static
    encode gzip

    handle {
      try_files {path} {path}.html {path}/ /index.html
      file_server
    }
}

查看 TLS 证书

openssl s_client -connect 127.0.0.1:8443 \
  -servername www.example.com \
  -alpn h2 -tls1_3 </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

结果显示域名,以及证书类型 Let’s Encrypt 即可

接下来修改 SNI(只需修改客户端至中转机这一段)

(1) 如果使用一键脚本(对应入站保存在 /etc/sing-box/conf/VLESS-REALITY-xxx.json,采用 sb 更改配置无法单独修改 handshake)或手动搭建,修改入站 inbounds 对应字段

"tls": {
        "enabled": true,
        "server_name": "www.example.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "127.0.0.1",
            "server_port": 8443
          },
        },
}

同时客户端 servername 做对应修改为 www.example.com

proxies:
  - name: VLESS-REALITY-443
    type: vless
    server: <中转机ip>
    port: 443
    uuid: "<中转机uuid>"
    network: tcp
    tls: true
    udp: true
    flow: xtls-rprx-vision
    # 修改这里的 servername
    servername: www.example.com
    reality-opts:
      public-key: "<中转机公钥>"
      short-id: "<中转机short id>"
    client-fingerprint: chrome

(2)使用 S-UI,如图修改 TLS 设置

TLS设置修改

在对应入站选择该 TLS 模板即可

3. 服务器加固

对中转机,创建普通用户,以heylong为例

useradd -m -s /bin/bash heylong

设置密码

passwd heylong

复制 ssh 密钥并授权

cp -r /root/.ssh/ /home/heylong/
chown -R heylong:heylong /home/heylong/.ssh/
usermod -aG sudo heylong

修改 ssh 端口并验证语法是否正确

sed -i 's/^#Port 22/Port 8086/' /etc/ssh/sshd_config
sudo sshd -t

安装并设置防火墙

apt update
apt install -y ufw

# 默认出入站规则
ufw default deny incoming
ufw default allow outgoing

# 放行对应端口
ufw allow 8086/tcp comment 'SSH'
ufw allow 443/tcp comment 'VLESS Reality'
ufw allow 10001/udp comment 'Hysteria2'

重启 ssh

systemctl restart ssh

启用防火墙,查看防火墙状态

ufw enable
ufw status

开一个新的本地终端,验证在新端口可以 ssh 登录成功

ssh heylong@<中转机ip> -p 8086
sudo whoami # 应该输出 sudo

禁用 root 远程登录

sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config

检查语法并重启 ssh

sshd -t
systemctl restart ssh

同步修改 Termius 图形界面

ssh修改

加固完成后,执行需要 root 权限的命令前面需要加 sudo,或者可以通过 sudo -i 切换到 root 环境


原文作者:heylong(LINUX DO) | 原文链接:linux.do/t/topic/3145198 | 来源:LINUX DO · 文档共建 | 转载整理:误差之外

评论交流

文章目录