ROS2 + Zenoh ACL 与配置指南
rmw_zenoh_cpp 的环境变量、配置加载、ACL 设置参考手册
1. 通信架构概览
ROS2 使用 rmw_zenoh_cpp 时有两种通信模式:
模式 A:Peer 模式(默认,无独立 Router)
Node1 ──── Node2
Node1 ──── Node3
- 每个节点内部自带嵌入式
zenohd - 节点之间以 P2P 网状连接
- 通过 scouting(组播)互相发现
- ACL 不生效——没有集中 Router,无法拦截
模式 B:独立 Router 模式(推荐生产用)
Node1 ─┐
Node2 ─┼── zenohd(独立进程)── Node4
Node3 ─┘
- 所有节点以 Client 模式连接到中心 Router
- 消息全部经过 Router 转发
- ACL 只在这种模式下生效
2. 环境变量大全
2.1 完整变量表
| 变量 | 用途 | 默认值 | 适用于 |
|---|---|---|---|
ZENOH_ROUTER_CONFIG_URI | Router 配置文件路径 | DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5 | Router |
ZENOH_SESSION_CONFIG_URI | Session 配置文件路径 | DEFAULT_RMW_ZENOH_SESSION_CONFIG.json5 | Session |
ZENOH_CONFIG_OVERRIDE | Inline 覆盖 key=value | — | 两者皆可 |
ZENOH_ROUTER_CHECK_ATTEMPTS | Router 连接重试次数 | 1 | Session |
RMW_IMPLEMENTATION | 指定 RMW 实现 | 系统默认 | Session |
ROS_DOMAIN_ID | ROS2 域 ID | 默认 | Session |
2.2 ZENOH_CONFIG_OVERRIDE 详解
这是 rmw_zenoh_cpp(Humble 0.1.x)中唯一的 inline 配置方式。语法:
key1="value1";key2/subkey=["val1","val2"];key3=true
- 用
;分隔多个字段 - JSON5 值用
=赋值 - 支持多层嵌套路径(用
/)
示例:
# Client 模式 + 指定连接端点
export ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/192.168.1.100:7447"]'
# Router 模式 + 修改监听端口
export ZENOH_CONFIG_OVERRIDE='listen/endpoints=["tcp/0.0.0.0:7448"]'
# 禁用组播
export ZENOH_CONFIG_OVERRIDE='scouting/multicast/enabled=false'
# 组合多个
export ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/10.0.0.1:7447"];scouting/multicast/enabled=false'
2.3 关于 RMW_ZENOH_SESSION_CONFIG
这个变量在 rmw_zenoh_cpp 官方源码中从未定义过,是一个不存在的变量。合法的方式只有 ZENOH_CONFIG_OVERRIDE。
| 变量 | 官方支持 | 说明 |
|---|---|---|
RMW_ZENOH_SESSION_CONFIG | ❌ 不存在 | 非官方变量,无任何作用 |
ZENOH_CONFIG_OVERRIDE | ✅ 支持 | 唯一 inline 方式 |
3. 使用方式
3.1 Router 配置
# 方式 1:配置文件
export ZENOH_ROUTER_CONFIG_URI=/path/to/router_config.json5
ros2 run rmw_zenoh_cpp rmw_zenohd
# 方式 2:Inline 覆盖
export ZENOH_CONFIG_OVERRIDE='listen/endpoints=["tcp/0.0.0.0:7448"]'
ros2 run rmw_zenoh_cpp rmw_zenohd
3.2 Session(ROS2 节点)配置
# 方式 1:配置文件
export ZENOH_SESSION_CONFIG_URI=/path/to/session_config.json5
ros2 run my_package my_node
# 方式 2:Inline 覆盖(常用)
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
export ROS_DOMAIN_ID=24
export ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/192.168.1.100:7447"]'
ros2 run my_package my_node
3.3 配置文件加载顺序(rmw_zenoh_cpp 源码逻辑)
- 读
ZENOH_ROUTER_CONFIG_URI(Router)或ZENOH_SESSION_CONFIG_URI(Session) - 如果设置了 → 通过
zenoh::Config::from_file()加载文件 - 如果未设置 → 使用默认文件
{package_share_dir}/config/DEFAULT_RMW_ZENOH_ROUTER_CONFIG.json5 - 然后应用
ZENOH_CONFIG_OVERRIDE的 key=value 覆盖
覆盖优先级:ZENOH_CONFIG_OVERRIDE > 配置文件 > 默认配置
3.4 daemon 注意事项
# 改变 RMW 或 Zenoh 配置后,必须重启 daemon
ros2 daemon stop 2>/dev/null
# 或绕过 daemon
ros2 topic list --no-daemon
ros2 topic echo /topic --no-daemon
4. 重要限制
rmw_zenoh_cpp(Humble 0.1.x)使用的 rmw_zenohd 是上游 zenoh 的 fork,版本较老:
| 特性 | rmw_zenohd (Humble) | zenohd (upstream 1.0.0+) |
|---|---|---|
| 配置格式 | JSON5 | JSON5 |
access_control | ⚠️ 可能不支持 | ✅ 原生支持 |
autoconnect_strategy | ✅ 有额外字段 | ❌ 无此字段 |
| 配置文件互用 | ⚠️ 不完全兼容 | 完全兼容 |
如果要用 ACL,推荐使用上游独立 zenohd。
5. ACL 配置
5.1 架构前提
ROS2 Node1 ──┐
├──→ 独立 zenohd(加载 ACL 配置)──→ ROS2 Node3
ROS2 Node2 ──┘
↑ ↑ ↑
rmw_zenoh_cpp zenohd 1.0.0+ rmw_zenoh_cpp
连接模式: client 负责路由 + 过滤 连接模式: client
只有中心 Router 模式下 ACL 才生效。
5.2 使用上游独立 zenohd
# 安装上游 zenohd(如果还未安装)
# https://github.com/eclipse-zenoh/zenoh/releases/tag/1.0.0
# 停止 rmw_zenoh_cpp 自带的 rmw_zenohd
kill $(pgrep rmw_zenohd)
# 启动上游 zenohd(加载 ACL 配置)
zenohd -c /path/to/acl_config.json5 &
# ROS2 节点以 client 模式连接
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
export ROS_DOMAIN_ID=24
export ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/127.0.0.1:7447"]'
ros2 run my_package my_node
5.3 ACL 配置模板
// /etc/zenoh/acl_router_config.json5
{
mode: "router",
listen: {
endpoints: ["tcp/0.0.0.0:7447"]
},
access_control: {
enabled: true,
default_permission: "deny",
subjects: [
{ id: "all" },
{ id: "debug_users", usernames: ["debug"] }
],
rules: [
{
id: "allow-navigation",
messages: ["put", "declare_subscriber", "declare_queryable",
"query", "reply", "delete"],
permission: "allow",
flows: ["egress", "ingress"],
key_exprs: ["**/navigo/**", "**/arc/**", "**/odom/**", "**/tf/**"]
},
{
id: "allow-diagnostics",
messages: ["put", "declare_subscriber"],
permission: "allow",
key_exprs: ["**/diagnostics**", "**/rosout"]
},
{
id: "allow-debug",
messages: ["put", "declare_subscriber"],
permission: "allow",
key_exprs: ["**/debug/**"]
}
],
policies: [
{ subjects: ["all"], rules: ["allow-navigation", "allow-diagnostics"] },
{ subjects: ["debug_users"], rules: ["allow-navigation", "allow-diagnostics", "allow-debug"] }
]
}
}
5.4 ACL 配置结构关系
subjects → 谁(身份)
rules → 能做什么(对什么 key、什么操作)
policies → 把谁和什么规则绑定
subjects: [{ id: "all" }, { id: "debug_users" }]
rules: [{ id: "allow-nav", ... }, { id: "deny-sensor", ... }]
policies: [{ subjects: ["all"], rules: ["allow-nav"] },
{ subjects: ["debug_users"], rules: ["allow-nav", "allow-debug"] }]
5.5 subject 过滤条件
| 条件 | 说明 |
|---|---|
interfaces | 网络接口名(如 wlan0, eth0) |
usernames | 用户名(需配合 usrpwd 认证) |
cert_common_names | TLS 证书 CN(需配合 TLS) |
link_protocols | 传输协议(如 tcp, tls, quic) |
空字段 = wildcard(匹配所有)。
5.6 消息类型
| 类型 | 对应操作 |
|---|---|
put | 发布数据 |
delete | 删除数据 |
declare_subscriber | 声明订阅 |
query | 查询请求 |
reply | 查询回复 |
declare_queryable | 声明可查询对象 |
liveliness_token | Liveliness token |
liveliness_query | Liveliness 查询 |
declare_liveliness_subscriber | Liveliness 订阅 |
5.7 安全方案矩阵
| 安全等级 | 配置 | 场景 |
|---|---|---|
| 全开放 | 默认配置 | 开发、内网测试 |
| Topic 白名单 | ACL allow 指定 topic 前缀 | 生产(控制可访问的数据) |
| 认证 + ACL | usrpwd 认证 + ACL 按用户分组 | 多机器人、调试权限分离 |
| 认证 + ACL + TLS | 全栈加密 | 公网/跨网络场景 |
6. FAQ
Q1: 如何判断当前是 Peer 模式还是 Router 模式?
ps aux | grep zenohd
# 有进程 → Router 模式
# 无进程 → Peer 模式(组播发现)
Q2: rmw_zenohd 配置文件是 JSON 还是 JSON5?
JSON5。文件名 *.json5,支持:
//和/* */注释- 不带引号的 key
- 尾随逗号
Q3: 如何持久化 Zenoh 配置?
# 写入 .bashrc
cat >> ~/.bashrc << 'EOF'
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
export ROS_DOMAIN_ID=24
export ZENOH_CONFIG_OVERRIDE='mode="client";connect/endpoints=["tcp/192.168.1.100:7447"]'
EOF
或使用配置文件:
export ZENOH_ROUTER_CONFIG_URI=/etc/zenoh/router_config.json5 # 写入 /etc/environment 或 systemd
Q4: ACL 中 default_permission 设置成 deny 后会不会连 rosout 都看不到?
会。需要显式 allow /rosout 和必要的 discovery topic。建议先用 allow 模式调试,逐步收紧为 deny。
Q5: 如果只改一个端口,需要写整个配置文件吗?
不需要,用 ZENOH_CONFIG_OVERRIDE:
export ZENOH_CONFIG_OVERRIDE='listen/endpoints=["tcp/0.0.0.0:7448"]'

189

被折叠的 条评论
为什么被折叠?



