Debian 13 (trixie)从零开始、不依赖任何面板(纯净安装)的 Xray 部署流程:装系统依赖 → 安装 Xray-core → 配置 VLESS + Reality → 开启 BBR。
说明:本文用于技术学习与个人合规用途。请在你所在地区法律允许的前提下使用,并仅用于访问你有权访问的资源。
一、系统准备
先用 root 登录,更新软件源并升级:
apt update
apt upgrade -y
装几个后续会用到的工具:
apt install -y curl wget gnupg2 lsb-release ca-certificates
确认系统版本(应显示 trixie / 13):
cat /etc/os-release | grep -E "VERSION|PRETTY"
Reality 对内核版本没有硬性要求,但 Debian 13 自带 6.x 内核,BBR 原生支持,无需换内核。确认一下:
uname -r
二、纯净安装 Xray-core
官方推荐的方式是用 XTLS 提供的安装脚本,它会把二进制放到 /usr/local/bin/xray、配置目录放到 /usr/local/etc/xray/,并注册 systemd 服务,不污染系统包管理器。
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
安装完成后查看版本,确认成功:
xray version
如果 GitHub 访问不畅,可改用镜像(二选一,注意替换为可信镜像源):
# 例如 jsdelivr 镜像
bash -c "$(curl -L https://cdn.jsdelivr.net/gh/XTLS/Xray-install@main/install-release.sh)" @ install
安装脚本同时创建了 xray 用户与 /etc/systemd/system/xray.service。检查服务状态:
systemctl status xray --no-pager
此时服务是 inactive,因为我们还没放配置。
安装后的文件位置(官方 FHS 布局):
| 用途 | 路径 |
|---|---|
| 主程序 | /usr/local/bin/xray |
| 配置文件 | /usr/local/etc/xray/config.json |
| geo 数据 | /usr/local/share/xray/geoip.dat、geosite.dat |
| systemd 服务 | /etc/systemd/system/xray.service |
| 日志目录 | /var/log/xray/ |
三、生成密钥与 UUID
Reality 使用 X25519 密钥对做身份验证,公钥给客户端、私钥留服务器。执行:
xray x25519
输出形如:
Private key: <你的私钥>
Public key: <你的公钥>
再生成一个 UUID 作为客户端 ID:
xray uuid
<你的-uuid>
把这两个值记下来,下面配置要用。
四、配置 VLESS + Reality(服务端)
编辑配置文件:
nano /usr/local/etc/xray/config.json
写入以下内容(注意替换 <...> 占位符):
{
"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": "www.microsoft.com:443",
"xver": 0,
"serverNames": ["www.microsoft.com", "www.apple.com"],
"privateKey": "<你的私钥>",
"minClientVer": "",
"maxClientVer": "",
"maxTimeDiff": 0,
"shortIds": ["", "abcd1234"],
"spiderX": "/"
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "blocked"
}
],
"routing": {
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "blocked"
}
]
}
}
字段说明:
port: 443:复用标准 HTTPS 端口,配合 Reality 伪装成正常 TLS 流量,最难被识别。flow: xtls-rprx-vision:VLESS 的高性能流控,必须客户端一致。(一定要配置,影响速度)dest/serverNames:Reality 会“借用”一个真实站点的 TLS 握手。这里借用www.microsoft.com,无需你持有证书或域名。privateKey:上一步生成的 X25519 私钥。shortIds:留空串""和一个自定义值均可,客户端需与之对应。
校验配置语法:
xray run -test -config /usr/local/etc/xray/config.json
看到 Configuration OK 即可启动:
systemctl enable --now xray
systemctl status xray --no-pager
确认 443 在监听:
ss -tlnp | grep 443
五、客户端配置(VLESS + Reality)
客户端同样需要 Xray-core(Windows/macOS/Linux 均可用对应的安装包或 GUI 客户端,内核配置同理)。一份 Linux 客户端的 config.json 示例:
{
"inbounds": [
{
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": { "udp": true }
},
{
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http"
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "<服务器IP>",
"port": 443,
"users": [
{
"id": "<你的-uuid>",
"flow": "xtls-rprx-vision",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.microsoft.com",
"fingerprint": "chrome",
"publicKey": "<你的公钥>",
"shortId": "abcd1234",
"spiderX": "/"
}
}
}
]
}
客户端要填的是上一步的 Public key(不是私钥),serverName 与 shortId 必须与服务端 serverNames / shortIds 中的某一项一致,fingerprint 填 chrome 或 firefox 等浏览器指纹以模拟真实客户端。
六、与网站共存:把 Xray 端口从 443 改到 8443
如果这台机器上还跑了网站(Nginx / Caddy / Apache 等),它们默认会占用 443 端口。而上面的 Xray 入站也监听 443,两者会端口冲突,只能有一个能起来。
解决办法:把 Xray 的入站端口改到 8443(或其他未占用端口),网站继续独占 443,各走各的。
1. 修改服务端配置
编辑 config.json,把入站 port 由 443 改为 8443:
{
"listen": "0.0.0.0",
"port": 8443,
"protocol": "vless",
"settings": { ... }
}
实际改动只有一行:"port": 443 → "port": 8443。注意 Reality 的 dest 仍借用 www.microsoft.com:443,那是目标站地址,不是本机监听端口,因此无需改动。
2. 修改客户端配置
客户端 vnext 里的 port 同样改成 8443:
"vnext": [
{
"address": "<服务器IP>",
"port": 8443,
"users": [ ... ]
}
]
3. 防火墙放行 8443
如果用了 ufw,放行新端口(443 留给网站,无需再为 Xray 放行):
ufw allow 8443/tcp
ufw reload
4. 重启 Xray 并验证
systemctl restart xray
ss -tlnp | grep 8443
看到 8443 在监听、且 systemctl status xray 正常,说明 Xray 与网站各占 8443 / 443,互不干扰。
5. 进阶:用 Nginx / Caddy 回落,让客户端仍走 443
如果你嫌客户端要记 8443 麻烦,想要客户端只填标准 443、外观上和正常 HTTPS 网站完全一致,可以用 Web 服务器在 443 入口做 SNI 分流(即“回落 / fallback”):
- 443 交给 Nginx(或 Caddy)统一监听;
- 用 SNI(客户端 Hello 里携带的域名)判断:是代理流量 → 转发给本机 Xray(
127.0.0.1:8443);是普通访客 → 转发给网站; - 客户端
port改回443,不用再记特殊端口。
5.1 准备你自己的域名与证书
回落方案需要你自己的一个域名(如 proxy.yourdomain.com),解析到服务器 IP,并用 Let’s Encrypt 等签发证书,让 Nginx 能在该域名上提供正常的 HTTPS 站点。这个站点既是给访客看的,也同时充当 Reality 的 dest 目标。
5.2 改 Xray:借用你自己的域名
Xray 入站仍监听 8443(见上一节),但把 dest / serverNames 改成你自己的域名:
"realitySettings": {
"show": false,
"dest": "proxy.yourdomain.com:443",
"xver": 0,
"serverNames": ["proxy.yourdomain.com"],
"privateKey": "<你的私钥>",
"shortIds": ["", "abcd1234"],
"spiderX": "/"
}
dest 现在是你自己的站点,Xray 会借用它的 TLS 做 Reality 握手,因此该域名必须证书有效、Nginx 能正常响应(正好由下面的网站 server 提供)。
5.3 Nginx:stream + ssl_preread 按 SNI 分流
在 nginx.conf 里加一个与 http 块同级的 stream 块,用 ssl_preread 读取 SNI 后转发:
stream {
# 按 SNI 选择后端:代理域名 → Xray,其它 → 网站
map $ssl_preread_server_name $backend {
proxy.yourdomain.com 127.0.0.1:8443; # 代理流量给 Xray
default 127.0.0.1:8444; # 普通访客给网站
}
server {
listen 443 reuseport;
ssl_preread on;
proxy_pass $backend;
}
}
注意:stream 和 http 不能在同一端口上同时监听,所以把原本在 443 的网站 server 挪到 8444(由上面的 default 转发过去):
# /etc/nginx/sites-enabled/yourdomain.conf
server {
listen 8444 ssl;
server_name yourdomain.com proxy.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
root /var/www/html;
index index.html;
}
改完重载:nginx -t && systemctl reload nginx。
5.4 客户端:改回 443
客户端 vnext 的 port 改回 443,serverName 填你自己的域名,其余不变:
"vnext": [
{
"address": "<服务器IP>",
"port": 443,
"users": [ { "id": "<你的-uuid>", "flow": "xtls-rprx-vision", "encryption": "none" } ]
}
],
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "proxy.yourdomain.com",
"fingerprint": "chrome",
"publicKey": "<你的公钥>",
"shortId": "abcd1234",
"spiderX": "/"
}
}
5.5 Caddy 用户
思路相同,只是用 Caddy 实现 SNI 分流:可用 reverse_proxy 配合 tls 的 sni 匹配,或更干净地用 layer4 插件 在四层按 SNI 路由(代理域名 → 127.0.0.1:8443,其余 → 本地 HTTPS 站点)。
5.6 关键点回顾
- 443 入口只能有一个监听者,所以用 Nginx stream 统一收口再分流;
- Reality 的
dest/serverNames必须指向你自己有证书的域名; - 客户端
serverName与port要与之一致(这里是proxy.yourdomain.com+443); - 此方案对外完全像“一个普通 HTTPS 网站”,隐蔽性最好,但配置比直接换端口复杂,按需选择。
七、启用 BBR 拥塞控制
VLESS + Reality 跑在 TCP 上,开启 BBR 能显著改善高延迟、高丢包链路下的吞吐。Debian 13 内核已自带 BBR 模块,无需编译。
写入 sysctl 配置:
echo 'net.core.default_qdisc = fq' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_congestion_control = bbr' >> /etc/sysctl.conf
sysctl -p
验证是否生效:
sysctl net.ipv4.tcp_congestion_control
# 期望输出:net.ipv4.tcp_congestion_control = bbr
再从内核模块侧确认:
lsmod | grep bbr
# 或
cat /proc/sys/net/ipv4/tcp_available_congestion_control
# 期望能看到 bbr
若 tcp_available_congestion_control 里没有 bbr,通常是模块未加载,手动加载即可:
modprobe tcp_bbr
BBR 立即生效,无需重启;重启后由 /etc/sysctl.conf 自动应用。
八、防火墙与收尾
若开启了 ufw,放行 Xray 所用端口:单用途场景放行默认的 443,若按「第六节」改了端口则放行 8443(网站自身需要的 443 由 Web 服务器自己处理):
# 单用途(Xray 在 443)
ufw allow 443/tcp
# 与网站共存(Xray 已改到 8443)
ufw allow 8443/tcp
ufw reload
最后做一次端到端验证:客户端连接后,浏览器或 curl -x socks5://127.0.0.1:10808 https://www.google.com 能正常返回即大功告成。
小结
整套下来核心就三步:用官方脚本纯净装 Xray → 写好 Reality 入站(借用真实站点 TLS,免证书)、客户端填公钥 → 开 BBR。