部署NaiveProxy 使用 8443,Nginx 保持占用 80/443

引用

https://github.com/RayWangQvQ/naiveproxy-docker

摘要

目标是在现有 VPS 上新增一套 NaiveProxy 服务端,而不改动现有 Nginx 对 80/443 的占用关系。最终形态为:

  • 现有网站/Nginx 继续占用 80/443
  • 新增域名 np.example.com 指向该 VPS
  • Nginx 仅负责该域名的 80 端口 ACME 校验与可选跳转
  • Let’s Encrypt 证书由 Nginx + Certbot 签发和续期
  • naiveproxy-docker 通过 cert-mode=2 导入现有证书
  • NaiveProxy 对外监听 8443
  • 客户端使用 naive+https://user:[email protected]:8443

这是当前约束下最简单、失败面最小、维护成本最低的方案。

目标状态

部署完成后应满足:

  • http://np.example.com/.well-known/acme-challenge/... 可被 Let’s Encrypt 访问
  • np.example.com 的证书由 Let’s Encrypt 签发
  • 宿主机 8443/tcp 对外开放,并由 NaiveProxy 容器接收
  • 80/443 仍由原 Nginx/原网站使用,不与 NaiveProxy 冲突
  • NaiveProxy 客户端可通过 np.example.com:8443 建立连接
  • 证书续期后,NaiveProxy 能重新加载新证书

公共接口与外部约定

需要新增或确认以下外部接口/配置:

  • 域名:
    • np.example.com,专用于 NaiveProxy
  • 外部端口:
    • 80/tcp:Nginx 用于 ACME HTTP-01 校验
    • 443/tcp:现有网站继续使用
    • 8443/tcp:NaiveProxy 对外服务
  • 证书文件路径:
    • /etc/letsencrypt/live/np.example.com/fullchain.pem
    • /etc/letsencrypt/live/np.example.com/privkey.pem
  • NaiveProxy 连接串格式:
    • naive+https://:@np.example.com:8443#naive

实施步骤

1. 前置确认

实施前确认以下条件:

  • 你可修改该 VPS 的 Nginx 配置
  • np.example.com 已解析到目标 VPS 公网 IP
  • 防火墙/安全组允许外网访问 80/tcp 与 8443/tcp
  • VPS 已安装 Docker
  • VPS 上现有 Nginx 可正常重载

默认假设:

  • 系统为 Debian/Ubuntu 系
  • 使用 Certbot 申请 Let’s Encrypt 证书
  • NaiveProxy 用独立子域名,不与现有站点复用同一 server_name

2. 为 np.example.com 配置 Nginx 的 ACME 校验入口

在 Nginx 中新增一个仅服务于 np.example.com 的 80 端口 server:

server {
    listen 80;
    server_name np.example.com;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/letsencrypt;
        default_type text/plain;
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

说明:

  • 该配置的主要作用是让 Certbot 的 webroot 模式完成 HTTP-01 验证
  • 即使未来没有在 443 上为 np.example.com 提供网页服务,这个 80 入口仍需保留用于续期
  • 443 上不需要为 np.example.com 提供站点服务,因为 NaiveProxy 实际走 8443

3. 准备 ACME webroot 目录并校验 Nginx

执行顺序:

  1. 创建 /var/www/letsencrypt/.well-known/acme-challenge
  2. 设置目录权限给 Nginx 运行用户
  3. nginx -t
  4. systemctl reload nginx

验收标准:

  • 访问 http://np.example.com/.well-known/acme-challenge/test 时,若放入测试文件,应可从公网读取到

4. 申请 Let’s Encrypt 证书

使用 webroot 模式签发:

sudo certbot certonly \
--webroot -w /var/www/letsencrypt \
-d np.example.com \
--agree-tos -m [email protected] --non-interactive

申请完成后确认:

- /etc/letsencrypt/live/np.example.com/fullchain.pem 存在
- /etc/letsencrypt/live/np.example.com/privkey.pem 存在

关键约束:

  • HTTP-01 必须走 80
  • 不需要释放 443
  • 不需要让 NaiveProxy 参与签证书流程

5. 部署 naiveproxy-docker

采用 install.sh 路线,使用 cert-mode=2 导入已有证书。

推荐参数策略:

- -t np.example.com
- -o 2
- -c /etc/letsencrypt/live/np.example.com/fullchain.pem
- -k /etc/letsencrypt/live/np.example.com/privkey.pem
- -s 8443
- -w 8083
- -u <naive_user>
- -p <strong_password>
- -f <fake_site_url>

示例:

./install.sh \
-t np.example.com \
-o 2 \
-c /etc/letsencrypt/live/np.example.com/fullchain.pem \
-k /etc/letsencrypt/live/np.example.com/privkey.pem \
-w 8083 \
-s 8443 \
-u naiveuser \
-p 'strong-password-here' \
-f https://demo.cloudreve.org \
--verbose

实施要求:

  • 8443 必须不被其他服务占用
  • 8083 只是内部 HTTP 端口,通常不对外开放
  • 伪装站点 URL 必须可正常访问,推荐选稳定的 HTTPS 目标
  • 用户名和密码必须是高强度值

6. 证书挂载策略确认

虽然 install.sh 可直接引用 Let’s Encrypt 文件路径,但实施时应优先确认容器如何看到续期后的证书更新。

推荐默认策略:

  • 若脚本生成的是“直接绑定两个证书文件”,先保留
  • 但计划中应准备在落地后检查容器证书更新行为
  • 如果验证发现续期后容器无法读到新证书,则切换为“挂载整个 /etc/letsencrypt 目录只读”方案

保守运维建议:

  • 无论是否能自动感知新证书,续期成功后都显式执行一次 caddy reload 或容器重启

7. 配置证书续期后的服务重载

增加 Certbot deploy hook,在续期成功后执行:

  • 优先:容器内 caddy reload --config /data/Caddyfile
  • 兜底:docker restart naiveproxy

默认选择:

  • 先尝试 reload
  • 若部署后的镜像/路径与预期不符,则使用 docker restart naiveproxy

验收标准:

  • 模拟续期或人工触发 hook 后,NaiveProxy 仍可正常建立连接
  • 新证书在客户端握手时可见

8. 放通防火墙/安全组

需要开放:

  • 80/tcp
  • 8443/tcp

无需新增开放:

  • 443/tcp 已由现有网站使用
  • 8083/tcp 不应对公网开放

9. 客户端接入

客户端统一使用:

  • 地址:np.example.com
  • 端口:8443
  • 用户名:部署时指定
  • 密码:部署时指定

输出格式以 install.sh 最终打印结果为准,但必须确保连接串包含 :8443。

10. 验收

按顺序验收:

  1. DNS 正确解析到 VPS
  2. certbot 证书申请成功
  3. 宿主机 8443 正在监听
  4. NaiveProxy 容器正常运行,无 TLS/Caddyfile 报错
  5. 使用客户端连接 np.example.com:8443 成功
  6. 现有网站 80/443 服务不受影响
  7. 人工执行证书 reload/restart 后代理仍可用

测试场景与验收用例

基础连通性

  • np.example.com DNS 解析正确
  • 外网能访问 80
  • 外网能访问 8443
  • 443 上原网站不受影响

证书相关

  • 首次申请证书成功
  • 证书链为 Let’s Encrypt 公网可信链
  • NaiveProxy 握手时返回的证书与 np.example.com 匹配
  • 证书续期后,NaiveProxy 能重新加载新证书

服务稳定性

  • 重启 Docker 后 NaiveProxy 自动恢复
  • 重载 Nginx 不影响 NaiveProxy
  • NaiveProxy 容器重启不影响现有网站

错误场景

  • 8443 被占用时,部署应失败并明确暴露端口冲突
  • np.example.com 未解析到该 VPS 时,证书申请应失败
  • /.well-known/acme-challenge/ 路由错误时,Certbot 应失败
  • 证书路径错误时,NaiveProxy 启动应报 TLS 文件加载错误

不做的事情

本方案明确不包含:

  • 不改造现有 443 为 Nginx stream + ssl_preread
  • 不引入第二公网 IP
  • 不使用自签名证书或私有 CA
  • 不通过 Nginx http 反向代理 NaiveProxy
  • 不让 Caddy 自动申请证书

回滚方案

如果部署失败或效果不符合预期,回滚应极简:

  1. 停止并删除 NaiveProxy 容器
  2. 关闭 8443/tcp 防火墙规则
  3. 删除 np.example.com 的 Nginx ACME 配置
  4. reload Nginx
  5. 可选删除 np.example.com 的 Let’s Encrypt 证书与 DNS 记录

回滚后现有网站应恢复到部署前状态,因为本方案本身不改动现有 80/443 的服务归属。

假设与默认值

默认采用以下假设,除非你后续明确修改:

  • 域名使用独立子域名 np.example.com
  • 系统为 Debian/Ubuntu
  • 证书工具为 Certbot
  • 证书来源为 Let’s Encrypt
  • 部署方式为 naiveproxy-docker 官方 install.sh
  • 外部端口固定为 8443
  • 内部 HTTP 端口使用 8083
  • 续期后优先执行 reload,失败再 restart
  • 伪装站点使用稳定 HTTPS 目标
  • 客户端可接受显式填写 :8443

后续只剩的用户输入

实施前还需要你提供这些确定值:

  • 最终域名,例如 np.example.com
  • 联系邮箱,用于 Let’s Encrypt
  • NaiveProxy 用户名
  • NaiveProxy 密码
  • 伪装站点 URL
  • VPS 系统版本
  • 现有 Nginx 是否由你完全控制

评论

还没有人评论,抢个沙发吧...

Viagle Blog

欢迎来到我的个人博客网站