# Nginx + Xray(Reliability)多域名共用443端口完美解决方案 为了更好的伪装,且本身有两个网站要使用,所以就弄了这么一个东西,最终就是两个网站和Xray都使用443端口,流量监测的时候代理的流量被伪装成了正常的TSL,没有问题,这个是基础功能。如果主动探测,代理域名,不是客户端访问引导到正常更新使用的博客上。 在这篇文章前,使用的Xray在前,使用Xray的回落机制+分流实现。不过会该方案有严重的串站问题。最后定了下面的方案,Nginx在前通过串流,原封不动的将代理域名的信息转给Xray。 ## 一、需求背景与最终架构 ### 1.1 原始需求 一台服务器(Debian 12 + Nginx 1.22.1 + PHP 8.2) 三个域名都使用443端口: 网站A域名:Discuz论坛(HTTPS) 网站B域名:WordPress博客(HTTPS) 代理域名:XRay代理(REALITY协议) 探测代理域名时能看到真实的博客内容(回落机制) 绝对不串站 ### 1.2 最终架构(Nginx在前 + stream分流) 用户访问 ↓ 443端口 → Nginx(stream模块,读SNI不解密) ├─ SNI = 网站A域名 → 127.0.0.1:4431 ├─ SNI = 网站B域名 → 127.0.0.1:4432 └─ SNI = 代理域名 → 127.0.0.1:8443 ↓ ↓ ↓ Nginx http(4431) Nginx http(4432) Xray(8443) 处理论坛(HTTPS) 处理博客(HTTPS) 处理代理 回落指向博客端口(4432) ## 二、配置步骤详解 ### 2.1 准备工作:SSL证书(Let's Encrypt) #安装Certbot apt update apt install certbot python3-certbot-nginx -y #申请证书(包含三个域名) certbot --nginx -d 网站A域名 -d 网站B域名 -d 代理域名 #注意:如果已有其中一个域名的证书,选择 Expand 扩展域名 #证书路径:/etc/letsencrypt/live/代理域名/ ### 2.2 备份原有配置(可选) cp /etc/nginx/conf.d/网站A.conf /etc/nginx/conf.d/网站A.conf.bak cp /etc/nginx/conf.d/网站B.conf /etc/nginx/conf.d/网站B.conf.bak cp /usr/local/etc/xray/config.json /usr/local/etc/xray/config.json.bak cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak ### 2.3 修改Nginx主配置(添加stream模块) 编辑 /etc/nginx/nginx.conf,在文件最顶部(events块之前)添加: ```nginx stream { #根据SNI域名转发到不同后端 map $ssl_preread_server_name $backend { 网站A域名 127.0.0.1:4431; 网站B域名 127.0.0.1:4432; 代理域名 127.0.0.1:8443; default 127.0.0.1:4432; #默认看博客 } server { listen 443 reuseport; listen [::]:443 reuseport; ssl_preread on; proxy_pass $backend; #超时设置 proxy_connect_timeout 30s; proxy_timeout 30s; } } #下面是原有的 events { ... } 和 http { ... } events { worker_connections 768; #... } ``` ### 2.4 配置论坛(网站A) 编辑 /etc/nginx/conf.d/网站A.conf: ```nginx server { listen 127.0.0.1:4431 ssl; server_name 网站A域名; #SSL证书 ssl_certificate /etc/letsencrypt/live/代理域名/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/代理域名/privkey.pem; #SSL配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; root /var/www/网站A; index index.php index.html; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_param HTTPS on; } location ~ /\.ht { deny all; } location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, no-transform"; } } ``` ### 2.5 配置博客(网站B) 编辑 /etc/nginx/conf.d/网站B.conf: ```nginx server { listen 127.0.0.1:4432 ssl; server_name 网站B域名; #SSL证书(和论坛用同一个) ssl_certificate /etc/letsencrypt/live/代理域名/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/代理域名/privkey.pem; #SSL配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; root /var/www/wordpress; index index.php index.html; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.2-fpm.sock; fastcgi_param HTTPS on; } location ~ /\.ht { deny all; } client_max_body_size 128M; location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, no-transform"; } } ``` ### 2.6 配置XRay 编辑 /usr/local/etc/xray/config.json: ```json { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 8443, "listen": "127.0.0.1", "protocol": "vless", "settings": { "clients": [ { "id": "你的uuid-1", "flow": "xtls-rprx-vision" }, { "id": "你的uuid-2", "flow": "xtls-rprx-vision" } ], "decryption": "none", "fallbacks": [] }, "streamSettings": { "network": "raw", "security": "reality", "realitySettings": { "dest": "127.0.0.1:4432", // 回落指向博客端口 "serverNames": [ "代理域名" ], "privateKey": "你的私钥", "shortIds": [ "你的shortId-1", "你的shortId-2" ] } }, "sniffing": { "enabled": true, "destOverride": ["http", "tls"] } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct" }, { "protocol": "blackhole", "tag": "block" } ] } ``` ### 2.7 重载服务 nginx -t && systemctl reload nginx xray -test -config /usr/local/etc/xray/config.json systemctl restart xray ## 三、踩坑记录与解决方案 ### 坑1:证书申请时提示找不到代理域名的server_name 现象: text Could not automatically find a matching server block for 代理域名 原因:代理域名由XRay处理,Nginx中没有对应的server块 解决方案: bash #临时创建一个代理域名的Nginx配置 ``` cat > /etc/nginx/conf.d/代理域名.temp.conf << EOF server { listen 80; server_name 代理域名; root /var/www/html; } EOF ``` nginx -t && systemctl reload nginx certbot install --cert-name 代理域名 rm /etc/nginx/conf.d/代理域名.temp.conf ### 坑2:XRay回落配置错误导致循环 现象:curl测试代理域名时报错 SSL_ERROR_SYSCALL 原因:XRay配置中dest写成了域名网站B域名:443,导致流量循环 解决方案:改为直接指向博客的本地端口 json "dest": "127.0.0.1:4432" ### 坑3:浏览器测试时串站(先打开论坛,后面全变论坛) 现象:同一个浏览器中,先访问网站A,再开新标签页访问网站B,显示论坛内容 原因:HTTP/2的连接合并(coalescing)特性,三个域名共用同一IP和证书,浏览器复用连接 解决方案:在网站配置中禁用HTTP/2 nginx #将 listen 127.0.0.1:4431 ssl http2; 改为 listen 127.0.0.1:4431 ssl; 验证:禁用后感觉不到速度差异,问题彻底解决 ### 坑4:论坛友情链接跳转也串站 现象:从论坛点击友情链接到博客,显示论坛内容 原因:同坑3,同一标签页内跳转复用了连接 解决方案:同坑3,禁用HTTP/2后解决 ### 坑5:reuseport参数导致分流异常(偶发) 现象:偶尔出现分流错误,重启Nginx后恢复 原因:某些内核版本中reuseport与ssl_preread共用可能异常 解决方案:去掉reuseport参数(本案例最终保留,但遇到问题时可去掉) ## 四、验证命令汇总 ### 4.1 验证Nginx配置 nginx -t nginx -T | grep -A 20 -B 5 "stream {" ### 4.2 验证stream分流 #测试论坛(每次新建连接) curl -k --no-keepalive https://网站A域名 --resolve 网站A域名:443:127.0.0.1 | grep -o "