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

一、问题背景
系统架构如下:
text
公网 HTTPS 前端
├─ 业务请求 → 公网后端
└─ 文件请求 → 内网 NAS
主要存在两个问题:
- 文件经过公网服务器中转时,会受到公网带宽限制。
- 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-OriginAccess-Control-Allow-Private-NetworkRange请求支持- 短时 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 配置异常,也不会影响基本文件访问功能。