群晖 NAS 通过 frp 内网穿透 Docker 服务(songloft 58091)实战记录
背景
在群晖 NAS 上用 Docker 部署了一个 songloft 音乐服务,容器端口 58091 已映射到群晖宿主机。想通过有公网 IP 的云服务器(CentOS 7)做 frp 内网穿透,让外网也能访问这个服务。
看似简单的一条规则,中间踩了不少坑,记录下来供参考。
环境说明
| 角色 | 设备 | 系统 | 软件 | 配置文件 |
|---|---|---|---|---|
| 服务端 | 云服务器 117.72.72.6 | CentOS 7 | frps 0.72.0 | /opt/frp/frp_0.72.0_linux_amd64/frps.toml |
| 客户端 | 群晖 NAS 192.168.31.82 | DSM | frpc 0.61.1(套件) | /volume5/@appstore/frpc/bin/frpc.toml |
frps 监听 7000,dashboard 面板可以看到所有注册的代理。
目标服务
群晖上的 docker-compose.yml:
services:
songloft:
image: songloft/songloft:latest
container_name: songloft
restart: unless-stopped
ports:
- "58091:58091"
volumes:
- /volume5/docker/songloft:/app/data
- /volume1/music:/app/music
environment:
TZ: Asia/Shanghai
LISTEN_PORT: "58091"
容器端口 58091 已经映射到群晖宿主机 58091,所以 frp 只需要穿透宿主机的 58091。
问题现象
在 frps 面板里可以看到已有的几条规则(file_browser、music_player、nas_webdav、wiznote)状态都是 online,但新加的 songloft 始终不出现。
排查过程
坑一:改错了配置文件
一开始凭经验改了某个 frpc.toml,重启 frpc 后面板里还是看不到新规则。
关键动作:找到 frpc 进程,看它实际用的是哪个配置文件。
ps -ef | grep frpc
输出:
root 11850 1 0 Sep11 ? 00:00:33 /volume5/@appstore/frpc/bin/frpc -c /volume5/@appstore/frpc/bin/frpc.toml
-c 后面才是真正生效的路径。之前改的是别的文件,当然不生效。
结论:改配置前一定先确认进程用的哪个文件。
坑二:分不清服务端和客户端
一开始在云服务器(CentOS)上找 frpc 进程,结果:
ps -ef | grep frpc
# 只有 grep 自己的进程
后来才反应过来:云服务器是 frps(服务端),群晖才是 frpc(客户端)。
- frps 的进程名是
frps,配置是frps.toml - frpc 的进程名是
frpc,配置是frpc.toml
面板显示的是客户端注册上来的代理,所以规则改了不生效,要去客户端排查。
坑三:TOML 语法的引号
写 frpc 配置时,字符串必须加英文引号:
# ❌ 会解析失败
serverAddr = 117.72.72.6
type = tcp
auth.method = token
# ✅ 正确
serverAddr = "117.72.72.6"
type = "tcp"
auth.method = "token"
TOML 一旦有语法错误,整个文件加载失败,所有规则都不会注册,不只是新加的那条。
验证语法可以用 Python:
python3 -c "import tomllib; tomllib.load(open('/path/to/frpc.toml','rb')); print('OK')"
或者用 cat -A 看有没有中文引号、全角空格混进去。
坑四:kill 掉进程后套件没自动拉起
配置文件改好后,用 kill 11850 想让 frpc 重载,结果进程没了,规则全部变成 offline。
尝试用 synopkg 启动:
synopkg start frpc-0.61.1
# {"action":"prepare","error":{"code":150,"description":"Failed to load package info"},"success":false}
synopkg status frpc-0.61.1
# "status":"non_installed"
套件状态显示 non_installed,但文件明明还在 /volume5/@appstore/frpc/。这是套件状态损坏了。
最终解法:直接重启 NAS。重启后 frpc 被守护进程正常拉起:
ps -ef | grep frpc
# root 11881 1 ... /volume5/@appstore/frpc/bin/frpc -c /volume5/@appstore/frpc/bin/frpc.toml
经验:群晖套件管理的服务,不要随手 kill,优先用 synopkg restart,实在不行重启 NAS 最省事。
最终配置
/volume5/@appstore/frpc/bin/frpc.toml:
serverAddr = "117.72.72.6"
serverPort = 7000
auth.method = "token"
auth.token = "your-token-here"
[[proxies]]
name = "wiznote"
type = "tcp"
localIP = "0.0.0.0"
localPort = 5555
remotePort = 5555
[[proxies]]
name = "nas_webdav"
type = "tcp"
localIP = "0.0.0.0"
localPort = 5005
remotePort = 5005
[[proxies]]
name = "file_browser"
type = "tcp"
localIP = "0.0.0.0"
localPort = 3663
remotePort = 3663
[[proxies]]
name = "music_player"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5678
remotePort = 5680
[[proxies]]
name = "songloft"
type = "tcp"
localIP = "127.0.0.1"
localPort = 58091
remotePort = 58091
关于 localIP:
127.0.0.1:frpc 和容器在同一宿主机,通过 Docker 端口映射访问0.0.0.0:监听所有网卡时适用192.168.31.82:frpc 跑在容器里、需要走局域网 IP 时用
大部分情况用 127.0.0.1 就够了。
防火墙放行
穿透成功只是第一步,外网能不能访问还要看两层防火墙:
1. 云服务器本机防火墙(CentOS 7)
72
sudo firewall-cmd --zone=public --add-port=58091/tcp --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
2. 云服务商安全组
登录云控制台,在安全组里放行 58091 TCP 入站。这一步最容易漏,很多人只改了系统防火墙,忘了云平台的安全组。
3. frps 服务端限制
检查 /opt/frp/frp_0.72.0_linux_amd64/frps.toml 有没有 allowPorts 限制:
toml
allowPorts = [
{ start = 5000, end = 6000 },
]
如果有,需要把 58091 加进去。
验证
在群晖上确认本地服务正常:
72
sudo netstat -tlnp | grep 58091
curl -I http://127.0.0.1:58091
在前台跑一次 frpc,确认规则注册成功:
72
/volume5/@appstore/frpc/bin/frpc -c /volume5/@appstore/frpc/bin/frpc.toml
日志里出现这些就说明成功:
text
proxy added: [wiznote nas_webdav file_browser music_player songloft]
[songloft] start proxy success
外网测试:
curl -I http://117.72.72.6:58091
浏览器打开 http://117.72.72.6:58091,看到 songloft 页面即完成。
经验总结
| 现象 | 根因 | 解决 |
|---|---|---|
| 面板不显示新规则 | 改错了配置文件 | `ps -ef |
| 所有规则 offline | 进程被 kill 后未自动拉起 | 用 synopkg restart 而非 kill,或重启 NAS |
synopkg 报 non_installed | 套件状态损坏 | 重启 NAS 后自动恢复 |
| 服务端找不到 frpc | 角色搞混了 | 云服务器是 frps,群晖是 frpc |
| 配置改了不生效 | TOML 语法错误导致整体加载失败 | 检查英文引号,用 python3 tomllib 验证 |
| 外网访问不通 | 防火墙或安全组未放行 | 系统防火墙 + 云安全组两边都要放行 |
安全提醒
- 不要直接把敏感服务的端口暴露到公网。songloft 这类有管理后台的服务,尽量配合 frp 的
https类型 + 域名 + SSL 证书,或者在 frps 端加vhost认证。 - Token 和密码不要泄露。frpc 配置文件里的
auth.token、docker-compose.yml里的ADMIN_PASSWORD都属于敏感信息,写博客或截图时务必打码。 - 定期更新 frp 版本。老版本可能存在安全漏洞,服务端和客户端版本尽量保持一致。
结语
frp 本身配置不复杂,真正消耗时间的是定位问题:改错文件、角色混淆、套件状态异常、防火墙多层拦截。掌握 ps -ef | grep frpc 看进程实际参数、看日志确认注册结果、分清楚服务端和客户端,基本就能快速定位绝大多数问题。
