Files
IT-Docs/Nginx + Xray(Reliability)多域名共用443端口完美解决方案.md

9.7 KiB
Raw Permalink Blame History

Nginx + XrayReliability)多域名共用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端口 → Nginxstream模块,读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块之前)添加:

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

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

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

{
  "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

坑2XRay回落配置错误导致循环

现象: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 ""

#测试博客 curl -k --no-keepalive https://网站B域名 --resolve 网站B域名:443:127.0.0.1 | grep -o ""

#测试代理域名(应返回博客内容) curl -k --no-keepalive https://代理域名 --resolve 代理域名:443:127.0.0.1 | grep -o ""

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 串站问题 解决 不同浏览器同时访问三个域名均正确