本文介绍了LND(Lightning Network Daemon)0.3-alpha版本中引入的基于Macaroon的RPC身份验证机制。
作为 lnd
0.3-alpha 版本的一部分,我们解决了 issue 20,即 RPC 身份验证。在此实现之前,对 lnd
的所有 RPC 调用都未经身份验证。为了解决这个问题,我们使用了 macaroons,它类似于 cookie,但功能更强大。这个简短的概述从基本层面解释了它们的工作原理、我们如何使用它们进行 lnd
身份验证以及我们未来的计划。
你可以将 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 通过添加限制(称为 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
,它只能访问与发票相关的方法。
lnd
和 lncli
如何使用 macaroons。启动时,lnd
检查 admin.macaroon
、readonly.macaroon
和 invoice.macaroon
文件是否存在。如果它们不存在,lnd
会使用新的 macaroon ID 更新其数据库,生成三个文件 admin.macaroon
、readonly.macaroon
和 invoice.macaroon
,所有文件都具有相同的 ID。readonly.macaroon
文件有一个额外的 caveat,它限制调用者只能使用只读方法,而 invoice.macaroon
也有一个额外的 caveat,它限制调用者只能使用与发票相关的方法。这意味着一些重要的事情:
你可以删除 admin.macaroon
并只留下 readonly.macaroon
,这有时很有用(例如,如果你希望你的 lnd
实例以自动驾驶模式运行,并且不想意外地更改其状态)。
如果你删除包含 macaroons.db
文件的数据目录,这将使 admin.macaroon
、readonly.macaroon
和 invoice.macaroon
文件失效。无效的 macaroon 文件会给你带来诸如 cannot get macaroon: root key with id 0 doesn't exist
或 verification failed: signature mismatch after caveat verification
之类的错误。
你还可以使用 --no-macaroons
选项运行 lnd
,这将跳过 macaroon 文件的创建以及 RPC 服务器中的所有 macaroon 检查。这意味着你仍然可以使用客户端将 macaroon 传递到 RPC 服务器,但不会检查其有效性。请注意,不允许禁用侦听公共接口的服务器的身份验证。这意味着只有当 RPC 服务器位于专用网络中时才允许使用 --no-macaroons
选项。在 CIDR 表示法中,以下 IP 被认为是私有的,
169.254.0.0/16
和 fe80::/10
。224.0.0.0/4
和 ff00::/8
。10.0.0.0/8
、172.16.0.0/12
和 192.168.0.0/16
。fc00::/7
。由于 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
的三个启动命令 create
、unlock
和 changepassword
都有一个名为 --stateless_init
的标志,该标志指示守护程序不创建 *.macaroon
文件。create
和 changepassword
将在 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
$ lncli --macaroonpath=/safe/location/admin.macaroon getinfo
所有 macaroons 都派生自一个秘密根密钥(默认情况下来自 ID 为 "0"
的根密钥)。该根密钥在首次初始化 macaroon 存储时(创建钱包时)随机生成,因此默认情况下不是确定性的。
使用确定性(或预生成的)根密钥可能很有用,这就是为什么 InitWallet
RPC(或 lncli create
或 lncli createwatchonly
对应项)允许指定根密钥的原因。
使用预生成的根密钥对于以下情况可能很有用:
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
当使用 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 示例 了解编程使用详情。
macaroon bakery 在 macaroons 包中的 README 中有更详细的描述。
lnd
macaroon 实施的改进lnd
和 lncli
中现有的 macaroon 实施为未来在功能和安全性方面的改进奠定了基础。我们将添加以下功能:
改进的重放保护,用于保护 RPC 调用
Macaroon 数据库加密
根密钥轮换以及可能的 macaroon 失效/轮换
额外的限制,例如限制付款以使用(或不使用)特定路由、通道、节点等。
基于记帐的 macaroons,它可以使 lnd
实例几乎像应用程序的银行一样:例如,一个应用程序通过提供 API/服务来支付消耗其预算限制为所收到款项的 API
支持第三方 caveat,这允许用于授权和身份验证的外部插件
通过这项新功能,我们已经开始为 lnd
的 RPC 调用的灵活身份验证和授权奠定基础。我们期待扩展其功能,使其易于开发安全的应用程序。
- 原文链接: github.com/lightningnetw...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!