使用 Xray、Nginx 与 Cloudflare 搭建个人专属 VPN
security, servers, linux
security, servers, linux
适用于:已有一台带公网 IP 的 VPS、可控制自己的域名解析,并希望通过
Xray + Nginx + Cloudflare搭一条可长期维护的个人代理链路。
整体链路如下:
客户端
↓
Cloudflare(代理 + Edge TLS)
↓
Nginx :443(源站 TLS)
├─ / → 可选静态首页
└─ /ray → 127.0.0.1:10000(Xray WebSocket 入站)
如果你已经有一台公网 VPS,那么把代理入口、TLS 和 Web 服务入口整理到同一条链路里,会比“只开一个裸端口”更容易维护。Nginx 统一接管 443,Xray 只监听本地端口,后续你要加静态页、反向代理或证书调整时都比较顺手。
这套方案的核心是:客户端走 VLESS + WebSocket,Cloudflare 负责公网边缘接入,Nginx 负责源站 TLS 和反向代理,Xray 在本地提供实际代理服务。这样做的好处是结构清楚,组件边界明确,排错时也容易逐层验证。
开始之前,先准备下面这些东西:
vpn-sg.example.com。先在 Cloudflare 中新增一条 A 记录,把子域名指向你的 VPS 公网 IP。

然后在 SSL/TLS 中把模式切到 Full (strict),确保 Cloudflare 到源站这一段也校验证书。

接着在 SSL/TLS -> 源服务器 中签发一张 Cloudflare Origin CA 证书。建议只给当前代理子域名使用,生成后把证书和私钥都保存下来,稍后写入 Nginx。

先安装并启动 Nginx:
sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
sudo systemctl status nginx
然后为当前域名准备证书目录,把刚才从 Cloudflare 拿到的源证书和私钥分别写入文件:
sudo mkdir -p /etc/nginx/ssl/vpn.sg
sudo vim /etc/nginx/ssl/vpn.sg/origin.pem
sudo vim /etc/nginx/ssl/vpn.sg/origin.key
切到 root 用户后执行官方安装脚本:
sudo su - root
bash <(curl -Ls https://raw.githubusercontent.com/XTLS/Xray-install/main/install-release.sh)
安装完成后先确认版本:
xray version
再生成一个 UUID,后面会写到客户端配置里:
cat /proc/sys/kernel/random/uuid
编辑配置文件:
vim /usr/local/etc/xray/config.json
写入下面这份最小配置。注意把 clients.id 改成刚才生成的 UUID,监听端口保持为本地 10000:
{
"log": {
"loglevel": "warning",
"access": "/var/log/xray/access.log",
"error": "/var/log/xray/error.log"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10000,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<你的 UUID>"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"path": "/ray"
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}
配置完成后先做语法检查:
xray run -test -config /usr/local/etc/xray/config.json
没有报错再重启并设置开机自启:
systemctl restart xray
systemctl enable xray
最后确认监听端口已经起来:
ss -tlnp | grep 10000
预期能看到类似输出:
LISTEN 0 4096 127.0.0.1:10000 0.0.0.0:* users:(("xray",pid=80276,fd=4))
创建站点配置文件:
sudo vim /etc/nginx/sites-available/vpn-sg.conf
写入如下配置。这里让 Nginx 统一监听 80/443,HTTP 自动跳转到 HTTPS,/ray 代理到本地 Xray 的 WebSocket 入站:
server {
listen 80;
server_name vpn-sg.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name vpn-sg.example.com;
ssl_certificate /etc/nginx/ssl/vpn.sg/origin.pem;
ssl_certificate_key /etc/nginx/ssl/vpn.sg/origin.key;
ssl_protocols TLSv1.2 TLSv1.3;
location = / {
default_type text/html;
return 200 '<html><body><h1>OK</h1></body></html>';
}
location /ray {
proxy_redirect off;
proxy_pass http://127.0.0.1:10000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
启用配置并重载 Nginx:
sudo ln -s /etc/nginx/sites-available/vpn-sg.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
如果服务器启用了 ufw,记得把 80、443 和 SSH 端口放开:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw enable
可以按下面这个顺序排查整条链路:
ss -tlnp | grep xray
https://vpn-sg.<你的域名>.com
如果首页能直接返回 OK,说明 Cloudflare -> Nginx -> 源证书 这一段已经通了。
Full (strict)。nginx -t 是否通过。80/443。wsSettings.path 与 Nginx 的 location /ray 是否完全一致。Android 可以使用 v2rayNG,Windows 可以使用 v2rayN,协议选择 VLESS。核心参数如下:
地址: vpn-sg.example.com
端口: 443
UUID: <你的 UUID>
传输: ws
路径: /ray
TLS: 开启
SNI: vpn-sg.example.com
Host: vpn-sg.example.com

这套配置的重点不在“命令要敲多少”,而在几个边界要保持一致:
server_name、客户端 SNI/Host 必须一致。如果后续继续扩展,可以优先补上这几项:
日志还会继续,欢迎常来。
返回首页