转载说明
本文转载自 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 协议的软件)进行加密(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 会确认丢失并补发

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


落地机设置白名单接受中转机 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 端口进行伪装)

脚本会自动生成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)
选择继续修改设置,端口和路径这里采用默认值,修改管理员的账号和密码

在本地执行
# -N不执行远程指令,-L本地端口转发
ssh -N -L 2095:127.0.0.1:2095 root@<中转机ip>
之后在浏览器打开
http://127.0.0.1:2095/app
即可看到图形界面,在左侧菜单找到 出站管理,点击上方 添加


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

接下来添加 入站管理

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

以下内容针对的是订阅获取节点的方式,其他方式可以基于 2.4 手动客户端导入 修改文件
设置分流规则以及防止 DNS 泄露

打开编辑器后复制以下内容,并保存
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
导入节点采用本地文件的形式

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 模板

编辑 入站管理 服务端

2.6* 将 SNI 改为自己的域名
这一小节需要有自己的域名,以 www.example.com 为例,托管在 CloudFlare,用 DNS-01 的方式获取证书
创建一个静态页

选择 Upload your static files

如果之前创建过 www.example.com 的 A/AAAA 记录或 CNAME 会冲突,需要删除原纪录或换一个域名
同时将相同文件放在中转机
/var/www/static/index.html
添加 Cloudflare DNS 插件
caddy add-package github.com/caddy-dns/cloudflare
创建 CloudFlare API Token

点击 Create Token,再使用 Edit zone DNS 的模板,这里的 Permission 设置表示给予该 token 编辑 zone 内 dns 以及查看 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 模板即可
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 图形界面

加固完成后,执行需要 root 权限的命令前面需要加 sudo,或者可以通过 sudo -i 切换到 root 环境
原文作者:heylong(LINUX DO) | 原文链接:linux.do/t/topic/3145198 | 来源:LINUX DO · 文档共建 | 转载整理:误差之外