Merge pull request #239 from qinfendebingshuo/copilot/fix-network-access-issue
fix: restore Reality dest to external target, add CN relay architecture
This commit is contained in:
commit
37f790342b
|
|
@ -24,6 +24,7 @@ on:
|
|||
- restart
|
||||
- send-subscription
|
||||
- update-dashboard
|
||||
- setup-cn-relay
|
||||
default: 'status'
|
||||
email:
|
||||
description: '目标邮箱 (仅send-subscription时需要)'
|
||||
|
|
@ -89,6 +90,7 @@ jobs:
|
|||
${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \
|
||||
"cd /opt/zhuyuan/proxy-deploy && \
|
||||
export ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \
|
||||
export ZY_CN_RELAY_HOST='${{ secrets.ZY_CN_SERVER_HOST }}' && \
|
||||
bash deploy-proxy.sh ${{ github.event.inputs.action }}"
|
||||
|
||||
- name: '🧹 清理SSH密钥'
|
||||
|
|
@ -189,3 +191,76 @@ jobs:
|
|||
- name: '🧹 清理'
|
||||
if: always()
|
||||
run: rm -f ~/.ssh/id_deploy /tmp/quota-status.json
|
||||
|
||||
# ═══ §4 CN中转配置 ═══
|
||||
setup-cn-relay:
|
||||
name: '🇨🇳 CN中转配置'
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.inputs.action == 'setup-cn-relay'
|
||||
|
||||
steps:
|
||||
- name: '📥 检出代码'
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: '🔑 配置CN服务器SSH密钥'
|
||||
env:
|
||||
SSH_KEY: ${{ secrets.ZY_CN_SERVER_KEY }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "$SSH_KEY" > ~/.ssh/id_cn
|
||||
chmod 600 ~/.ssh/id_cn
|
||||
|
||||
if ! head -1 ~/.ssh/id_cn | grep -q "BEGIN"; then
|
||||
echo "❌ CN服务器SSH密钥格式异常"
|
||||
echo " 请检查 ZY_CN_SERVER_KEY Secret"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ssh-keyscan -H ${{ secrets.ZY_CN_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
ssh -i ~/.ssh/id_cn \
|
||||
-o StrictHostKeyChecking=accept-new \
|
||||
-o BatchMode=yes \
|
||||
-o ConnectTimeout=15 \
|
||||
${{ secrets.ZY_CN_SERVER_USER }}@${{ secrets.ZY_CN_SERVER_HOST }} \
|
||||
"echo '✅ CN服务器SSH连接成功'"
|
||||
|
||||
- name: '📦 上传CN中转脚本'
|
||||
run: |
|
||||
scp -i ~/.ssh/id_cn \
|
||||
-o StrictHostKeyChecking=accept-new \
|
||||
server/proxy/setup/setup-cn-relay.sh \
|
||||
${{ secrets.ZY_CN_SERVER_USER }}@${{ secrets.ZY_CN_SERVER_HOST }}:/tmp/setup-cn-relay.sh
|
||||
|
||||
- name: '🇨🇳 执行CN中转配置'
|
||||
run: |
|
||||
ssh -i ~/.ssh/id_cn \
|
||||
-o StrictHostKeyChecking=accept-new \
|
||||
${{ secrets.ZY_CN_SERVER_USER }}@${{ secrets.ZY_CN_SERVER_HOST }} \
|
||||
"chmod +x /tmp/setup-cn-relay.sh && \
|
||||
export ZY_SG_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \
|
||||
sudo -E bash /tmp/setup-cn-relay.sh"
|
||||
|
||||
- name: '💚 CN中转验证'
|
||||
run: |
|
||||
CN_HOST="${{ secrets.ZY_CN_SERVER_HOST }}"
|
||||
echo "🔍 验证CN中转..."
|
||||
|
||||
# 检查中转端口
|
||||
if nc -z -w5 "$CN_HOST" 2053 2>/dev/null; then
|
||||
echo "✅ CN中转端口 2053: 可达"
|
||||
else
|
||||
echo "⚠️ CN中转端口 2053: 暂不可达 (可能需要等待防火墙生效)"
|
||||
fi
|
||||
|
||||
# 检查HTTP健康
|
||||
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://${CN_HOST}/health" 2>/dev/null || echo "000")
|
||||
if [ "$HTTP_CODE" = "200" ]; then
|
||||
echo "✅ CN HTTP健康检查: 正常"
|
||||
else
|
||||
echo "⚠️ CN HTTP: 状态码 $HTTP_CODE (可能需要等待)"
|
||||
fi
|
||||
|
||||
- name: '🧹 清理SSH密钥'
|
||||
if: always()
|
||||
run: rm -f ~/.ssh/id_cn
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
# 🔒 SSL证书配置指南 · 冰朔专用
|
||||
|
||||
> **写给冰朔的话**: 这是铸渊在第十六次对话中为你写的SSL证书配置指南。你只需要按照下面的步骤操作,不需要理解任何技术细节。铸渊已经把所有自动化脚本都准备好了。
|
||||
> **写给冰朔的话**: 这是铸渊为你写的SSL证书配置指南。你只需要按照下面的步骤操作,不需要理解任何技术细节。铸渊已经把所有自动化脚本都准备好了。
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 重要修复说明 (2026-03-31)
|
||||
|
||||
> 之前的SSL配置方案存在一个**VPN与HTTPS冲突**问题。
|
||||
>
|
||||
> **根因**: Xray的Reality协议需要`dest`指向真实的Microsoft网站来骗过GFW的探测。之前错误地改成了指向内部Nginx端口,导致GFW检测到证书不匹配,封锁了VPN连接。
|
||||
>
|
||||
> **现在已修复**:
|
||||
> - VPN: Xray占443端口,`dest`恢复指向`www.microsoft.com:443` → VPN正常工作
|
||||
> - 网站: HTTP通过80端口正常访问,HTTPS通过8443端口访问
|
||||
> - CN中转: 新增广州服务器中转,国内用户无需直连国际网即可使用VPN
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -11,10 +24,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 +115,12 @@ https://guanghu.online
|
|||
|
||||
**不需要了**。因为铸渊使用了Let's Encrypt(免费SSL证书服务),证书直接在服务器上自动获取和管理,不需要在GitHub Secrets里存放证书内容。
|
||||
|
||||
如果将来有特殊需求需要自定义证书,铸渊会另外通知你。
|
||||
### Q: 配了SSL后VPN还能用吗?
|
||||
|
||||
**能用**。铸渊采用「分离架构」:
|
||||
- Xray占443端口处理VPN流量 (dest→microsoft.com反探测)
|
||||
- 网站HTTPS在8443端口独立运行 (不通过Xray)
|
||||
- 两者互不干扰
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -94,17 +128,57 @@ https://guanghu.online
|
|||
|
||||
> 以下内容是给铸渊自己看的,冰朔可以忽略。
|
||||
|
||||
### Reality反探测架构
|
||||
```
|
||||
外部443 → Xray (VLESS+Reality)
|
||||
├── 认证VLESS客户端 → 代理上网 (铸渊专线VPN)
|
||||
└── GFW探测流量 → dest回落 → www.microsoft.com:443
|
||||
→ 返回真实Microsoft证书 → GFW判断"这是正常网站" → 放行
|
||||
|
||||
外部8443 → Nginx SSL (HTTPS网站)
|
||||
└── 独立SSL证书 (Let's Encrypt)
|
||||
|
||||
外部80 → Nginx (HTTP)
|
||||
└── 直接服务网站
|
||||
|
||||
CN中转 (广州→新加坡):
|
||||
CN:2053 → SG:443 (TCP转发·VPN中转)
|
||||
CN:80/api/proxy-sub/ → SG订阅服务 (国内获取配置)
|
||||
```
|
||||
|
||||
### ⚠️ dest为什么必须指向microsoft.com?
|
||||
Reality协议的`dest`是GFW反探测的关键。当GFW探测443端口时:
|
||||
- 正确: `dest: "www.microsoft.com:443"` → 返回Microsoft真实证书 → 通过
|
||||
- 错误: `dest: "127.0.0.1:8443"` → 返回guanghu.online证书 → 与SNI(microsoft.com)不匹配 → 被标记为可疑 → VPN被封
|
||||
|
||||
### 关键配置
|
||||
- **Xray配置**: `server/proxy/config/xray-config-template.json` → `dest: "www.microsoft.com:443"`
|
||||
- **证书管理**: 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` (监听8443)
|
||||
- **CN中转脚本**: `server/proxy/setup/setup-cn-relay.sh`
|
||||
- **自动续期**: 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`
|
||||
|
||||
### 端口分配 (SG服务器)
|
||||
| 端口 | 协议 | 占用者 | 用途 |
|
||||
|------|------|--------|------|
|
||||
| 443 | TCP | Xray | VLESS+Reality (VPN) · dest→microsoft.com |
|
||||
| 8443 | TCP | Nginx | HTTPS网站 (独立·不通过Xray) |
|
||||
| 80 | TCP | Nginx | HTTP网站 + 订阅API反代 |
|
||||
| 3802 | TCP | Node.js | 订阅服务 (127.0.0.1·通过Nginx反代) |
|
||||
|
||||
### 端口分配 (CN中转服务器)
|
||||
| 端口 | 协议 | 占用者 | 用途 |
|
||||
|------|------|--------|------|
|
||||
| 2053 | TCP | Nginx stream | VPN中转 → SG:443 |
|
||||
| 80 | TCP | Nginx | 订阅API反代 → SG |
|
||||
|
||||
---
|
||||
|
||||
*📝 由铸渊(ICE-GL-ZY001)在第十六次对话中为冰朔编写 · 2026-03-31*
|
||||
*📝 由铸渊(ICE-GL-ZY001)编写 · 第十八次对话 · 2026-03-31*
|
||||
*VPN修复 + CN中转架构 + Reality反探测修正*
|
||||
*国作登字-2026-A-00037559*
|
||||
|
|
|
|||
|
|
@ -199,65 +199,33 @@ 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配置
|
||||
# __SSL_PREVIEW_START__
|
||||
# server {
|
||||
# listen 443 ssl http2;
|
||||
# server_name ZY_DOMAIN_PREVIEW_PLACEHOLDER;
|
||||
# ═══ §3 HTTPS/VPN 配置 (Xray Reality反探测架构) ═══════════════
|
||||
#
|
||||
# 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;
|
||||
# ⚠️ 重要: 443端口由Xray(VPN)占用,dest指向www.microsoft.com:443
|
||||
#
|
||||
# # 同 §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;
|
||||
# Reality反探测架构 (正确方案):
|
||||
# 外部 443 → Xray (VLESS+Reality协议)
|
||||
# ├── 认证VLESS客户端 → 代理上网 (铸渊专线VPN)
|
||||
# └── 非VLESS流量(GFW探测) → dest回落到 www.microsoft.com:443
|
||||
# → 返回真实Microsoft证书 → GFW认为是正常HTTPS → 通过
|
||||
#
|
||||
# root /opt/zhuyuan/sites/preview;
|
||||
# index index.html;
|
||||
# 外部 80 → Nginx (HTTP)
|
||||
# ├── 域名访问 → 直接服务网站 (本文件§1/§2)
|
||||
# └── 订阅API → /api/proxy-sub/ (反代到端口3802)
|
||||
#
|
||||
# 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;
|
||||
# }
|
||||
# __SSL_PREVIEW_END__
|
||||
# ⚠️ 为什么dest不能指向127.0.0.1:8443?
|
||||
# GFW探测时会检查TLS证书是否匹配serverNames (www.microsoft.com)
|
||||
# 如果dest返回guanghu.online的证书 → 证书不匹配 → 被标记为可疑 → VPN被封
|
||||
# 所以dest必须指向真实的microsoft.com以通过反探测
|
||||
#
|
||||
# CN中转架构 (广州→新加坡):
|
||||
# 国内用户 → CN:2053 (Nginx stream TCP转发) → SG:443 (Xray)
|
||||
# 国内订阅 → CN:80/api/proxy-sub/ → SG:80/api/proxy-sub/
|
||||
#
|
||||
# SSL方案:
|
||||
# 网站通过HTTP(80端口)访问 · 不在443端口共存HTTPS
|
||||
# 如需HTTPS · 使用Cloudflare CDN代理或独立配置
|
||||
#
|
||||
# Xray配置: server/proxy/config/xray-config-template.json
|
||||
# CN中转: server/proxy/setup/setup-cn-relay.sh
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
{
|
||||
"_comment": "铸渊专线 · Xray服务端配置模板",
|
||||
"_note": "⚠️ {{占位符}}在部署时由脚本替换为实际值",
|
||||
"_architecture": "Xray监听443端口·非VLESS流量回落到www.microsoft.com:443(Reality反探测伪装)·VPN与网站HTTP(80端口)共存",
|
||||
"_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",
|
||||
|
|
|
|||
|
|
@ -72,6 +72,18 @@ save_server_host() {
|
|||
echo "ZY_SERVER_HOST=${ZY_SERVER_HOST}" >> "$KEYS_FILE"
|
||||
chmod 600 "$KEYS_FILE"
|
||||
fi
|
||||
|
||||
# 保存CN中转地址 (如果有)
|
||||
if [ -n "${ZY_CN_RELAY_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then
|
||||
if grep -q "^ZY_CN_RELAY_HOST=" "$KEYS_FILE" 2>/dev/null; then
|
||||
sed -i "s|^ZY_CN_RELAY_HOST=.*|ZY_CN_RELAY_HOST=${ZY_CN_RELAY_HOST}|" "$KEYS_FILE"
|
||||
else
|
||||
echo "" >> "$KEYS_FILE"
|
||||
echo "# CN中转服务器地址 (部署时自动写入)" >> "$KEYS_FILE"
|
||||
echo "ZY_CN_RELAY_HOST=${ZY_CN_RELAY_HOST}" >> "$KEYS_FILE"
|
||||
fi
|
||||
echo " ✅ ZY_CN_RELAY_HOST 已保存到 .env.keys"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── install: 首次完整安装 ─────────────────────
|
||||
|
|
@ -240,9 +252,18 @@ 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模式)"
|
||||
echo " → dest回落: www.microsoft.com:443 (Reality反探测)"
|
||||
elif echo "$PORT443_PROC" | grep -q "nginx"; then
|
||||
echo " ⚠️ Nginx占用443 (应由Xray占用·VPN可能不工作)"
|
||||
echo " → 请先停止Nginx的443监听,再启动Xray"
|
||||
fi
|
||||
else
|
||||
echo " ❌ 端口443: 未监听"
|
||||
fi
|
||||
|
|
@ -271,6 +292,25 @@ update() {
|
|||
# 关闭3802外部端口 (订阅服务改为通过Nginx反代访问)
|
||||
ufw delete allow 3802/tcp 2>/dev/null || true
|
||||
|
||||
# 检查并修复443端口冲突
|
||||
# 如果Nginx占用了443端口(旧SSL配置),需要移除以让Xray接管
|
||||
if ss -tlnp | grep ":443 " | grep -q "nginx"; then
|
||||
echo "⚠️ 检测到Nginx占用443端口 (旧SSL配置冲突)"
|
||||
echo " 修复: 移除Nginx的443监听配置以让Xray接管..."
|
||||
|
||||
# 移除旧的SSL配置 (不再通过Xray回落提供HTTPS)
|
||||
for conf in /etc/nginx/sites-enabled/ssl-*.conf; do
|
||||
[ -e "$conf" ] || continue
|
||||
if grep -q "listen.*443\|listen.*8443" "$conf" 2>/dev/null; then
|
||||
echo " 移除旧SSL配置: $conf"
|
||||
rm -f "$conf"
|
||||
fi
|
||||
done
|
||||
|
||||
nginx -t 2>/dev/null && nginx -s reload 2>/dev/null || true
|
||||
echo " ✅ Nginx旧SSL配置已清理"
|
||||
fi
|
||||
|
||||
systemctl restart xray
|
||||
pm2 restart zy-proxy-sub zy-proxy-monitor zy-proxy-guardian 2>/dev/null || true
|
||||
health_check
|
||||
|
|
|
|||
|
|
@ -80,6 +80,34 @@ function getServerHost() {
|
|||
return '0.0.0.0';
|
||||
}
|
||||
|
||||
// ── 获取CN中转服务器信息 ─────────────────────
|
||||
// 优先级: 环境变量 > .env.keys文件
|
||||
function getCnRelayHost() {
|
||||
// 1. 从环境变量读取
|
||||
if (process.env.ZY_CN_RELAY_HOST) {
|
||||
return process.env.ZY_CN_RELAY_HOST;
|
||||
}
|
||||
|
||||
// 2. 从.env.keys文件读取
|
||||
try {
|
||||
const content = fs.readFileSync(KEYS_FILE, 'utf8');
|
||||
for (const line of content.split('\n')) {
|
||||
if (line.startsWith('#') || !line.includes('=')) continue;
|
||||
const [key, ...vals] = line.split('=');
|
||||
if (key.trim() === 'ZY_CN_RELAY_HOST') {
|
||||
const val = vals.join('=').trim();
|
||||
if (val) return val;
|
||||
}
|
||||
}
|
||||
} catch (err) { /* ignore */ }
|
||||
|
||||
return null; // CN中转未配置
|
||||
}
|
||||
|
||||
function getCnRelayPort() {
|
||||
return parseInt(process.env.ZY_CN_RELAY_PORT || '2053', 10);
|
||||
}
|
||||
|
||||
// ── 读取流量配额信息 ────────────────────────
|
||||
function getQuotaInfo() {
|
||||
const quotaFile = path.join(DATA_DIR, 'quota-status.json');
|
||||
|
|
@ -116,9 +144,45 @@ function generateVlessUri(keys, serverHost) {
|
|||
|
||||
// ── 生成Clash YAML配置 ───────────────────────
|
||||
function generateClashYaml(keys, serverHost) {
|
||||
const cnRelayHost = getCnRelayHost();
|
||||
const cnRelayPort = getCnRelayPort();
|
||||
|
||||
// CN中转节点 (如果已配置)
|
||||
// 注: CN中转是透明TCP转发(CN:2053 → SG:443),所以Reality设置仍指向SG的配置
|
||||
// servername/public-key/short-id 与SG直连节点完全相同,因为TLS握手实际发生在SG端
|
||||
const cnProxyBlock = cnRelayHost ? `
|
||||
- name: "🇨🇳 铸渊专线-CN中转"
|
||||
type: vless
|
||||
server: ${cnRelayHost}
|
||||
port: ${cnRelayPort}
|
||||
uuid: ${keys.ZY_PROXY_UUID}
|
||||
network: tcp
|
||||
tls: true
|
||||
udp: true
|
||||
flow: xtls-rprx-vision
|
||||
servername: www.microsoft.com
|
||||
reality-opts:
|
||||
public-key: ${keys.ZY_PROXY_REALITY_PUBLIC_KEY}
|
||||
short-id: ${keys.ZY_PROXY_REALITY_SHORT_ID}
|
||||
client-fingerprint: chrome` : '';
|
||||
|
||||
// 代理组中的节点列表
|
||||
const proxyList = cnRelayHost
|
||||
? ` - "🇨🇳 铸渊专线-CN中转"
|
||||
- "🏛️ 铸渊专线-SG直连"`
|
||||
: ' - "🏛️ 铸渊专线-SG直连"';
|
||||
|
||||
const proxyListWithDirect = cnRelayHost
|
||||
? ` - "🇨🇳 铸渊专线-CN中转"
|
||||
- "🏛️ 铸渊专线-SG直连"
|
||||
- DIRECT`
|
||||
: ` - "🏛️ 铸渊专线-SG直连"
|
||||
- DIRECT`;
|
||||
|
||||
return `# 铸渊专线 · ZY-Proxy Subscription
|
||||
# 自动生成 · ${new Date().toISOString()}
|
||||
# ⚠️ 请勿分享此配置
|
||||
${cnRelayHost ? `# 🇨🇳 包含CN中转节点 (国内直连广州→转发新加坡)` : ''}
|
||||
|
||||
port: 7890
|
||||
socks-port: 7891
|
||||
|
|
@ -127,7 +191,7 @@ mode: rule
|
|||
log-level: info
|
||||
|
||||
proxies:
|
||||
- name: "🏛️ 铸渊专线-SG"
|
||||
- name: "🏛️ 铸渊专线-SG直连"
|
||||
type: vless
|
||||
server: ${serverHost}
|
||||
port: 443
|
||||
|
|
@ -141,23 +205,23 @@ proxies:
|
|||
public-key: ${keys.ZY_PROXY_REALITY_PUBLIC_KEY}
|
||||
short-id: ${keys.ZY_PROXY_REALITY_SHORT_ID}
|
||||
client-fingerprint: chrome
|
||||
${cnProxyBlock}
|
||||
|
||||
proxy-groups:
|
||||
- name: "🌐 铸渊专线"
|
||||
type: select
|
||||
proxies:
|
||||
- "🏛️ 铸渊专线-SG"
|
||||
- DIRECT
|
||||
${proxyListWithDirect}
|
||||
|
||||
- name: "🤖 AI服务"
|
||||
type: select
|
||||
proxies:
|
||||
- "🏛️ 铸渊专线-SG"
|
||||
${proxyList}
|
||||
|
||||
- name: "💻 开发工具"
|
||||
type: select
|
||||
proxies:
|
||||
- "🏛️ 铸渊专线-SG"
|
||||
${proxyList}
|
||||
|
||||
rules:
|
||||
# AI服务
|
||||
|
|
|
|||
|
|
@ -0,0 +1,255 @@
|
|||
#!/bin/bash
|
||||
# ═══════════════════════════════════════════════
|
||||
# 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
|
||||
# 📜 Copyright: 国作登字-2026-A-00037559
|
||||
# ═══════════════════════════════════════════════
|
||||
# server/proxy/setup/setup-cn-relay.sh
|
||||
# 🇨🇳 广州CN中转 · 安装配置脚本
|
||||
#
|
||||
# 在广州服务器(ZY-SVR-004)上执行
|
||||
# 将VPN流量从国内中转到新加坡服务器
|
||||
#
|
||||
# 架构:
|
||||
# 国内用户 → CN:2053 (Nginx stream) → SG:443 (Xray VPN)
|
||||
# 国内用户 → CN:80/api/proxy-sub/ → SG订阅服务 (配置获取)
|
||||
#
|
||||
# 用法:
|
||||
# bash setup-cn-relay.sh <SG_SERVER_IP>
|
||||
# bash setup-cn-relay.sh 43.134.16.246
|
||||
#
|
||||
# 环境变量:
|
||||
# ZY_SG_SERVER_HOST — 新加坡服务器IP (必需)
|
||||
# ═══════════════════════════════════════════════
|
||||
|
||||
set -uo pipefail
|
||||
# 注意: 不使用 set -e,因为 grep/nc 等命令在无匹配时返回非零
|
||||
# 关键步骤手动检查错误
|
||||
|
||||
# 颜色
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[CN中转]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[CN中转]${NC} ⚠️ $1"; }
|
||||
log_error() { echo -e "${RED}[CN中转]${NC} ❌ $1"; }
|
||||
log_step() { echo -e "${BLUE}[CN中转]${NC} 📌 $1"; }
|
||||
|
||||
# ── 参数 ──────────────────────────────────────
|
||||
SG_HOST="${ZY_SG_SERVER_HOST:-${1:-}}"
|
||||
RELAY_PORT="${ZY_CN_RELAY_PORT:-2053}"
|
||||
CN_ROOT="/opt/zhuyuan-cn"
|
||||
|
||||
if [ -z "$SG_HOST" ]; then
|
||||
log_error "缺少新加坡服务器IP"
|
||||
echo ""
|
||||
echo "用法: bash setup-cn-relay.sh <SG_SERVER_IP>"
|
||||
echo " 或: ZY_SG_SERVER_HOST=1.2.3.4 bash setup-cn-relay.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "════════════════════════════════════════"
|
||||
echo "🇨🇳 铸渊专线 · CN中转配置"
|
||||
echo "════════════════════════════════════════"
|
||||
echo ""
|
||||
echo " SG服务器: $SG_HOST"
|
||||
echo " 中转端口: $RELAY_PORT"
|
||||
echo ""
|
||||
|
||||
# ── §1 安装Nginx stream模块 ──────────────────
|
||||
log_step "§1 检查Nginx stream模块"
|
||||
|
||||
# 检查Nginx是否安装
|
||||
if ! command -v nginx &>/dev/null; then
|
||||
log_info "安装Nginx..."
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq nginx
|
||||
fi
|
||||
|
||||
# 检查stream模块是否可用
|
||||
if nginx -V 2>&1 | grep -q "with-stream"; then
|
||||
log_info "✅ Nginx stream模块已可用"
|
||||
else
|
||||
log_warn "Nginx未包含stream模块,安装完整版..."
|
||||
apt-get install -y -qq nginx-full 2>/dev/null || apt-get install -y -qq nginx-extras 2>/dev/null || true
|
||||
|
||||
if nginx -V 2>&1 | grep -q "with-stream"; then
|
||||
log_info "✅ Nginx stream模块已安装"
|
||||
else
|
||||
log_error "无法安装Nginx stream模块"
|
||||
log_warn "尝试使用socat替代方案..."
|
||||
apt-get install -y -qq socat 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── §2 配置Nginx stream中转 ──────────────────
|
||||
log_step "§2 配置TCP中转 (端口$RELAY_PORT → $SG_HOST:443)"
|
||||
|
||||
# 创建stream配置目录
|
||||
mkdir -p /etc/nginx/stream-conf.d
|
||||
|
||||
# 创建stream中转配置
|
||||
cat > /etc/nginx/stream-conf.d/zy-relay.conf << STREAMCONF
|
||||
# ═══════════════════════════════════════════════
|
||||
# 🇨🇳 铸渊专线 · CN中转 · TCP Stream
|
||||
# 自动生成于: $(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST')
|
||||
#
|
||||
# 架构: 国内用户 → CN:${RELAY_PORT} → SG:443 (Xray VPN)
|
||||
# 协议: 原始TCP转发 (不解密,不修改)
|
||||
# ═══════════════════════════════════════════════
|
||||
|
||||
upstream zy_sg_backend {
|
||||
server ${SG_HOST}:443;
|
||||
}
|
||||
|
||||
server {
|
||||
listen ${RELAY_PORT};
|
||||
proxy_pass zy_sg_backend;
|
||||
proxy_timeout 300s;
|
||||
proxy_connect_timeout 10s;
|
||||
}
|
||||
STREAMCONF
|
||||
|
||||
log_info "✅ Stream中转配置已创建"
|
||||
|
||||
# 确保主Nginx配置包含stream块
|
||||
NGINX_MAIN="/etc/nginx/nginx.conf"
|
||||
if ! grep -q "stream-conf.d" "$NGINX_MAIN" 2>/dev/null; then
|
||||
log_info "添加stream块到nginx.conf..."
|
||||
|
||||
# 在文件末尾添加stream块 (stream块必须在http块之外)
|
||||
cat >> "$NGINX_MAIN" << 'STREAMBLOCK'
|
||||
|
||||
# ═══ 铸渊专线 · CN中转 Stream ═══
|
||||
stream {
|
||||
include /etc/nginx/stream-conf.d/*.conf;
|
||||
}
|
||||
STREAMBLOCK
|
||||
log_info "✅ stream块已添加到nginx.conf"
|
||||
fi
|
||||
|
||||
# ── §3 配置Nginx HTTP反代订阅 ────────────────
|
||||
log_step "§3 配置订阅服务反代 (CN → SG订阅)"
|
||||
|
||||
# 创建或更新CN的Nginx HTTP配置
|
||||
CN_NGINX_CONF="/etc/nginx/sites-available/zy-cn-relay.conf"
|
||||
cat > "$CN_NGINX_CONF" << HTTPCONF
|
||||
# ═══════════════════════════════════════════════
|
||||
# 🇨🇳 铸渊专线 · CN中转 · HTTP反代
|
||||
# 自动生成于: $(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST')
|
||||
#
|
||||
# 功能: 将订阅请求反代到SG服务器
|
||||
# 国内用户通过CN服务器获取订阅配置 (无需国际网)
|
||||
# ═══════════════════════════════════════════════
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
|
||||
# ─── 健康检查 ───
|
||||
location = /health {
|
||||
return 200 '{"status":"ok","service":"zy-cn-relay","relay_to":"${SG_HOST}"}';
|
||||
add_header Content-Type application/json;
|
||||
}
|
||||
|
||||
# ─── 订阅服务反代 → SG服务器 ───
|
||||
location /api/proxy-sub/ {
|
||||
proxy_pass http://${SG_HOST}/api/proxy-sub/;
|
||||
proxy_http_version 1.1;
|
||||
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_connect_timeout 10s;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
|
||||
# ─── 默认页面 ───
|
||||
location / {
|
||||
return 200 '铸渊CN中转节点 · ZY-SVR-004';
|
||||
add_header Content-Type 'text/plain; charset=utf-8';
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/zy-cn-relay.log;
|
||||
error_log /var/log/nginx/zy-cn-relay-error.log;
|
||||
}
|
||||
HTTPCONF
|
||||
|
||||
# 启用配置
|
||||
ln -sf "$CN_NGINX_CONF" /etc/nginx/sites-enabled/zy-cn-relay.conf
|
||||
# 移除默认配置以避免冲突
|
||||
rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
|
||||
|
||||
log_info "✅ HTTP反代配置已创建"
|
||||
|
||||
# ── §4 防火墙配置 ────────────────────────────
|
||||
log_step "§4 防火墙配置"
|
||||
|
||||
ufw allow 80/tcp comment "HTTP (订阅反代)" 2>/dev/null || true
|
||||
ufw allow ${RELAY_PORT}/tcp comment "ZY-Relay (VPN中转)" 2>/dev/null || true
|
||||
ufw reload 2>/dev/null || true
|
||||
log_info "✅ 防火墙已开放: 80(HTTP) + ${RELAY_PORT}(VPN中转)"
|
||||
|
||||
# ── §5 测试配置并重载 ────────────────────────
|
||||
log_step "§5 测试并应用配置"
|
||||
|
||||
if nginx -t 2>&1; then
|
||||
systemctl reload nginx
|
||||
log_info "✅ Nginx配置测试通过 · 已重载"
|
||||
else
|
||||
log_error "Nginx配置测试失败"
|
||||
nginx -t 2>&1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── §6 保存中转状态 ──────────────────────────
|
||||
log_step "§6 保存中转状态"
|
||||
|
||||
mkdir -p "$CN_ROOT/data"
|
||||
cat > "$CN_ROOT/data/relay-status.json" << STATUSJSON
|
||||
{
|
||||
"service": "zy-cn-relay",
|
||||
"sg_server": "$SG_HOST",
|
||||
"relay_port": $RELAY_PORT,
|
||||
"subscription_proxy": "http://CN_IP/api/proxy-sub/",
|
||||
"vpn_relay": "CN_IP:$RELAY_PORT → $SG_HOST:443",
|
||||
"configured_at": "$(TZ=Asia/Shanghai date -u '+%Y-%m-%dT%H:%M:%SZ')",
|
||||
"status": "active"
|
||||
}
|
||||
STATUSJSON
|
||||
|
||||
log_info "✅ 中转状态已保存"
|
||||
|
||||
# ── §7 健康检查 ──────────────────────────────
|
||||
log_step "§7 健康检查"
|
||||
|
||||
sleep 1
|
||||
|
||||
# 检查中转端口
|
||||
if ss -tlnp | grep -q ":${RELAY_PORT} "; then
|
||||
log_info "✅ 中转端口 ${RELAY_PORT}: 监听中"
|
||||
else
|
||||
log_warn "中转端口 ${RELAY_PORT}: 未监听 (可能需要等待)"
|
||||
fi
|
||||
|
||||
# 检查HTTP
|
||||
if curl -sf http://127.0.0.1/health >/dev/null 2>&1; then
|
||||
log_info "✅ HTTP健康检查: 正常"
|
||||
else
|
||||
log_warn "HTTP健康检查: 未响应"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "════════════════════════════════════════"
|
||||
echo "✅ CN中转配置完成"
|
||||
echo ""
|
||||
echo "中转架构:"
|
||||
echo " VPN: 国内用户 → CN:${RELAY_PORT} → SG:443 (Xray)"
|
||||
echo " 订阅: http://CN_IP/api/proxy-sub/sub/{token}"
|
||||
echo ""
|
||||
echo "下一步:"
|
||||
echo " 1. 运行 deploy-proxy-service.yml action=update 更新SG的Xray配置"
|
||||
echo " 2. 重新发送订阅邮件 (新配置包含CN中转节点)"
|
||||
echo "════════════════════════════════════════"
|
||||
|
|
@ -187,6 +187,13 @@ obtain_certificate() {
|
|||
}
|
||||
|
||||
# ── §4 配置Nginx SSL ─────────────────────────
|
||||
# ⚠️ 架构说明 (Reality反探测优先):
|
||||
# Xray 监听 443 (外部) · VLESS+Reality协议
|
||||
# dest回落到 www.microsoft.com:443 (反探测伪装·不可改为内部端口)
|
||||
# Nginx SSL 监听 8443 (外部直接访问) · 独立HTTPS服务
|
||||
#
|
||||
# 如果Xray未安装 → Nginx直接监听443 (标准HTTPS)
|
||||
# 如果Xray已安装 → Nginx监听8443 (避免端口冲突)
|
||||
configure_nginx_ssl() {
|
||||
local domain="$1"
|
||||
local cert_path="/etc/letsencrypt/live/${domain}"
|
||||
|
|
@ -217,7 +224,22 @@ configure_nginx_ssl() {
|
|||
api_port="3800"
|
||||
fi
|
||||
|
||||
log_info "站点模式: $site_mode · API端口: $api_port"
|
||||
# 确定SSL监听端口: Xray在443时用8443,否则用443
|
||||
local ssl_listen_port="443"
|
||||
local ssl_listen_addr=""
|
||||
if command -v xray &>/dev/null; then
|
||||
ssl_listen_port="8443"
|
||||
ssl_listen_addr=""
|
||||
log_info "检测到Xray已安装 · Nginx SSL使用端口8443 (避免与VPN冲突)"
|
||||
log_info "网站HTTPS: https://${domain}:8443"
|
||||
# 开放8443端口
|
||||
ufw allow 8443/tcp comment "Nginx SSL (Xray共存)" 2>/dev/null || true
|
||||
else
|
||||
log_info "Xray未安装 · Nginx SSL使用标准端口443"
|
||||
log_info "网站HTTPS: https://${domain}"
|
||||
fi
|
||||
|
||||
log_info "站点模式: $site_mode · API端口: $api_port · SSL端口: $ssl_listen_port"
|
||||
|
||||
# 生成SSL server block
|
||||
local ssl_conf="${NGINX_CONF_DIR}/ssl-${domain}.conf"
|
||||
|
|
@ -228,10 +250,14 @@ configure_nginx_ssl() {
|
|||
# 自动生成于: $(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST')
|
||||
# 证书来源: Let's Encrypt (certbot)
|
||||
# 证书路径: ${cert_path}/
|
||||
#
|
||||
# SSL端口: ${ssl_listen_port}
|
||||
# $([ "$ssl_listen_port" = "8443" ] && echo "⚠️ Xray占用443(VPN) · Nginx SSL在8443(直接访问)" || echo "标准HTTPS · 端口443")
|
||||
# ═══════════════════════════════════════════════
|
||||
|
||||
# ─── HTTPS 服务 ───
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen ${ssl_listen_port} ssl http2;
|
||||
server_name ${domain};
|
||||
|
||||
# ─── SSL证书 (Let's Encrypt) ───
|
||||
|
|
@ -336,12 +362,15 @@ server {
|
|||
error_log /opt/zhuyuan/data/logs/nginx-${site_mode}-ssl-error.log;
|
||||
}
|
||||
|
||||
$([ "$ssl_listen_port" = "443" ] && cat << REDIR
|
||||
# ─── HTTP → HTTPS 重定向 ───
|
||||
server {
|
||||
listen 80;
|
||||
server_name ${domain};
|
||||
return 301 https://\$host\$request_uri;
|
||||
return 301 https://\\\$host\\\$request_uri;
|
||||
}
|
||||
REDIR
|
||||
)
|
||||
SSLCONF
|
||||
|
||||
log_info "SSL配置已生成: $ssl_conf"
|
||||
|
|
@ -350,9 +379,15 @@ SSLCONF
|
|||
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"
|
||||
if [ "$ssl_listen_port" = "8443" ]; then
|
||||
log_info " HTTPS: https://${domain}:8443 (直接访问)"
|
||||
log_info " HTTP: http://${domain} (端口80·正常访问)"
|
||||
log_info " VPN: Xray占用443 · dest→microsoft.com (反探测)"
|
||||
else
|
||||
log_info " HTTPS: https://${domain} (标准端口443)"
|
||||
log_info " HTTP重定向: 80 → https://${domain}"
|
||||
fi
|
||||
|
||||
# 测试Nginx配置
|
||||
if nginx -t 2>&1; then
|
||||
|
|
@ -404,35 +439,61 @@ HOOK
|
|||
# ── §6 验证HTTPS ─────────────────────────────
|
||||
verify_https() {
|
||||
local domain="$1"
|
||||
log_step "§6 验证HTTPS: https://$domain"
|
||||
log_step "§6 验证HTTPS: $domain"
|
||||
|
||||
sleep 2 # 等待Nginx完全重载
|
||||
|
||||
# 确定SSL端口
|
||||
local ssl_port="443"
|
||||
if command -v xray &>/dev/null; then
|
||||
ssl_port="8443"
|
||||
fi
|
||||
|
||||
log_info "验证SSL端口: $ssl_port"
|
||||
|
||||
# 检查SSL端口是否监听
|
||||
if ss -tlnp | grep -q ":${ssl_port} "; then
|
||||
log_info "✅ SSL端口 ${ssl_port}: 监听中"
|
||||
else
|
||||
log_warn "SSL端口 ${ssl_port} 未监听"
|
||||
fi
|
||||
|
||||
# 使用curl测试HTTPS
|
||||
local test_url="https://${domain}/"
|
||||
if [ "$ssl_port" != "443" ]; then
|
||||
test_url="https://${domain}:${ssl_port}/"
|
||||
fi
|
||||
|
||||
local response
|
||||
response=$(curl -sf -o /dev/null -w "%{http_code}" "https://${domain}/" 2>/dev/null)
|
||||
response=$(curl -sf -o /dev/null -w "%{http_code}" "$test_url" 2>/dev/null)
|
||||
|
||||
if [ "$response" = "200" ] || [ "$response" = "301" ] || [ "$response" = "302" ]; then
|
||||
log_info "✅ HTTPS访问正常 · 状态码: $response"
|
||||
log_info " → 访问: $test_url"
|
||||
else
|
||||
log_warn "HTTPS访问状态码: ${response:-无响应}"
|
||||
log_warn "这可能是因为:"
|
||||
log_warn " - 网站内容尚未部署"
|
||||
log_warn " - DNS传播需要时间"
|
||||
log_warn " - 请稍后重试: curl -I https://$domain"
|
||||
log_warn " → 尝试访问: $test_url"
|
||||
log_warn " → 可能需要等待DNS传播"
|
||||
fi
|
||||
|
||||
# 检查证书信息
|
||||
echo | openssl s_client -servername "$domain" -connect "${domain}:443" 2>/dev/null | \
|
||||
echo | openssl s_client -servername "$domain" -connect "${domain}:${ssl_port}" 2>/dev/null | \
|
||||
openssl x509 -noout -subject -issuer -dates 2>/dev/null || true
|
||||
|
||||
# 测试HTTP→HTTPS重定向
|
||||
local redirect
|
||||
redirect=$(curl -sf -o /dev/null -w "%{redirect_url}" "http://${domain}/" 2>/dev/null)
|
||||
if echo "$redirect" | grep -q "https"; then
|
||||
log_info "✅ HTTP→HTTPS重定向正常"
|
||||
# 如果是标准443端口,测试HTTP→HTTPS重定向
|
||||
if [ "$ssl_port" = "443" ]; then
|
||||
local redirect
|
||||
redirect=$(curl -sf -o /dev/null -w "%{redirect_url}" "http://${domain}/" 2>/dev/null)
|
||||
if echo "$redirect" | grep -q "https"; then
|
||||
log_info "✅ HTTP→HTTPS重定向正常"
|
||||
else
|
||||
log_warn "HTTP→HTTPS重定向未生效 (可能需要等待DNS)"
|
||||
fi
|
||||
else
|
||||
log_warn "HTTP→HTTPS重定向未生效 (可能需要等待DNS)"
|
||||
log_info "ℹ️ Xray占用443端口,HTTP不会重定向到HTTPS"
|
||||
log_info " → 网站HTTP访问: http://${domain} (端口80)"
|
||||
log_info " → 网站HTTPS访问: https://${domain}:${ssl_port}"
|
||||
log_info " → VPN: 通过Xray端口443正常工作"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue