OPNsense MCP
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--> OPNsenseMCP 端点使用位于 /mcp 的 Streamable HTTP 传输。会话是有状态的,因此一次性变更计划始终绑定到代理的 MCP 会话上。会话数量有上限,空闲超时后过期,并且每个 HTTP 请求都会进行认证。
内置的 HTTP 监听器设计上应放在 TLS 反向代理、ingress controller、VPN 或私有 overlay 之后。不要将其明文 HTTP 端口直接暴露给不受信任的网络。
Related MCP server: ufw-mcp
OPNsense API 模型
OPNsense 将 API 请求按以下方式路由:
/api/<module>/<controller>/<command>/<parameter...>对自动化来说,需要了解的重要行为包括:
API 密钥使用 HTTP Bearer 认证:密钥作为用户名,密码作为密码。
访问范围仍受该密钥拥有者在 OPNsense 中的 ACL 权限限制。
请求和绝大多数响应都是 JSON 格式;下载和流式数据传输可能不是 JSON。
GET和POST并不与“只读”和“可写”操作一一对应;部分读取使用POST,部分变更使用GET。可更改的模型控制器经常暴露
get、search、add、set、del和toggle操作。数组模型记录使用 UUID。不带 UUID 的
get通常返回一条以默认值填充的空白记录。一次成功的模型变更通常只是写入暂存配置;需要单独的
apply或reconfigure将其激活。模型写操作会返回形如
{"result":"saved"}或{"result":"failed","validations":...}的内容;仅凭 HTTP 200 不能证明语义上的成功。OPNsense 的配置锁定、模型校验、版本上下文和 ACL 检查都在服务端进行,不能绕过。
官方参考资料:
https://docs.opnsense.org/development/frontend/controller.html
https://docs.opnsense.org/development/frontend/models_fieldtypes.html
安全模型
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.jsMCP 的 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_SESSIONS、MCP_SESSION_TTL_MS和MCP_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_MODE:disabled、plan或enabled。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 授权服务器。如果代理需要独立的身份,请使用隔离部署或实现认证的反向代理。
会话状态仅保存在内存中,不支持副本复制。目前请运行单个副本实例,除非添加了外部会话存储和路由粘性。
This server cannot be deployed
Maintenance
Related MCP Connectors
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Remote MCP for A2A caller identity, scope policy, verdict receipts, and audit history.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables cloud agents to securely operate local machine resources (files, commands, screenshots) via standard MCP protocol.MIT
- FlicenseNot gradedqualityCmaintenanceEnables least-privilege UFW firewall rule management over MCP, with safety checks to prevent silent no-op allows and audit trails tied to authenticated identity.-
- FlicenseNot gradedqualityAmaintenanceEnables MCP clients to safely access user-local filesystems, apply validated patches, inspect git state, and run persistent jobs on outbound-connected local runners through a stateless Cloudflare control plane.16-
- AlicenseNot gradedqualityBmaintenanceEnables transparent MCP proxying with a hash-chained effect ledger, classifying agent actions by reversibility, enforcing approval gates, and dry-run previews of sessions.MIT