Skip to main content
Glama

OPNsense MCP

一个以安全为核心、用于 OPNsense MVC API 的远程 Model Context Protocol 服务器。它通过有状态的 Streamable HTTP 向远程代理开放,上游使用 OPNsense API 原生的 HTTP Basic 认证,并且在无法判断某条 OPNsense 命令是否只读时,会按“默认关闭”(fail closed)的方式拒绝执行。

一个服务器实例代表一台 OPNsense 防火墙。防火墙 URL 和 API 凭据仅保存在服务器环境中;代理使用独立的 Bearer 令牌向 MCP 认证,无法将请求重定向到任何网络目标。管理多台防火墙时,请为每台设备单独部署一个隔离实例。

架构

Remote agent --HTTPS + MCP bearer token--> OPNsense MCP --HTTPS + API key/secret--> OPNsense

MCP 端点使用位于 /mcp 的 Streamable HTTP 传输。会话是有状态的,因此一次性变更计划始终绑定到代理的 MCP 会话上。会话数量有上限,空闲超时后过期,并且每个 HTTP 请求都会进行认证。

内置的 HTTP 监听器设计上应放在 TLS 反向代理、ingress controller、VPN 或私有 overlay 之后。不要将其明文 HTTP 端口直接暴露给不受信任的网络。

OPNsense API 模型

OPNsense 将 API 请求按以下方式路由:

/api/<module>/<controller>/<command>/<parameter...>

对自动化来说,需要了解的重要行为包括:

  • API 密钥使用 HTTP Bearer 认证:密钥作为用户名,密码作为密码。

  • 访问范围仍受该密钥拥有者在 OPNsense 中的 ACL 权限限制。

  • 请求和绝大多数响应都是 JSON 格式;下载和流式数据传输可能不是 JSON。

  • GETPOST 并不与“只读”和“可写”操作一一对应;部分读取使用 POST,部分变更使用 GET

  • 可更改的模型控制器经常暴露 getsearchaddsetdeltoggle 操作。

  • 数组模型记录使用 UUID。不带 UUID 的 get 通常返回一条以默认值填充的空白记录。

  • 一次成功的模型变更通常只是写入暂存配置;需要单独的 applyreconfigure 将其激活。

  • 模型写操作会返回形如 {"result":"saved"}{"result":"failed","validations":...} 的内容;仅凭 HTTP 200 不能证明语义上的成功。

  • OPNsense 的配置锁定、模型校验、版本上下文和 ACL 检查都在服务端进行,不能绕过。

官方参考资料:

安全模型

opnsense_request 只接受被归类为读取的命令。判断依据是命令本身,而不是 HTTP 方法。

变更操作使用两个工具:

  • opnsense_plan_change 在不访问 OPNsense 的情况下,报告确切的请求内容及其风险。

  • opnsense_execute_change 需要有匹配的一次性令牌,该令牌五分钟后过期。

风险等级区分暂存写入、激活、破坏性服务或固件操作,以及灾难性的重置/恢复操作。未知命令一律视为“关闭”(fail closed),不会执行。

写模式在代理之外进行控制:

  • disabled:仅允许读取。

  • plan:允许变更分析,但绝不生成执行令牌。

  • enabled:只有拿到匹配令牌时才允许执行。

请使用一个专用的 OPNsense 用户,仅授予目标工具所需的有效权限。对于只读部署,还应在 OPNsense 中授予 System: Deny config write(即 user-config-readonly)。

精选只读工具

在这类受保护的通用客户端基础上,还提供了一些固定的只读工具,用于常见的运维任务:

  • opnsense_get_firewall_logs:读取结构化包过滤日志。

  • opnsense_get_logs:按页读取核心日志和服务日志,包括 system、configd、gateways、VPN、DNS、DHCP、IDS、routing 以及 Web UI 日志。

  • opnsense_list_firewall_rules:读取自动化 API 可见的防火墙过滤规则。

  • opnsense_list_nat_rules:读取目的地址、源地址、一对一或 NPT 规则。

  • opnsense_get_route_table:读取实时内核路由表或已配置的静态路由。

这些工具直接调用固定的查询端点,不能执行任何可变操作,例如清空日志、强制刷新、修改规则或应用配置。结果仍然受该 API 用户的 OPNsense ACL 权限约束。

设置

npm install
npm run build

.env.example 作为参考来配置环境。环境变量文件不会被自动加载,Git 会忽略它们。使用 openssl rand -hex 32 生成一个独立的 MCP 令牌;切勿使用 OPNsense 的 API 凭据来替代。

优先使用公开可信的证书;否则请将 OPNSENSE_CA_FILE 设置为你自己的 CA 证书文件。OPNSENSE_TLS_VERIFY=false 仅用于隔离开发环境。

在本地回环上运行远程服务器,供本地 TLS 反向代理使用:

OPNSENSE_URL=https://firewall.example \
OPNSENSE_API_KEY=... \
OPNSENSE_API_SECRET=... \
MCP_AUTH_TOKEN=<random-token-at-least-32-characters> \
node dist/index.js

MCP 的 URL 为 http://127.0.0.1:3000/mcp。通过反向代理将该地址发布为 HTTPS,并传入令牌:

Authorization: Bearer <MCP_AUTH_TOKEN>

以下是一个支持 URL 和自定义请求头的远程客户端配置示例:

{
  "mcpServers": {
    "opnsense": {
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_AUTH_TOKEN}"
      }
    }
  }
}

不同客户端的配置格式各不相同。请将令牌保存在客户端的 secret 机制中,不要提交到配置文件。

Docker Compose

compose.yaml 将 3000 端口绑定到宿主机回环 localhost,这样反向代理就能安全地终止 TLS。

export OPNSENSE_URL=https://firewall.example
export OPNSENSE_API_KEY=...
export OPNSENSE_API_SECRET=...
export MCP_AUTH_TOKEN="$(openssl rand -hex 32)"
export MCP_ALLOWED_HOSTS=mcp.example.com
docker compose up -d --build

开发时如果需要直接连接 localhost:3000,请在 MCP_ALLOWED_HOSTS 中包含 localhost。未加密的健康检查端点 /health 不返回任何目标或凭据信息。

远程安全

  • 使用 HTTP 传输时必须设置 MCP_AUTH_TOKEN,其长度必须至少 32 字符。

  • 绑定到非回环地址时,必须设置 MCP_ALLOWED_HOSTS,可以防止 Host 头注入的 DNS 重绑定。

  • 带有浏览器 Origin 头的请求会被拒绝,除非该来源精确出现在 MCP_ALLOWED_ORIGINS 中。

  • MCP_MAX_SESSIONSMCP_SESSION_TTL_MSMCP_RATE_LIMIT_PER_MINUTE 是限制远程资源使用的上限。

  • 请保持 OPNSENSE_TLS_VERIFY=true。对于内部 CA,使用 OPNSENSE_CA_FILE,而不是关闭验证。

  • 在仅监控的部署中,保持 OPNSENSE_WRITE_MODE=disabled

  • 仅授予 OPNsense API 用户必要的 ACL 权限,并在适当的时候启用 user-config-readonly

  • 将 MCP 端点放在 HTTPS、防火墙策略以及(最好)VPN 或私有网络之后。

MCP_ALLOW_UNAUTHENTICATED=true 仅供隔离的本地开发使用,绝不能用于能被远程访问的监听地址。

Stdio 兼容性

本地客户端仍然可以将服务器作为子进程启动:

OPNSENSE_URL=https://firewall.example \
OPNSENSE_API_KEY=... \
OPNSENSE_API_SECRET=... \
MCP_TRANSPORT=stdio \
node dist/index.js

配置

  • OPNSENSE_URL:固定的防火墙基础 URL。

  • OPNSENSE_API_KEY:专用 OPNsense 用户的 API 密钥。

  • OPNSENSE_API_SECRET:与该密钥对应的 API Secret。

  • OPNSENSE_WRITE_MODEdisabledplanenabled

  • OPNSENSE_CA_FILE:可选的私有 CA PEM 文件。

  • OPNSENSE_TLS_VERIFY:默认值为 true

  • MCP_TRANSPORT:默认 http,也可是 stdio

  • MCP_HOST:监听地址,默认 127.0.0.1

  • MCP_PORT:监听端口,默认 3000

  • MCP_PATH:MCP 端点路径,默认 /mcp

  • MCP_AUTH_TOKEN:远程代理的 Bearer 令牌。

  • MCP_ALLOWED_HOSTS:允许出现在 HTTP Host 头中的主机名列表,逗号分隔。

  • MCP_ALLOWED_ORIGINS:允许访问的浏览器来源列表,逗号分隔;为空表示拒绝任何来源的浏览器请求。

  • MCP_MAX_SESSIONS:最大并发会话数,默认 100

  • MCP_SESSION_TTL_MS:空闲会话的存活时间,默认一小时。

  • MCP_RATE_LIMIT_PER_MINUTE:单个客户端的每分钟 HTTP 请求限制,默认 120

例如,读取系统状态的调用方式是:

{
  "module": "core",
  "controller": "system",
  "command": "status"
}

当前限制

  • OPNsense 并未发布完整的 OpenAPI 规范。生成的参考只识别出了路由和可能的方法,但通常缺少 body 的 schema。

  • 插件端点只有在对应插件已安装且通过 ACL 授权后才会存在。

  • 语义响应校验目前还没有实现到具体端点级别。

  • 词法风险分类器有意保持保守。精选工具最终应改为使用一份经过审计的端点清单,并给出明确的请求和响应 schema。

  • 计划类令牌减少了误执行和计划不匹配的情况,但 MCP Host 仍须将破坏性工具的审批交给人来确认。

  • 远程认证策略目前使用静态共享的 Bearer 令牌,而不是 OAuth 授权服务器。如果代理需要独立的身份,请使用隔离部署或实现认证的反向代理。

  • 会话状态仅保存在内存中,不支持副本复制。目前请运行单个副本实例,除非添加了外部会话存储和路由粘性。

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Remote MCP for A2A caller identity, scope policy, verdict receipts, and audit history.

  • Remote MCP for Android CLI agent build gate, structured receipts, audit logs, and reviewer-ready evi

  • Remote MCP for Copilot CLI switch gate MCP, structured receipts, audit logs, and reviewer-ready evid

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ethereal-Jay/opnsense-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server