322 lines
9.7 KiB
Markdown
322 lines
9.7 KiB
Markdown
# 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 "<title>.*</title>"
|
||
|
||
#测试博客
|
||
curl -k --no-keepalive https://网站B域名 --resolve 网站B域名:443:127.0.0.1 | grep -o "<title>.*</title>"
|
||
|
||
#测试代理域名(应返回博客内容)
|
||
curl -k --no-keepalive https://代理域名 --resolve 代理域名:443:127.0.0.1 | grep -o "<title>.*</title>"
|
||
|
||
### 4.3 验证XRay
|
||
systemctl status xray
|
||
ss -tlnp | grep 8443
|
||
xray -test -config /usr/local/etc/xray/config.json
|
||
|
||
### 4.4 验证证书自动续期
|
||
bash
|
||
systemctl list-timers | grep certbot
|
||
certbot renew --dry-run
|
||
|
||
## 五、客户端配置(XRay)
|
||
##5.1 连接信息
|
||
参数 值
|
||
地址 代理域名
|
||
端口 443
|
||
协议 VLESS
|
||
UUID 你的uuid
|
||
Flow xtls-rprx-vision
|
||
加密 none
|
||
安全 reality
|
||
serverName 代理域名
|
||
|
||
publicKey 你的公钥
|
||
shortId 你的shortId
|
||
dest 网站B域名:443(客户端不需要配置,这是服务端回落目标)
|
||
|
||
## 六、最终状态确认
|
||
组件 状态 验证方式
|
||
论坛 HTTPS ✅ 正常 浏览器访问 https://网站A域名
|
||
博客 HTTPS ✅ 正常 浏览器访问 https://网站B域名
|
||
代理域名回落 ✅ 正常 浏览器访问 https://代理域名 看到博客
|
||
XRay代理 ✅ 正常 客户端连接测试
|
||
证书续期 ✅ 自动 systemctl list-timers | grep certbot
|
||
串站问题 ✅ 解决 不同浏览器同时访问三个域名均正确
|
||
|