FRP 动态端口与 1Panel 防火墙自动同步:一套可维护的实现方案

通过 frps 服务端插件、Dashboard API 和 1Panel 防火墙 API,实现 FRP 动态端口的自动放行、范围合并、IPv4/IPv6 双栈同步与失效端口自动关闭。

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 的结果并不够可靠:

  1. FRPS 的监听状态不一定等同于代理已经完成注册。
  2. TCP 和 UDP 代理需要分别处理。
  3. 端口短时间重连时,监听状态可能出现抖动。
  4. 从监听列表中无法直接判断端口对应的是哪个 FRP 代理。
  5. 仅根据端口删除规则,容易误删人工创建的防火墙规则。

因此,端口状态应以 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.yml

Compose 使用相对挂载:

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 没有规则

检查:

  1. 控制器容器是否为 healthy。
  2. hookPath 是否与 frps 插件路径一致。
  3. 1Panel API 地址是否能从控制器容器访问。
  4. API Key 是否有效。
  5. 1Panel 防火墙是否处于启用状态。
  6. 云安全组是否允许对应协议和端口。
  7. 控制器日志是否出现 API 请求错误。

1Panel 后台看不到规则描述

不同 1Panel 版本或主题可能不会展示所有底层字段。可以直接查看规则详情或 nftables 规则,确认是否存在 frp-sync:v1 标记。控制器的清理逻辑只依赖标记字段,不依赖后台列表的显示文字。

出现端口关闭过快

增大 missingThreshold,或延长 reconcileInterval。重启控制器后,缺失计数会重新开始,这是有意设计,用于避免服务刚重启就误删规则。

十一、发布与维护

源码、Dockerfile、Compose 模板和配置示例放在 Git 中管理;生产环境只保留 Compose 文件和实际配置,不把服务器上的密钥文件纳入仓库。

升级时建议:

  1. 先执行单元测试和静态检查。
  2. 构建新的不可变版本镜像,例如 1.2.0。
  3. 备份当前 YAML 配置。
  4. 更新 Compose 镜像标签。
  5. 使用 1Panel 或 Docker Compose 重建服务。
  6. 检查容器健康状态和 /readyz。
  7. 观察一轮端口创建与删除,再清理旧镜像。

回滚时只需恢复旧镜像标签和旧配置备份,然后重新创建容器。由于规则带有版本化标记,升级过程中不应清理不属于当前控制器的规则。

总结

最适合长期运行的方式不是永久开放所有 frps 端口,也不是单独轮询操作系统监听列表,而是:

  • 用 frps 插件触发即时同步;
  • 用 frps Dashboard API 做权威巡检;
  • 通过 1Panel API 管理防火墙;
  • 只操作带 frp-sync:v1 标记的规则;
  • 按 TCP/UDP、IPv4/IPv6 分开管理;
  • 对连续端口做安全范围合并;
  • 对失效端口延迟确认后自动关闭;
  • 用单个 YAML 文件集中维护部署配置。

这样既保留了 1Panel 的管理体验,也能让频繁变化的 FRP 端口自动跟随实际代理状态。

1Panel + 雷池 T1K 旁路接入:完整部署与运维教程 2026-09-15
Oracle OCI 上的 Proxmox VE 双栈网络重构:SDN 分段、独享公网 IP 与可维护运维 2026-09-15