LND 的前置审查官:RegisterRPCMiddleware 的 caveat 绑定、只读模式与安全线 图 1
LND 的前置审查官:RegisterRPCMiddleware 的 caveat 绑定、只读模式与安全线 · 图 1

LND 的 gRPC 权限体系以 macaroon 为核心:谁拿什么钥匙、调哪些接口,出厂就能配。但 macaroon 管的是”能不能进门”,管不了”进门之后干了什么、结果是否要过第二道审批”。想把审计、二次确认、限流这类业务逻辑加在 LND 前面,官方留的接口是 RegisterRPCMiddleware——把外部程序注册进 gRPC 拦截器链,让它观察、拦截甚至改写 RPC 流量。这个能力在 0.14.0 引入,0.15.1 又补上了请求侧的拦截与修改。本文基于 0.19.0-beta 源码讲清它的注册模型与安全边界。

双向流接口与注册二选一

RegisterRPCMiddleware 在 proto 里定义为一个双向流:客户端(中间件程序)持续上报处置结果,服务端持续下发被拦截的请求。注册时要交出一份注册信息,内容二选一,两个字段不能同时填。第一种是给名字加一个自定义 caveat 名:中间件起一个有信息量的名字(注册时会写进日志),然后声明自己只对”带着这个自定义 caveat 的 macaroon”的请求负责——只有含该 caveat 的请求和响应会被转发给中间件检查,其他流量与它无关。给 macaroon 附加自定义 caveat 正是这套体系里的挂钩方式:签发钥匙时把 caveat 写进去,调用者的每次请求就自动落到指定中间件的审查台上。第二种是只读模式:声明为只读后,所有请求与响应都会转发给它——无论调用方用的是什么钥匙——但中间件被明确禁止改动任何响应。一句话总结:想改结果,就只接带自己 caveat 的活;想看全部流量,就得放弃改写的权力。

LND 的前置审查官:RegisterRPCMiddleware 的 caveat 绑定、只读模式与安全线 图 2
LND 的前置审查官:RegisterRPCMiddleware 的 caveat 绑定、只读模式与安全线 · 图 2

一条任何中间件都越不过的安全线

源码注释里用斜体强调了一条安全规则:对于用”无负担 macaroon”——也就是没有附加任何自定义 caveat 的普通钥匙——发出的请求,任何中间件都不能修改其响应。这条线的意义在于防止钥匙之外的第三方偷换结果:一个持有普通管理员 macaroon 的调用者,得到的响应不会被某个悄悄注册的中间件动过手脚;中间件的改写权只存在于调用方主动用 caveat 授权的那个闭环里。审计日志可以旁观所有人,改写只有特约通道可以。

拦截消息里有什么

被选中拦截的请求,会以带唯一请求编号的截获消息下发给中间件:同一个 gRPC 调用乃至同一个流的所有来回共用一个编号,方便中间件把请求与响应配对;消息里还能直接拿到调用方 macaroon 的原始字节,供中间件自行解析权限细节。中间件的回复可以是放行,也可以是替换后的响应——响应改写从注册那天就有,请求改写则是 0.15.1 起的能力。需要注意这是一条长驻的双向流:中间件是一个常驻外部进程,与节点同生共死地处理着被挂钩的那部分流量,它挂掉或行为异常时,带对应 caveat 的调用是最先受到影响的对象;上线时先让少数试验 macaroon 带上 caveat 小范围试跑,验证中间件行为符合预期后再逐步放量,是这类关键路径组件的标准姿势。

什么时候值得上中间件

典型场景有三类。支付平台把”大额动账需要外部审批系统点头”做成 caveat 挂进签发流程,中间件不点头请求就不放行;安全团队用只读模式全量旁观 RPC 流水做审计,接受”不能改结果”的约束;多租户网关按 caveat 分流不同客户的请求做配额。反过来,如果只是给某个 macaroon 收紧接口清单,用权限系统与 checkmacaroonprivs 一类工具就够了,不需要动用中间件。这个接口没有 lncli 子命令,是给程序化集成准备的通道,不是给人手敲的开关。

风险提示:中间件位于 RPC 关键路径上,注册不当或中间件故障可能阻断正常调用;涉及资金操作的改写逻辑务必先在测试网验证;本文不构成任何投资建议。