LND 0.3-alpha 版本中基于 Macaroon 的 RPC 身份验证

本文介绍了LND(Lightning Network Daemon)0.3-alpha版本中引入的基于Macaroon的RPC身份验证机制。

作为 lnd 0.3-alpha 版本的一部分,我们解决了 issue 20,即 RPC 身份验证。在此实现之前,对 lnd 的所有 RPC 调用都未经身份验证。为了解决这个问题,我们使用了 macaroons,它类似于 cookie,但功能更强大。这个简短的概述从基本层面解释了它们的工作原理、我们如何使用它们进行 lnd 身份验证以及我们未来的计划。

什么是 macaroons?

你可以将 macaroon 看作是一种 cookie。Cookies 是浏览器存储并在向特定网站发出请求时发送到该网站的小段数据。如果你已登录某个网站,则该 cookie 可以存储会话 ID,站点可以在其自己的数据库中查找该 ID 以检查你的身份并为你提供适当的内容。

macaroon 类似:它是一小段数据,客户端(如 lncli )可以将其发送到服务(如 lnd )以声明它被允许执行某个操作。服务查找 macaroon ID 并验证 macaroon 最初是否使用服务的根密钥签名。但是,与 cookie 不同,你可以委托 macaroon,或创建具有更有限功能的版本,然后将其发送给其他人使用。

就像 cookie 一样,macaroon 应该通过安全通道(例如 TLS 加密连接)发送,这就是为什么我们也在本版本中开始强制执行 RPC 请求的 TLS。在 Facebook 和 Google 等网站上强制执行 SSL 之前,监听无线网络上的 HTTP 会话是劫持会话并以该用户身份登录的一种方式,从而获得对用户帐户的访问权限。Macaroons 类似,因为拦截传输中的 macaroon 允许拦截器使用该 macaroon 来获得合法用户的所有权限。

Macaroon 委托

macaroon 通过添加限制(称为 caveat)和类似于签名的身份验证代码(技术上是 HMAC)来委托。这样做的技术方法超出了本文档的范围,但 macaroons 包中的 README 或上面链接的 macaroon 论文更详细地描述了它。用户必须记住以下几点:

  • 共享 macaroon 允许任何拥有该 macaroon 的人使用它来访问服务(在我们的例子中是 lnd ),以执行 macaroon 允许的任何操作。有一种特定类型的限制,称为“第三方 caveat”,它需要外部服务来验证请求;但是,lnd 当前未实现这些 caveat。

  • 如果你向 macaroon 添加 caveat 并共享生成的 macaroon,则收到它的人无法删除该 caveat。

这在 lnd 中以一种有趣的方式使用。默认情况下,当 lnd 启动时,它会创建三个包含 macaroons 的文件:一个名为 admin.macaroon 的文件,其中包含没有 caveat 的 macaroon;一个名为 readonly.macaroon 的文件,它是相同的 macaroon,但带有一个额外的 caveat,它只允许不更改 lnd 状态的方法;以及 invoice.macaroon,它只能访问与发票相关的方法。

lndlncli 如何使用 macaroons。

启动时,lnd 检查 admin.macaroonreadonly.macarooninvoice.macaroon 文件是否存在。如果它们不存在,lnd 会使用新的 macaroon ID 更新其数据库,生成三个文件 admin.macaroonreadonly.macarooninvoice.macaroon,所有文件都具有相同的 ID。readonly.macaroon 文件有一个额外的 caveat,它限制调用者只能使用只读方法,而 invoice.macaroon 也有一个额外的 caveat,它限制调用者只能使用与发票相关的方法。这意味着一些重要的事情:

  • 你可以删除 admin.macaroon 并只留下 readonly.macaroon,这有时很有用(例如,如果你希望你的 lnd 实例以自动驾驶模式运行,并且不想意外地更改其状态)。

  • 如果你删除包含 macaroons.db 文件的数据目录,这将使 admin.macaroonreadonly.macarooninvoice.macaroon 文件失效。无效的 macaroon 文件会给你带来诸如 cannot get macaroon: root key with id 0 doesn't existverification failed: signature mismatch after caveat verification 之类的错误。

你还可以使用 --no-macaroons 选项运行 lnd,这将跳过 macaroon 文件的创建以及 RPC 服务器中的所有 macaroon 检查。这意味着你仍然可以使用客户端将 macaroon 传递到 RPC 服务器,但不会检查其有效性。请注意,不允许禁用侦听公共接口的服务器的身份验证。这意味着只有当 RPC 服务器位于专用网络中时才允许使用 --no-macaroons 选项。在 CIDR 表示法中,以下 IP 被认为是私有的,

由于 lnd 默认情况下需要 macaroons 才能调用 RPC 方法,因此 lncli 现在读取 macaroon 并在 RPC 调用中提供它。除非路径被 --macaroonpath 选项更改,否则 lncli 尝试从 lnd 当前活动网络的网络目录中读取 macaroon(例如,对于 simnet,默认为 lnddir/data/chain/bitcoin/simnet/admin.macaroon ),如果该文件不存在,则会出错,除非提供了 --no-macaroons 选项。在使用 --no-macaroons 运行 lnd 时请记住这一点,因为除非以相同的方式调用 lncli lnd 在没有此选项的先抢跑中生成了 macaroon,否则 lncli 将会出错。

lncli 还添加了一个 caveat,使其默认情况下仅在 60 秒内有效,以帮助防止重放,以防 macaroon 在传输过程中以某种方式被拦截。这在 TLS 的情况下不太可能发生,但例如在使用允许检查加密流量的 PKI 和网络设置时可能会发生,并且攻击者在拦截后可以访问流量日志。可以使用 --macaroontimeout 选项更改默认的 60 秒超时;对于在时钟相差 60 秒以上的系统之间进行 RPC 调用,可以增加此值。

无状态初始化

如上所述,默认情况下,lnd 会在其目录中创建多个 macaroon 文件。这些文件是未加密的,并且在 admin.macaroon 的情况下,提供对守护程序的完全访问权限。如果 lnd 守护程序在并非完全受信任的环境中运行,这可能会被认为是一个相当大的安全风险。

macaroon 文件是唯一包含高度敏感信息且未加密的文件(与钱包文件和包含根密钥 的 macaroon 数据库文件不同,即使未使用密码,这些文件也始终加密)。

为避免泄漏 macaroon 信息,lnd 支持所谓的 无状态初始化 模式:

  • lncli 的三个启动命令 createunlockchangepassword 都有一个名为 --stateless_init 的标志,该标志指示守护程序创建 *.macaroon 文件。
  • 实际上创建/更新 macaroon 数据库的两个操作 createchangepassword 将在 RPC 调用中返回 admin macaroon。假设守护程序和 lncli 不在同一台机器上使用,这将不会在运行 lnd 的机器上留下任何未加密的信息。
    • 更准确地说:默认情况下,当使用 changepassword 命令时,macaroon DB 中的 macaroon 根密钥只是使用新密码重新加密。但密钥保持不变,因此在 changepassword 命令之前颁发的 macaroons 仍然有效。如果用户想要使所有先前创建的 macaroons 无效,则应使用 changepassword 命令的 --new_mac_root_key 标志!
  • 如果使用参数 --save_to=some_file.macaroon ,则 lncli 的用户将看到返回的 admin macaroon 打印到屏幕或保存到文件。
  • 重要提示: 默认情况下,如果未使用 --stateless_init 标志,lnd 将在 unlock 阶段创建 macaroon 文件。因此,为避免泄漏 macaroon 信息,请对钱包解锁服务的全部三个启动命令使用无状态初始化标志!

例子:

  • 以无状态方式创建一个新钱包(首次运行):
    $  lncli create --stateless_init --save_to=/safe/location/admin.macaroon
  • 解锁先前以无状态方式初始化的钱包:
    $  lncli unlock --stateless_init
  • 使用创建的 macaroon:
    $  lncli --macaroonpath=/safe/location/admin.macaroon getinfo

使用确定性/预生成的 macaroons

所有 macaroons 都派生自一个秘密根密钥(默认情况下来自 ID 为 "0" 的根密钥)。该根密钥在首次初始化 macaroon 存储时(创建钱包时)随机生成,因此默认情况下不是确定性的。

使用确定性(或预生成的)根密钥可能很有用,这就是为什么 InitWallet RPC(或 lncli createlncli createwatchonly 对应项)允许指定根密钥的原因。

使用预生成的根密钥对于以下情况可能很有用:

  • 测试:如果节点始终使用相同的根密钥初始化每次测试运行,则在一个测试运行中生成的 macaroons 可以在另一个运行中重复使用,而无需重新派生。
  • 远程签名设置:当使用其中有两个相关的 lnd 节点(例如,仅监视和签名者对)的远程签名设置时,在甚至启动任何节点 之前 生成有效的 macaroon 会很有用。

示例:

以下示例显示如何在甚至启动节点之前生成有效的 macaroon:

## 随机生成一个 32 字节长的秘密根密钥,并将其编码为十六进制。
ROOT_KEY=$(cat /dev/urandom | head -c32 | xxd -p -c32)

## 从该根密钥派生一个只读 macaroon。
## 注意:当使用 --root_key 标志时,`lncli bakemacaroon` 命令是完全脱机的,不需要连接到任何 lnd 节点。
lncli bakemacaroon --root_key $ROOT_KEY --save_to /tmp/info.macaroon info:read

## 现在创建 lnd 节点,使用相同的根密钥。
lncli create --mac_root_key $ROOT_KEY

## 使用预生成的 macaroon 进行调用。
lncli --macaroonpath /tmp/info.macaroon getinfo

将 Macaroons 与 GRPC 客户端一起使用

当使用 GRPC 接口与 lnd 交互时,macaroons 在线路上编码为十六进制字符串,可以通过将十六进制编码的 macaroon 指定为 GRPC 元数据传递给 lnd

GET https://localhost:8080/v1/getinfo
Grpc-Metadata-macaroon: <macaroon>

其中 <macaroon> 是 macaroon 文件本身中的十六进制编码的二进制数据。

使用 curl 的一个非常简单的示例可能如下所示:

$  curl --insecure --header "Grpc-Metadata-macaroon: $(xxd -ps -u -c 1000  $HOME/.lnd/data/chain/bitcoin/simnet/admin.macaroon)" https://localhost:8080/v1/getinfo

请查看 Java GRPC 示例 了解编程使用详情。

使用自定义权限创建 macaroons

macaroon bakery 在 macaroons 包中的 README 中有更详细的描述。

未来对 lnd macaroon 实施的改进

lndlncli 中现有的 macaroon 实施为未来在功能和安全性方面的改进奠定了基础。我们将添加以下功能:

  • 改进的重放保护,用于保护 RPC 调用

  • Macaroon 数据库加密

  • 根密钥轮换以及可能的 macaroon 失效/轮换

  • 额外的限制,例如限制付款以使用(或不使用)特定路由、通道、节点等。

  • 基于记帐的 macaroons,它可以使 lnd 实例几乎像应用程序的银行一样:例如,一个应用程序通过提供 API/服务来支付消耗其预算限制为所收到款项的 API

  • 支持第三方 caveat,这允许用于授权和身份验证的外部插件

通过这项新功能,我们已经开始为 lnd 的 RPC 调用的灵活身份验证和授权奠定基础。我们期待扩展其功能,使其易于开发安全的应用程序。

  • 原文链接: github.com/lightningnetw...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
lightningnetwork
lightningnetwork
江湖只有他的大名,没有他的介绍。