FRP 动态端口与 1Panel 防火墙自动同步:一套可维护的实现方案
在使用 FRP 做内网穿透时,常见的维护痛点是:frpc 配置增加、修改或删除 remotePort 后,frps 服务器上的主机防火墙也要手动同步,否则代理端口可能无法访问;如果长期把防火墙端口全部放开,又会扩大暴露面。
本文介绍一套以 frps 服务端插件为入口、以 frps Dashboard 状态为事实来源、通过 1Panel 防火墙 API 管理规则的实现方案。它适合端口变化频繁、希望继续使用 1Panel 管理防火墙的场景。
一、目标与边界
这套方案解决以下问题:
- frpc 新增一个 TCP 或 UDP 代理后,自动放行对应的 frps 端口。
- 代理删除或长期离线后,自动关闭不再使用的端口。
- IPv4 和 IPv6 同步处理。
- 连续端口自动合并为范围规则,减少 1Panel 后台中的规则数量。
- 自动生成的规则带有稳定标记,便于识别和清理。
- 配置集中在一个 YAML 文件中,Compose 使用相对路径,方便 1Panel 管理。
- 服务重启后能够通过巡检恢复正确状态。
需要注意,主机防火墙只是其中一层。阿里云安全组、其他云防火墙或上游网络 ACL 仍然需要单独允许相应流量;如果云安全组没有放行,主机防火墙自动放行也无法从公网访问。
二、为什么不能只监听端口
简单监听 ss 或 netstat 的结果并不够可靠:
- FRPS 的监听状态不一定等同于代理已经完成注册。
- TCP 和 UDP 代理需要分别处理。
- 端口短时间重连时,监听状态可能出现抖动。
- 从监听列表中无法直接判断端口对应的是哪个 FRP 代理。
- 仅根据端口删除规则,容易误删人工创建的防火墙规则。
因此,端口状态应以 frps Dashboard API 返回的在线代理为准。系统监听端口可以用于辅助诊断,但不应作为唯一事实来源。
三、推荐架构
整体结构如下:
frpc
│ 通过 FRP 协议注册代理
▼
frps
├─ 服务端插件:触发即时同步
├─ Dashboard API:提供在线代理清单
▼
frp-firewall-sync 控制器
▼
1Panel v2 防火墙 API
▼
主机防火墙(nftables)控制器采用“两条路径”:
- 即时路径:收到 frps 的
NewProxy事件后,立即创建或确保规则存在。 - 巡检路径:定时读取 frps 在线代理,与 1Panel 中带有专用标记的规则进行对比,补齐遗漏并清理失效规则。
即时路径负责降低延迟,巡检路径负责处理插件通知丢失、frps 重启、控制器重启以及网络短暂异常。两者配合比单纯监听端口更可靠。
四、规则管理原则
1. 只管理带专用标记的规则
控制器只能创建和删除带有固定前缀的规则,例如:
frp-sync:v1:ipv4:tcp:443
frp-sync:v1:ipv6:udp:9000-9040其中:
frp-sync:v1是控制器标记。ipv4或ipv6表示地址族。tcp或udp表示协议。- 最后的端口可以是单个端口或连续范围。
人工创建的规则、1Panel 其他应用创建的规则以及不带该标记的 nftables 规则,都不应该被控制器删除。
在 1Panel 的 nftables 实现中,描述字段或 sourceID 可以保存这个标记。某些 1Panel 主题或版本可能不会在列表界面显示完整描述,但标记仍然应写入规则数据,并由控制器严格按标记识别。
2. TCP、UDP 和 IPv6 分开同步
TCP 与 UDP 端口不能混为一条规则;IPv4 与 IPv6 也应分别维护。这样可以避免“只开放 TCP”或“只开放 IPv4”造成的隐性故障。
当服务器确实启用了 IPv6,并且云安全组也允许 IPv6 时,可以开启双栈同步:
firewall:
families: [ipv4, ipv6]如果服务器没有可用的 IPv6,建议只配置 ipv4,避免产生没有实际意义的规则。
3. 连续端口合并为范围
例如在线代理端口为:
9000, 9001, 9002, 9003, 9004, 9005控制器可以生成:
9000-9005而不是创建六条单端口规则。端口之间存在间隔时不应跨越间隔合并,例如:
9000, 9001, 9003只能生成:
9000-9001
9003这样既减少规则数量,也不会因为范围合并而意外打开未使用端口。
4. 延迟删除
代理断开不一定表示配置已经删除,也可能只是 frpc 或网络临时重连。因此删除规则前应连续多次确认端口不在在线代理清单中。
一个实用的默认值是:
- 每 30 秒巡检一次。
- 连续 3 次缺失后删除。
- 实际关闭时间约为 90 秒。
如果端口变更非常频繁,可以适当延长确认次数;如果更重视快速回收,可以缩短巡检间隔,但不建议立即删除。
五、最简 YAML 配置
将运行参数、1Panel API Key 和 frps Dashboard 凭据放在一个受保护的 config.yml 中即可。以下是脱敏示例:
listen: 127.0.0.1:19001
hookPath: /frp-firewall-sync/change-this-path
cleanupEnabled: true
onePanel:
baseURL: http://127.0.0.1:22188/api/v2
apiKey: REPLACE_WITH_1PANEL_API_KEY
frps:
dashboardURL: http://127.0.0.1:7500
username: REPLACE_WITH_FRPS_DASHBOARD_USERNAME
password: REPLACE_WITH_FRPS_DASHBOARD_PASSWORD
firewall:
families: [ipv4, ipv6]其他参数使用程序默认值,例如日志级别、巡检间隔、删除确认次数、请求超时时间、nftables 表和 1Panel 基础链。
配置文件应限制权限,例如:
0640 root:10001不要把真实配置提交到公开仓库,也不要把 1Panel API 暴露到公网。更稳妥的方式是让控制器仅通过 127.0.0.1 访问 1Panel API,并使用专用 API Key。
旧版 JSON 配置仍可通过 -config /path/config.json 读取,便于回滚;新部署建议使用 YAML。
六、Compose 部署布局
建议把 Compose 项目放在 1Panel 的 Compose 目录中:
/opt/1panel/docker/compose/frp-firewall-sync/
├── docker-compose.yml
└── config.ymlCompose 使用相对挂载:
services:
frp-firewall-sync:
image: frp-firewall-sync:1.2.0
pull_policy: never
container_name: frp-firewall-sync
network_mode: host
restart: unless-stopped
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
volumes:
- ./config.yml:/app/config.yml:ro采用 host 网络是为了让控制器访问宿主机上的 1Panel API,并让健康检查和回调地址保持简单。容器本身不需要防火墙管理权限,也不需要挂载宿主机的 nftables socket;防火墙修改全部通过 1Panel API 完成。
七、frps 插件配置
frps 侧只需要把插件地址和路径指向控制器:
[[httpPlugins]]
name = "firewall-sync"
addr = "127.0.0.1:19001"
path = "/frp-firewall-sync/change-this-path"
ops = ["NewProxy"]插件路径必须与 config.yml 中的 hookPath 完全一致。回调监听地址建议只绑定到本机,不要暴露给公网。
插件主要承担“新代理出现时的即时触发”。端口关闭、批量重建和重启恢复由 Dashboard 巡检负责,这样即使回调偶尔丢失,也能最终恢复一致。
八、端口生命周期
一个端口的典型生命周期如下:
frpc 配置增加 remotePort
│
▼
frps 注册代理
│
├─ NewProxy 回调 → 立即创建 1Panel 规则
│
▼
巡检确认端口在线
│
▼
持续保留规则
│
frpc 删除配置或代理长期离线
│
▼
连续多次巡检缺失
│
▼
删除带 frp-sync:v1 标记的规则如果多个代理共享同一个协议和端口,控制器应采用引用计数或直接根据在线代理集合计算最终状态:只要仍有一个代理使用该端口,就不能关闭规则。
九、安全建议
“把 frps 端防火墙全部开放”不建议作为长期方案。它会让所有可能被扫描到的端口都进入暴露面,尤其是在 FRP 配置频繁变化、代理后端服务并非都需要公网访问的情况下。
更合理的安全边界是:
- 只放行 frps 当前确实使用的 TCP/UDP 端口。
- 只删除控制器自己创建的规则。
- 控制器 API 只监听本机。
- 1Panel API Key 只放在 root 可控的配置文件中。
- frps Dashboard 只监听本机或可信管理网段。
- 云安全组与主机防火墙同时收敛。
- 对高风险服务(数据库、管理面板、SSH 等)增加来源 IP 限制,不能仅依赖端口同步。
- 对配置文件和 Compose 项目目录做备份,保留旧镜像以便回滚。
动态放行解决的是“端口可达性”,并不替代身份认证、TLS、来源限制和应用层安全控制。
十、故障排查
端口已在 frps 监听,但 1Panel 没有规则
检查:
- 控制器容器是否为 healthy。
hookPath是否与 frps 插件路径一致。- 1Panel API 地址是否能从控制器容器访问。
- API Key 是否有效。
- 1Panel 防火墙是否处于启用状态。
- 云安全组是否允许对应协议和端口。
- 控制器日志是否出现 API 请求错误。
1Panel 后台看不到规则描述
不同 1Panel 版本或主题可能不会展示所有底层字段。可以直接查看规则详情或 nftables 规则,确认是否存在 frp-sync:v1 标记。控制器的清理逻辑只依赖标记字段,不依赖后台列表的显示文字。
出现端口关闭过快
增大 missingThreshold,或延长 reconcileInterval。重启控制器后,缺失计数会重新开始,这是有意设计,用于避免服务刚重启就误删规则。
十一、发布与维护
源码、Dockerfile、Compose 模板和配置示例放在 Git 中管理;生产环境只保留 Compose 文件和实际配置,不把服务器上的密钥文件纳入仓库。
升级时建议:
- 先执行单元测试和静态检查。
- 构建新的不可变版本镜像,例如
1.2.0。 - 备份当前 YAML 配置。
- 更新 Compose 镜像标签。
- 使用 1Panel 或 Docker Compose 重建服务。
- 检查容器健康状态和
/readyz。 - 观察一轮端口创建与删除,再清理旧镜像。
回滚时只需恢复旧镜像标签和旧配置备份,然后重新创建容器。由于规则带有版本化标记,升级过程中不应清理不属于当前控制器的规则。
总结
最适合长期运行的方式不是永久开放所有 frps 端口,也不是单独轮询操作系统监听列表,而是:
- 用 frps 插件触发即时同步;
- 用 frps Dashboard API 做权威巡检;
- 通过 1Panel API 管理防火墙;
- 只操作带
frp-sync:v1标记的规则; - 按 TCP/UDP、IPv4/IPv6 分开管理;
- 对连续端口做安全范围合并;
- 对失效端口延迟确认后自动关闭;
- 用单个 YAML 文件集中维护部署配置。
这样既保留了 1Panel 的管理体验,也能让频繁变化的 FRP 端口自动跟随实际代理状态。