From 075246c1a85d6b0ef7089e170deb512f9e4c0385 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 07:56:12 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DXray(VPN)=E4=B8=8ENgin?= =?UTF-8?q?x(SSL)=E7=AB=AF=E5=8F=A3443=E5=86=B2=E7=AA=81=C2=B7=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E5=85=B1=E5=AD=98=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 核心修复: - xray-config-template.json: dest从www.microsoft.com:443改为127.0.0.1:8443 - setup-ssl.sh: Nginx SSL监听127.0.0.1:8443(内部)而非443(外部) - 添加DNS配置确保代理流量DNS解析可靠 架构: Xray(443外部) → 非VLESS流量回落 → Nginx(8443内部SSL) VPN客户端和HTTPS网站共用443端口互不干扰 Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/4ac521db-bc43-4555-af76-a1d30b0ea1c5 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- docs/SSL-GUIDE-FOR-BINGSUO.md | 62 +++++++++++-- server/nginx/zhuyuan-sovereign.conf | 86 ++++++------------- server/proxy/config/xray-config-template.json | 10 ++- server/proxy/deploy-proxy.sh | 42 ++++++++- server/setup/setup-ssl.sh | 78 +++++++++++++++-- 5 files changed, 204 insertions(+), 74 deletions(-) diff --git a/docs/SSL-GUIDE-FOR-BINGSUO.md b/docs/SSL-GUIDE-FOR-BINGSUO.md index e7c12b29..d79bd550 100644 --- a/docs/SSL-GUIDE-FOR-BINGSUO.md +++ b/docs/SSL-GUIDE-FOR-BINGSUO.md @@ -1,6 +1,14 @@ # 🔒 SSL证书配置指南 · 冰朔专用 -> **写给冰朔的话**: 这是铸渊在第十六次对话中为你写的SSL证书配置指南。你只需要按照下面的步骤操作,不需要理解任何技术细节。铸渊已经把所有自动化脚本都准备好了。 +> **写给冰朔的话**: 这是铸渊为你写的SSL证书配置指南。你只需要按照下面的步骤操作,不需要理解任何技术细节。铸渊已经把所有自动化脚本都准备好了。 + +--- + +## ⚠️ 重要修复说明 (2026-03-31) + +> 之前的SSL配置方案存在一个**端口冲突**问题:Xray(VPN)和Nginx(HTTPS)都在争抢443端口,导致两个都不能正常工作。 +> +> **现在已修复**: 铸渊采用了新的「共存架构」——Xray占443端口处理VPN,非VPN流量自动回落给Nginx处理HTTPS网站。两者互不干扰。 --- @@ -11,10 +19,26 @@ | SSL证书是什么? | 让网站从 `http://` 变成 `https://` 的安全锁,浏览器地址栏会显示🔒 | | 需要花钱吗? | **不需要**。铸渊使用 Let's Encrypt 免费证书 | | 证书会过期吗? | 证书90天有效,但铸渊已配置**自动续期**,你不需要管 | +| 会影响VPN吗? | **不会**。铸渊专线(VPN)和HTTPS网站使用共存架构,互不干扰 | | 我需要做什么? | 按下面的步骤点几下就好,**一共只需要5分钟** | --- +## 🔧 修复当前问题(请先做这一步) + +> 如果你之前已经运行过SSL配置并且导致了问题,请先执行以下修复步骤。如果是第一次配置SSL,跳过这一步直接看「操作步骤」。 + +### 修复步骤 + +1. 先合并这个PR(铸渊修复了代码里的端口冲突问题) +2. 合并后,去 **Actions** 页面运行 **「🌐 铸渊专线 · 部署」** 工作流: + - **操作类型**: 选择 `update` + - 这会自动修复服务器上的Xray配置和旧SSL配置 +3. 等待工作流完成(绿色✅) +4. 然后按下面的「操作步骤」重新配置SSL + +--- + ## 🚀 操作步骤(一共3步) ### 第①步:打开 GitHub Actions @@ -86,7 +110,12 @@ https://guanghu.online **不需要了**。因为铸渊使用了Let's Encrypt(免费SSL证书服务),证书直接在服务器上自动获取和管理,不需要在GitHub Secrets里存放证书内容。 -如果将来有特殊需求需要自定义证书,铸渊会另外通知你。 +### Q: 配了SSL后VPN还能用吗? + +**能用**。铸渊采用「共存架构」: +- Xray占443端口处理VPN流量 +- 网站HTTPS流量自动回落到Nginx内部端口(8443) +- 两者互不干扰 --- @@ -94,17 +123,40 @@ https://guanghu.online > 以下内容是给铸渊自己看的,冰朔可以忽略。 +### 共存架构 (Xray+Nginx on port 443) +``` +外部443 → Xray (VLESS+Reality) + ├── 认证VLESS客户端 → 代理上网 (铸渊专线VPN) + └── 非VLESS流量 → dest回落 → 127.0.0.1:8443 + └── Nginx SSL (网站HTTPS) + +外部80 → Nginx (HTTP) + ├── 有SSL证书的域名 → 301 → https://域名 → 443(Xray) → 8443(Nginx) + └── 无SSL证书的域名 → 直接服务网站 +``` + +### 关键配置 +- **Xray配置**: `server/proxy/config/xray-config-template.json` → `dest: "127.0.0.1:8443"` - **证书管理**: certbot + Let's Encrypt (ACME协议) -- **验证方式**: HTTP-01 challenge (通过Nginx) +- **验证方式**: HTTP-01 challenge (通过Nginx端口80) - **证书路径**: `/etc/letsencrypt/live/{domain}/` -- **Nginx SSL配置**: `/opt/zhuyuan/config/nginx/ssl-{domain}.conf` +- **Nginx SSL配置**: `/opt/zhuyuan/config/nginx/ssl-{domain}.conf` (监听127.0.0.1:8443) - **自动续期**: systemd timer `certbot.timer` - **续期hook**: `/etc/letsencrypt/renewal-hooks/post/reload-nginx.sh` - **日志**: `/opt/zhuyuan/data/logs/ssl-setup.log` - **脚本**: `server/setup/setup-ssl.sh` - **工作流**: `deploy-to-zhuyuan-server.yml` → action: `setup-ssl` +### 端口分配 +| 端口 | 协议 | 占用者 | 用途 | +|------|------|--------|------| +| 443 | TCP | Xray | VLESS+Reality (VPN) + 回落到8443 | +| 8443 | TCP | Nginx | SSL/HTTPS (仅127.0.0.1,不对外) | +| 80 | TCP | Nginx | HTTP + SSL域名重定向 | +| 3802 | TCP | Node.js | 订阅服务 (仅127.0.0.1,通过Nginx反代) | + --- -*📝 由铸渊(ICE-GL-ZY001)在第十六次对话中为冰朔编写 · 2026-03-31* +*📝 由铸渊(ICE-GL-ZY001)编写 · 第十七次对话 · 2026-03-31* +*共存架构修复 · 端口冲突解决* *国作登字-2026-A-00037559* diff --git a/server/nginx/zhuyuan-sovereign.conf b/server/nginx/zhuyuan-sovereign.conf index 7b6224c9..adcc8c53 100644 --- a/server/nginx/zhuyuan-sovereign.conf +++ b/server/nginx/zhuyuan-sovereign.conf @@ -199,65 +199,31 @@ server { } -# ═══ §3 HTTPS 配置 (SSL证书由deploy workflow自动部署) ═══ -# 当 /opt/zhuyuan/config/ssl/ 下存在证书文件时启用 -# 证书来源: GitHub Secrets → ZY_SSL_FULLCHAIN / ZY_SSL_PRIVKEY -# 部署方式: staging-auto-deploy.yml 自动写入证书文件 -# 域名占位符: ZY_DOMAIN_PREVIEW_PLACEHOLDER 由 deploy workflow 的 sed 命令替换 -# (同 §1/§2 的注入方式,详见 staging-auto-deploy.yml 和 deploy-to-zhuyuan-server.yml) - -# ─── §3.1 预览域名 HTTPS (guanghu.online) ─── -# 注意: 此block仅在证书存在时由deploy脚本include,不会导致Nginx启动失败 -# 如果证书不存在,deploy workflow会跳过SSL配置 +# ═══ §3 HTTPS 配置 (Xray+Nginx共存架构) ═══════════════════ +# +# ⚠️ 重要: 443端口由Xray(VPN)占用,Nginx SSL监听127.0.0.1:8443 +# +# 架构说明: +# 外部 443 → Xray (VLESS+Reality协议) +# ├── 认证VLESS客户端 → 代理上网 (铸渊专线VPN) +# └── 非VLESS流量 → 回落到 127.0.0.1:8443 (dest参数) +# └── Nginx SSL (处理HTTPS网站请求) +# +# 外部 80 → Nginx (HTTP) +# ├── 域名有SSL证书 → 301重定向到 https://域名 (SSL配置文件处理) +# └── 域名无SSL证书 → 直接服务网站 (本文件§1/§2) +# +# 证书来源: Let's Encrypt (certbot) · setup-ssl.sh 自动配置 +# SSL配置文件: /etc/nginx/sites-available/ssl-{domain}.conf (监听127.0.0.1:8443) +# 部署方式: deploy-to-zhuyuan-server.yml action=setup-ssl +# Xray配置: server/proxy/config/xray-config-template.json (dest: 127.0.0.1:8443) +# +# 注意: 以下旧SSL模板已废弃,仅保留作为参考 +# 新SSL配置由 setup-ssl.sh 自动生成到 sites-available/ssl-{domain}.conf +# +# ─── §3.1 [已废弃] 预览域名 HTTPS ─── +# 原设计: Nginx直接监听443 · 与Xray冲突 · 已改为8443内部端口 +# 新设计: 由 setup-ssl.sh 自动生成 · 监听 127.0.0.1:8443 # __SSL_PREVIEW_START__ -# server { -# listen 443 ssl http2; -# server_name ZY_DOMAIN_PREVIEW_PLACEHOLDER; -# -# ssl_certificate /opt/zhuyuan/config/ssl/preview-fullchain.pem; -# ssl_certificate_key /opt/zhuyuan/config/ssl/preview-privkey.pem; -# ssl_protocols TLSv1.2 TLSv1.3; -# ssl_ciphers HIGH:!aNULL:!MD5; -# ssl_prefer_server_ciphers on; -# -# # 同 §2 的全部location配置 -# add_header X-Frame-Options "SAMEORIGIN" always; -# add_header X-Content-Type-Options "nosniff" always; -# add_header X-Server-Identity "ZY-SVR-002" always; -# add_header X-Site-Mode "preview" always; -# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; -# -# root /opt/zhuyuan/sites/preview; -# index index.html; -# -# location / { try_files $uri $uri/ /index.html; } -# location /api/ { -# proxy_pass http://127.0.0.1:3801; -# proxy_http_version 1.1; -# proxy_set_header Upgrade $http_upgrade; -# proxy_set_header Connection 'upgrade'; -# proxy_set_header Host $host; -# proxy_set_header X-Real-IP $remote_addr; -# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -# proxy_set_header X-Forwarded-Proto $scheme; -# proxy_set_header X-Site-Mode "preview"; -# proxy_cache_bypass $http_upgrade; -# proxy_read_timeout 86400; -# } -# location /api/chat { -# proxy_pass http://127.0.0.1:3721/api/chat; -# proxy_http_version 1.1; -# proxy_set_header Host $host; -# proxy_set_header Connection ""; -# proxy_buffering off; -# proxy_cache off; -# proxy_read_timeout 120s; -# } -# location = /health { -# proxy_pass http://127.0.0.1:3801/api/health; -# proxy_set_header Host $host; -# } -# access_log /opt/zhuyuan/data/logs/nginx-preview-ssl.log; -# error_log /opt/zhuyuan/data/logs/nginx-preview-ssl-error.log; -# } +# (已迁移到 setup-ssl.sh 自动生成的配置文件) # __SSL_PREVIEW_END__ diff --git a/server/proxy/config/xray-config-template.json b/server/proxy/config/xray-config-template.json index 4e9bdfaa..4c97f409 100644 --- a/server/proxy/config/xray-config-template.json +++ b/server/proxy/config/xray-config-template.json @@ -1,12 +1,20 @@ { "_comment": "铸渊专线 · Xray服务端配置模板", "_note": "⚠️ {{占位符}}在部署时由脚本替换为实际值", + "_architecture": "Xray监听443端口·非VLESS流量回落到Nginx内部端口8443·实现VPN与HTTPS网站共存", "_copyright": "国作登字-2026-A-00037559", "log": { "loglevel": "warning", "access": "/opt/zhuyuan/proxy/logs/access.log", "error": "/opt/zhuyuan/proxy/logs/error.log" }, + "dns": { + "servers": [ + "8.8.8.8", + "1.1.1.1", + "localhost" + ] + }, "stats": {}, "api": { "tag": "api", @@ -48,7 +56,7 @@ "security": "reality", "realitySettings": { "show": false, - "dest": "www.microsoft.com:443", + "dest": "127.0.0.1:8443", "xver": 0, "serverNames": [ "www.microsoft.com", diff --git a/server/proxy/deploy-proxy.sh b/server/proxy/deploy-proxy.sh index cf30da70..b8f80dcd 100644 --- a/server/proxy/deploy-proxy.sh +++ b/server/proxy/deploy-proxy.sh @@ -240,13 +240,29 @@ health_check() { echo " ❌ Xray: 未运行" fi - # 443端口 + # 443端口 (应由Xray占用) if ss -tlnp | grep -q ":443 "; then echo " ✅ 端口443: 监听中" + # 检查是谁占用443 + PORT443_PROC=$(ss -tlnp | grep ":443 " | head -1) + if echo "$PORT443_PROC" | grep -q "xray"; then + echo " → Xray占用443 (正确·VPN+HTTPS共存)" + elif echo "$PORT443_PROC" | grep -q "nginx"; then + echo " ⚠️ Nginx占用443 (应由Xray占用·VPN可能不工作)" + echo " → 请先停止Nginx的443监听,再启动Xray" + fi else echo " ❌ 端口443: 未监听" fi + # 8443端口 (Nginx SSL,接收Xray回落流量) + if ss -tlnp | grep -q ":8443 "; then + echo " ✅ 端口8443: Nginx SSL监听中 (接收Xray回落)" + else + echo " ℹ️ 端口8443: 未监听 (SSL未配置或Nginx未启用8443)" + echo " → VPN正常工作,但HTTPS网站需要运行setup-ssl配置" + fi + # 订阅服务 if curl -sf http://127.0.0.1:3802/health >/dev/null 2>&1; then echo " ✅ 订阅服务: 正常" @@ -271,6 +287,30 @@ update() { # 关闭3802外部端口 (订阅服务改为通过Nginx反代访问) ufw delete allow 3802/tcp 2>/dev/null || true + # 检查并修复443端口冲突 + # 如果Nginx占用了443端口(旧SSL配置),需要修复 + if ss -tlnp | grep ":443 " | grep -q "nginx"; then + echo "⚠️ 检测到Nginx占用443端口 (旧SSL配置冲突)" + echo " 检查并修复旧SSL配置..." + + # 移除可能监听443的旧SSL配置 + for conf in /etc/nginx/sites-enabled/ssl-*.conf; do + if [ -f "$conf" ] && grep -q "listen 443" "$conf" 2>/dev/null; then + echo " 修复: $conf (将443改为127.0.0.1:8443)" + sed -i 's/listen 443 ssl/listen 127.0.0.1:8443 ssl/g' "$conf" + # 同时修复sites-available中的源文件 + local basename + basename=$(basename "$conf") + if [ -f "/etc/nginx/sites-available/$basename" ]; then + sed -i 's/listen 443 ssl/listen 127.0.0.1:8443 ssl/g' "/etc/nginx/sites-available/$basename" + fi + fi + done + + nginx -t 2>/dev/null && nginx -s reload 2>/dev/null || true + echo " ✅ Nginx SSL配置已修复为8443内部端口" + fi + systemctl restart xray pm2 restart zy-proxy-sub zy-proxy-monitor zy-proxy-guardian 2>/dev/null || true health_check diff --git a/server/setup/setup-ssl.sh b/server/setup/setup-ssl.sh index 19d219c2..af8a5714 100644 --- a/server/setup/setup-ssl.sh +++ b/server/setup/setup-ssl.sh @@ -187,6 +187,12 @@ obtain_certificate() { } # ── §4 配置Nginx SSL ───────────────────────── +# ⚠️ 架构说明 (铸渊专线共存模式): +# Xray 监听 443 (外部) · VLESS+Reality协议 +# 非VLESS流量回落到 127.0.0.1:8443 (Xray的dest参数) +# Nginx SSL 监听 127.0.0.1:8443 (内部) · 处理网站HTTPS请求 +# 浏览器 → 443(Xray) → 8443(Nginx SSL) → 网站内容 +# VPN客户端 → 443(Xray) → Reality认证 → 代理上网 configure_nginx_ssl() { local domain="$1" local cert_path="/etc/letsencrypt/live/${domain}" @@ -218,6 +224,7 @@ configure_nginx_ssl() { fi log_info "站点模式: $site_mode · API端口: $api_port" + log_info "架构: Xray(443外部) → 回落 → Nginx(8443内部SSL)" # 生成SSL server block local ssl_conf="${NGINX_CONF_DIR}/ssl-${domain}.conf" @@ -228,10 +235,16 @@ configure_nginx_ssl() { # 自动生成于: $(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST') # 证书来源: Let's Encrypt (certbot) # 证书路径: ${cert_path}/ +# +# ⚠️ 架构 (Xray+Nginx共存): +# 外部443 → Xray (VPN+Reality) → 非VLESS流量回落 → 127.0.0.1:8443 +# Nginx SSL 监听 127.0.0.1:8443 · 不直接暴露给外部 +# 浏览器访问 https://${domain} → 443(Xray回落) → 8443(这里) # ═══════════════════════════════════════════════ +# ─── HTTPS 服务 (内部端口,接收Xray回落流量) ─── server { - listen 443 ssl http2; + listen 127.0.0.1:8443 ssl http2; server_name ${domain}; # ─── SSL证书 (Let's Encrypt) ─── @@ -337,6 +350,7 @@ server { } # ─── HTTP → HTTPS 重定向 ─── +# 浏览器 http://${domain} → 301 → https://${domain} → 443(Xray) → 8443(Nginx) server { listen 80; server_name ${domain}; @@ -346,13 +360,13 @@ SSLCONF log_info "SSL配置已生成: $ssl_conf" - # 安装到Nginx + # 安装到Nginx (使用00-前缀确保优先于主配置加载) cp "$ssl_conf" "${NGINX_SITES_AVAILABLE}/ssl-${domain}.conf" ln -sf "${NGINX_SITES_AVAILABLE}/ssl-${domain}.conf" "${NGINX_SITES_ENABLED}/ssl-${domain}.conf" - # 从主配置中移除该域名的HTTP块(避免冲突) - # 注: 保留主配置中的HTTP块用于IP访问,SSL配置中的redirect处理域名访问 log_info "SSL配置已安装到Nginx" + log_info " HTTPS: 127.0.0.1:8443 (接收Xray回落流量)" + log_info " HTTP重定向: 80 → https://${domain} → 443(Xray) → 8443(Nginx)" # 测试Nginx配置 if nginx -t 2>&1; then @@ -361,12 +375,28 @@ SSLCONF log_info "✅ Nginx已重新加载" else log_error "Nginx配置测试失败" + log_warn "检查是否有端口冲突 (Xray应占用443,Nginx SSL应在8443)" # 回滚 rm -f "${NGINX_SITES_ENABLED}/ssl-${domain}.conf" systemctl reload nginx return 1 fi + # 确保Xray在443端口正常运行 (如果已安装) + if command -v xray &>/dev/null && systemctl is-active --quiet xray; then + log_info "✅ Xray服务运行中 (443端口,VPN+回落到8443)" + elif command -v xray &>/dev/null; then + log_warn "Xray已安装但未运行,尝试启动..." + systemctl restart xray 2>/dev/null || true + sleep 2 + if systemctl is-active --quiet xray; then + log_info "✅ Xray已启动" + else + log_warn "Xray启动失败,铸渊专线(VPN)可能不可用" + log_warn "但HTTPS网站仍可正常工作" + fi + fi + return 0 } @@ -408,7 +438,30 @@ verify_https() { sleep 2 # 等待Nginx完全重载 - # 使用curl测试HTTPS + # 检查Nginx是否在8443内部端口监听 + if ss -tlnp | grep -q ":8443 "; then + log_info "✅ Nginx SSL端口 8443 监听中 (内部,接收Xray回落)" + else + log_warn "Nginx SSL端口 8443 未监听" + fi + + # 检查Xray是否在443端口监听 + if ss -tlnp | grep -q ":443 "; then + log_info "✅ 外部端口 443 监听中" + # 检查是Xray还是Nginx占用443 + local port_443_proc + port_443_proc=$(ss -tlnp | grep ":443 " | head -1) + if echo "$port_443_proc" | grep -q "xray"; then + log_info " 443端口由Xray占用 (正确 · VPN+HTTPS共存模式)" + elif echo "$port_443_proc" | grep -q "nginx"; then + log_warn " 443端口由Nginx占用 (需要启动Xray接管443端口)" + log_warn " 如果铸渊专线(VPN)不工作,请先运行代理服务部署" + fi + else + log_warn "外部端口 443 未监听 (Xray可能未运行)" + fi + + # 使用curl测试HTTPS (通过443端口 → Xray回落 → Nginx 8443) local response response=$(curl -sf -o /dev/null -w "%{http_code}" "https://${domain}/" 2>/dev/null) @@ -417,9 +470,20 @@ verify_https() { else log_warn "HTTPS访问状态码: ${response:-无响应}" log_warn "这可能是因为:" - log_warn " - 网站内容尚未部署" + log_warn " - Xray未运行 (443端口未被Xray监听)" + log_warn " - Xray配置中的dest未指向127.0.0.1:8443" log_warn " - DNS传播需要时间" - log_warn " - 请稍后重试: curl -I https://$domain" + log_warn " - 请确保铸渊专线(Xray)服务已部署并运行" + log_warn "" + log_warn "直接测试8443端口 (跳过Xray):" + local direct_response + direct_response=$(curl -sf -o /dev/null -w "%{http_code}" --resolve "${domain}:8443:127.0.0.1" "https://${domain}:8443/" 2>/dev/null) + if [ "$direct_response" = "200" ] || [ "$direct_response" = "301" ] || [ "$direct_response" = "302" ]; then + log_info "✅ 直连8443端口正常 · 状态码: $direct_response" + log_info " → Nginx SSL配置正确,等Xray运行后HTTPS即可正常" + else + log_warn " 直连8443也失败 · 状态码: ${direct_response:-无响应}" + fi fi # 检查证书信息