通过 Docker、Nginx Proxy Manager 与 FRP 安全地暴露内网服务

1506 字
8 分钟
通过 Docker、Nginx Proxy Manager 与 FRP 安全地暴露内网服务

概述#

本指南通过组合使用 Docker、Nginx Proxy Manager (NPM) 和 FRP,安全地将位于内网(如家庭 NAS、开发电脑)的服务发布到公网。目标效果:

  • 只能通过自定义的 HTTPS 域名(如 nas.yourdomain.com)访问内网服务。
  • 内网服务的真实 IP 和端口不暴露,所有流量经由加密隧道和反向代理,降低端口扫描风险。
  • 使用 Docker Compose 统一管理云端服务,通过 NPM 的 Web UI 轻松管理域名和 SSL 证书。
NginxProxyManager
/
nginx-proxy-manager
Waiting for api.github.com...
00K
0K
0K
Waiting...
fatedier
/
frp
Waiting for api.github.com...
00K
0K
0K
Waiting...

架构概览#

用户 → HTTPS 域名 → 云服务器(443) → NPM 容器 → Docker 内部网络 → frps 容器(代理端口) → FRP 隧道 → 内网 frpc 客户端 → 内网目标服务

先决条件#

  • 一台云服务器 (VPS),拥有一个公网 IP 地址。
  • 一个域名,并将需要使用的子域名(如 nas)通过 A 记录解析到云服务器公网 IP。
  • 云服务器已安装 Docker 与 Docker Compose。
  • 一台内网设备(如 NAS),并已知其内网 IP 地址与端口。
防火墙

推荐为云服务器开启防火墙,仅放行 80814437000 端口;其他由 FRP 动态创建的代理端口不需要对公网开放。

部署步骤#

第一步:准备服务器环境#

在云服务器上创建一个项目目录,用于存放所有配置文件。

Terminal window
mkdir my-proxy-stack
cd my-proxy-stack

在该目录中,我们将创建两个核心文件:frps.tomldocker-compose.yml

第二步:配置 frps 服务(frps.toml#

创建 frps.toml 文件,这是 FRP 服务端的配置文件。

# frps 监听的地址,"0.0.0.0" 表示监听所有网络接口
bindAddr = "0.0.0.0"
# frps 用于和 frpc 客户端通信的主端口
bindPort = 7000
# [关键配置] 代理服务监听的地址
# 设置为 0.0.0.0 意味着它会监听在容器的内部IP上,
# 这样同一个 Docker 网络中的其他容器(如NPM)才能访问它。
# 因为该端口不会通过 Docker 映射到宿主机,所以公网无法访问,是安全的。
proxyBindAddr = "0.0.0.0"
# 认证配置
[auth]
# 指定认证方式与令牌
method = "token"
token = "YOUR_VERY_STRONG_AND_SECRET_TOKEN"
WARNING

token 务必设置一个长且复杂的字符串,防止未经授权的客户端连接。建议使用 openssl rand -hex 32 生成。

关键点

  • bindPort = 7000:FRP 的”握手”端口,需要暴露给公网,让内网的 frpc 能连接上来。
  • proxyBindAddr = 0.0.0.0:确保 NPM 容器可以访问到 frps 的代理端口。
TIP

如果云服务器开启了防火墙/安全组,记得放行 TCP 7000 端口。

第三步:编排 Docker 服务(docker-compose.yml#

创建 docker-compose.yml 文件,这是定义和运行我们所有服务的蓝图。

version: '3.8'
services:
# 服务一:Nginx Proxy Manager (NPM)
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
# 公开的 Web 端口,用于接收外部用户的访问请求
- '80:80' # HTTP
- '443:443' # HTTPS
# NPM 自身的管理后台端口
- '81:81'
volumes:
- ./npm-data:/data
- ./npm-letsencrypt:/etc/letsencrypt
networks:
# 将 NPM 加入到我们自定义的共享网络中
- proxy-net
# 服务二:FRP Server (frps)
frps:
image: 'snowdreamtech/frps:latest'
container_name: frps
restart: unless-stopped
volumes:
# 将宿主机的 frps.toml 配置文件挂载到容器内部
- ./frps.toml:/etc/frp/frps.toml
ports:
# [关键] 只发布 frps 的主服务端口 7000 到公网
- '7000:7000'
# [注意] 千万不要在这里发布任何代理端口
networks:
# 将 frps 也加入到同一个共享网络中,以便和 NPM 通信
- proxy-net
# 定义一个自定义的桥接网络,用于服务间的内部通信
networks:
proxy-net:
driver: bridge
端口安全

ports 中只暴露 80814437000 四个端口。由 FRP 动态创建的代理端口不对公网暴露——它们仅存在于 Docker 内部网络 proxy-net 中,只有 NPM 可以访问。

第四步:启动云端服务#

my-proxy-stack 目录下,运行以下命令来启动所有服务:

Terminal window
docker-compose up -d

检查服务是否正常运行:

Terminal window
docker-compose ps

您应该能看到 nginx-proxy-managerfrps 两个容器都处于 Up 状态。

第五步:配置 Nginx Proxy Manager#

  1. 登录后台:在浏览器中访问 http://<你的服务器IP>:81

  2. 首次登录

    配置项默认值
    邮箱admin@example.com
    密码changeme
    WARNING

    登录后会立即要求修改邮箱和密码,请务必修改为安全的凭据。

  3. 添加代理主机 (Proxy Host)

    点击 HostsProxy HostsAdd Proxy Host

    Details 标签页:

    配置项
    Domain Namesnas.yourdomain.com
    Schemehttp
    Forward Hostname / IPfrps(Docker 内部容器名)
    Forward Port8096(frpc 穿透的端口)
    Block Common Exploits勾选

    SSL 标签页:

    配置项
    SSL CertificateRequest a new SSL Certificate
    Force SSL勾选
    HTTP/2 Support勾选

    点击 Save,NPM 会自动申请 SSL 证书并配置反向代理。

TIP

可在 NPM 中为不同内网服务添加多个 Proxy Host,并配合 Access List 实现基于用户名/密码的二次保护。

第六步:配置内网客户端(frpc.toml#

在您的内网设备(如 NAS)上,创建 frpc.toml 配置文件。

# 服务器(云主机)的公网 IP 地址
serverAddr = "YOUR_SERVER_PUBLIC_IP"
# 与 frps.toml 中设置的 bindPort 一致
serverPort = 7000
[auth]
method = "token"
token = "YOUR_VERY_STRONG_AND_SECRET_TOKEN"
# 定义一个代理
[[proxies]]
name = "nas_http_proxy" # 为代理起一个唯一的名字
type = "tcp" # 代理类型
localIP = "192.168.1.10" # 内网服务的 IP
localPort = 5000 # 内网服务的端口
remotePort = 5000 # 远程服务器的端口

启动 frpc 客户端(以 Linux 为例):

Terminal window
./frpc -c ./frpc.toml

建议将其设置为开机自启的服务。

第七步:最终验证#

验证清单
  • 成功验证:在浏览器中访问 https://nas.yourdomain.com,应能看到内网服务页面,且浏览器地址栏显示锁形图标。
  • 安全验证:尝试访问 http://<你的服务器IP>:8096,应当失败(无法连接)。这证明内网服务端口未暴露在公网,只能通过 NPM 安全访问。
NOTE

若证书申请失败,检查以下几点:

  • 域名 A 记录是否正确解析到服务器 IP
  • 80 / 443 端口是否被其他服务占用或被防火墙屏蔽
  • 服务器系统时间是否同步

参考#

通过 Docker、Nginx Proxy Manager 与 FRP 安全地暴露内网服务
https://lunary.cc/posts/通过-dockernginx-proxy-manager-与-frp-安全地暴露内网服务/
作者
鹤望兰
发布于
2025-09-06
许可协议
CC BY-NC-SA 4.0