HTTPS 页面内网直连 NAS:解决 Mixed Content 与公网带宽瓶颈

HTTPS 页面内网直连 NAS:解决 Mixed Content 与公网带宽瓶颈

文章目录

当前端部署在公网 HTTPS 环境,而文件存储在办公室内网 NAS 时,直接访问 HTTP NAS 地址会被浏览器以 Mixed Content 拦截。本文介绍一种"内网 HTTPS 直连优先、服务器中转兜底"的方案,让内网用户以局域网速度预览和下载文件,同时保证外网访问不受影响。

一、问题背景

系统架构如下:

text 复制代码
公网 HTTPS 前端
    ├─ 业务请求 → 公网后端
    └─ 文件请求 → 内网 NAS

主要存在两个问题:

  1. 文件经过公网服务器中转时,会受到公网带宽限制。
  2. HTTPS 页面访问 http://192.168.x.x 等内网地址时,会被浏览器按照 Mixed Content 策略拦截。

NAS 自带的自签名证书通常也无法直接解决,因为浏览器不信任该证书,且证书域名可能与访问地址不匹配。

二、整体解决方案

采用双通道访问机制:

text 复制代码
办公室内网可访问 NAS
    → 使用 NAS HTTPS 地址直接下载

无法访问 NAS
    → 自动回退到服务器中转

核心原则:

  • NAS 直连地址必须使用可信 HTTPS 证书。
  • 后端仅负责权限验证和生成短时签名 URL。
  • 文件数据直接从 NAS 传输到浏览器。
  • 前端通过短超时请求判断 NAS 是否可访问。
  • 探测失败时自动使用服务器中转地址。

三、配置内网 HTTPS 域名

可以为 NAS 配置一个专用域名,例如:

text 复制代码
nas-app.example.com

公网 DNS 不需要为该域名配置 A 记录,办公室内网 DNS 将其解析到 NAS:

text 复制代码
nas-app.example.com → 192.168.x.x

证书可以通过 Let's Encrypt DNS-01 验证申请:

bash 复制代码
sudo certbot certonly --manual \
  --preferred-challenges dns \
  -d nas-app.example.com

DNS-01 只需要验证 TXT 记录,因此特别适合没有公网 IP 的内网服务。

四、使用 AdGuard Home 提供内网 DNS

在 NAS 上部署 AdGuard Home:

bash 复制代码
docker run -d \
  --name adguardhome \
  --restart unless-stopped \
  -p 53:53/tcp \
  -p 53:53/udp \
  -p 3000:3000/tcp \
  adguard/adguardhome

然后添加 DNS 重写:

text 复制代码
nas-app.example.com → 192.168.x.x

路由器 DHCP 的首选 DNS 设置为 NAS 的内网 IP,确保办公室电脑能够获得正确的解析结果。

注意:设置DNS服务器后需要自己电脑重连网络才能生效。

五、部署 NAS HTTPS 网关

可以使用 Nginx 提供 HTTPS 文件访问服务:

nginx 复制代码
server {
    listen 8443 ssl;
    server_name nas-app.example.com;

    ssl_certificate /etc/letsencrypt/live/nas-app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/nas-app.example.com/privkey.pem;

    location = /healthz {
        add_header Access-Control-Allow-Origin "https://app.example.com" always;
        add_header Access-Control-Allow-Private-Network "true" always;
        return 204;
    }

    location /preview/ {
        secure_link $arg_md5,$arg_expires;
        secure_link_md5 "$secure_link_expires$uri ${SIGNING_SECRET}";

        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 410; }

        alias /data/;

        add_header Access-Control-Allow-Origin "https://app.example.com" always;
        add_header Access-Control-Allow-Private-Network "true" always;
        add_header Access-Control-Allow-Headers "Range" always;
        add_header Access-Control-Expose-Headers "Content-Range, Content-Length" always;
    }
}

需要重点配置:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Private-Network
  • Range 请求支持
  • 短时 URL 签名校验
  • NAS 文件目录只读挂载

六、后端与前端处理

后端返回可信 HTTPS 地址:

yaml 复制代码
file-storage:
  direct-access:
    enabled: true
    base-url: https://nas-app.example.com:18443
    signing-secret: <签名密钥>
    expires-in: 2h

前端增加保护逻辑:

typescript 复制代码
if (
  location.protocol === "https:" &&
  directUrl.startsWith("http://")
) {
  return fallbackUrl;
}

然后通过短超时 HEAD 请求探测 NAS:

typescript 复制代码
const response = await fetch(directUrl, {
  method: "HEAD"
});

return response.ok ? directUrl : fallbackUrl;

这样即使后端误返回 HTTP 地址,也不会触发 Mixed Content 报错。

七、验证方法

检查内网 DNS:

bash 复制代码
nslookup nas-app.example.com

预期返回 NAS 内网 IP。

检查 HTTPS:

bash 复制代码
curl -I https://nas-app.example.com:18443/healthz

预期返回:

text 复制代码
HTTP/1.1 204 No Content

检查未携带签名的访问:

bash 复制代码
curl -I https://nas-app.example.com:18443/preview/test.jpg

预期返回 403

检查过期签名时,应返回 410

八、常见问题

问题 可能原因
文件仍然走服务器中转 客户端没有使用内网 DNS
出现 Mixed Content 后端仍然返回 HTTP 地址
出现 CORS 错误 Allow-Origin 与前端域名不一致
签名返回 403 后端和 Nginx 使用的 URI 编码规则不一致
浏览器提示证书错误 使用了 NAS 自签名证书
大文件重连失败 签名 URL 有效期过短
PNA 预检失败 缺少 Allow-Private-Network 响应头

总结

通过内网 DNS、可信 HTTPS 证书、Nginx 文件网关和短时签名 URL,可以让办公室用户直接从 NAS 获取文件,避免公网服务器带宽瓶颈。

前端保留服务器中转作为兜底后,即使用户不在公司网络、NAS 暂时不可用或内网 DNS 配置异常,也不会影响基本文件访问功能。

相关推荐
難釋懷3 小时前
Nginx代理https请求
redis·nginx·https
想学好C++的oMen4 小时前
socket编程TCP
linux·网络·网络协议·tcp/ip
GitLqr19 小时前
别再盲目复制了:彻底搞懂 CORS 的本质与那些“神坑”
安全·http·面试
IPdodo_1 天前
Codex 一直显示 Thinking 怎么办?区分任务运行、界面卡住与会话恢复
http·网络调试
2401_873479401 天前
SOC告警日志中IP归属不明怎么办?部署IP离线库三步提升响应效率
网络·网络协议·tcp/ip
Kina_C1 天前
Apache HTTP Server 安装、配置与高级功能详解
linux·http·apache
想学好C++的oMen1 天前
socket编程UDP
网络协议·udp
chexus1 天前
21. 深入 Nginx HTTP 缓存源码:CDN功能
nginx·http·缓存
GitLqr2 天前
玩转 WebSocket:从原理到 Flutter 实战
websocket·网络协议·flutter