Lighthouse 网络地址转换 NAT 配置

本文介绍了如何正确配置和调试 NAT 设置,以最大限度地提高 Lighthouse 客户端的效率。文章详细解释了 NAT 的工作原理,以及如何配置 IPv4 和 IPv6 的 NAT,并提供了调试 NAT 问题的步骤,以确保 Lighthouse 节点能够正确地在网络上运行。

本文档描述了如何正确配置和调试你的 NAT 设置,以最大化 Lighthouse 客户端的有效性。

这是一份实用的指南,但我添加了一些关于 Lighthouse 如何运作的基础理论和信息,以帮助用户理解本文档中解决的问题。 你可以随意跳到对你来说最相关的章节。

  1. 什么是 NAT?
  2. Lighthouse 和 NAT
  3. IPv4 NAT 配置
  4. IPv6 配置
  5. 调试 NAT 问题

什么是 NAT?

网络地址转换( NAT) 是一种通常在大多数家庭路由器上使用的方法。它允许你的 ISP 为你的整个家庭分配一个 IPv4 地址。你家中的所有计算机都使用这一个 IP 地址,通常被称为“全局 IPv4 地址”。

这样做的原因是公共 IPv4 地址数量有限(约为 30 亿),而世界上的设备数量远多于此,因此每个设备不能都有一个公共 IPv4 地址。

为了了解它在实践中是如何运作的,让我们考虑一个典型的家庭网络,其中包含标准路由器。当数据包从该网络中的一台计算机(假设其 IPv4 地址为 192.168.0.10)发送到互联网(例如 Google 服务器)时,内部计算机首先将数据包发送到其网关,即路由器。路由器是拥有你的 ISP 分配给你帐户的单个公共 IPv4 地址的设备。路由器将该消息转发到 Google 服务器,但它将数据包的源地址从 192.168.0.10 更改为路由器的公共 IPv4 地址。这样,当数据包到达 Google 的服务器时,它就知道将响应发送回路由器的 IPv4 地址。一旦路由器收到响应,它就知道将其转发到原始计算机 192.168.0.10。这从根本上讲就是 NAT 的工作原理,并且你典型的路由器会为其内部网络中的所有计算机执行此操作。

Lighthouse 和 NAT

Lighthouse 可以在实施 NAT 的路由器后方运行,但是当路由器配置正确以允许流量通过其 NAT 和防火墙时,它的性能会显着提高。以下各节将介绍执行此操作的最佳方法,而本节将重点介绍为什么 Lighthouse 运行更好以及为什么我们建议为 Lighthouse 配置 NAT。

发现

Lighthouse 使用一种名为 discv5 的协议来查找适合我们正在运行的网络的节点。默认情况下,它打开 UDP 端口 9000(如果启用了 IPv4 和 IPv6)。发现的工作原理是首先连接到一组预定义的节点,称为 bootnodes。我们从这些节点询问它们是否知道任何其他节点。以递归且有些复杂的方式,我们进行此搜索,直到我们收集并连接到我们所需的节点数量。

节点可以通过一个名为 ENR 的签名记录来宣传自己。这只是一个对象,有效地包含了节点的 IP 地址和我们可以连接到的端口。这些 ENR 是通过发现协议传输的内容。如果一个节点向我们发送一个 ENR(可以理解为 IP 地址和端口),并且我们发现我们无法连接到它们(即 IP 地址错误,或者它们的防火墙或 NAT 未配置为允许传入连接),那么我们会拒绝它们的 ENR,因此不会将其转发给其他向我们询问已知 ENR 的节点。因此,不可连接的 ENR 不应通过发现网络传播。

这意味着,如果你没有正确打开你的 UDP 9000 端口(即,在你的路由器上配置防火墙/nat 以转发此端口),那么你的节点将不会被通告给其他人,并且你将不会收到来自其他节点的传入连接(我将在下面的 libp2p 部分解释为什么这不好)。

与发现相关的另一个复杂之处是 Lighthouse 节点正确识别并随后通告其外部(可以理解为全局)IP 地址的能力。它不像仅仅检查我们的本地 IP 地址那么简单,因为我们计算机的数据包可能位于一个或多个更改数据包源 IP 地址的 NAT 之后。在传统的家庭 IPv4 网络中,我们的外部 IPv4 地址通常是路由器的 IPv4 地址,而不是我们的本地地址。对于 IPv6,我们通常有一个全局可路由的 IPv6 地址(我将以 IPv6 为重点的讨论留给另一篇文章)。

我们在 Lighthouse 中确定外部 IP 地址的方式是,客户端最初启动时,其 ENR 中未设置任何 IP 地址或端口。这意味着在启动时,我们不会在发现上通告我们的 IP/PORT。一旦运行,Lighthouse 会不断尝试确定其外部 IP 地址。这是通过连接到网络上的其他节点(通过发现,即 UDP 9000)并询问它们看到我们的数据包的源 IP 地址和端口是什么来实现的。如果有足够多的节点同意特定的 IP/PORT 对,那么我们将其设置在我们的 ENR 中,并查看我们是否收到传入连接。如果我们收到传入连接,我们就知道我们已经正确设置了我们的外部 IP 地址,并且我们路由器中的所有配置都按预期工作。如果我们没有看到传入连接,我们会将我们的 ENR 重置为没有设置任何 IP/PORT,并稍后重试。

此过程的一个复杂之处在于,路由器可以以不同的方式执行其 NAT 转换。即使你已正确转发了端口(这意味着入站流量被定向到你的 Lighthouse 节点),出站流量也可以为每个连接映射到我们路由器上的随机端口。这意味着我们的节点将各自看到一组唯一的 IP/PORT 作为我们数据包的来源。如果是这种情况,那么我们将不会看到足够多的节点同意来自你的 Lighthouse 节点的数据包的来源是什么(因为出站端口是随机的)。为了正确解决这个问题,有时需要在路由器中进行额外的配置。此配置称为 SNAT 规则。这指示路由器为从内部主机和端口(即我们的 Lighthouse 节点和 UDP 9000)内部发出的所有流量映射一个外部端口。我将在下面的配置和调试部分中讨论这一点。

Libp2p

Lighthouse 默认监听 TCP 9000 和 UDP 9001 端口(有关 QUIC 支持,请参阅我们关于 QUIC 支持的博客)。我们使用这些端口进行直接通信和将数据传输到以太坊共识网络上的其他节点。Lighthouse 有一个 target-peers 的概念。这是一个 CLI 配置参数,在撰写本文时,默认为 100。Lighthouse 使用发现来搜索节点,直到我们连接到此数量的节点。为了允许新节点加入网络并维护健康的节点集,Lighthouse 允许比此数量多 10% 的节点连接到我们。在默认情况下,这是 10 个额外的节点。

然后,Lighthouse 每 30 秒评估其节点集。如果我们拥有的节点多于我们的目标节点数,我们会修剪多余的节点。此过程不是随机的。我们会修剪对我们来说不太有用的节点(即可能没有帮助提供我们的证明,响应消息的速度较慢或者根本不如其他节点表现良好)。随着时间的推移,这使得 Lighthouse 能够维护一个非常有用的且分布式的(就我们需要进行认证和其他指标的节点而言)节点集。这从根本上提高了 Lighthouse 客户端的效率。

在我们 libp2p 端口上设置正确的端口转发将有助于新的连接并将我们的节点计数增加到超出目标值。对于 Lighthouse 来说,这种过剩是有益的,以便进行上述修剪过程。虽然 Lighthouse 在没有传入连接的情况下仍然可以运行,但它可能会通过此修剪过程以稍慢的速度循环节点,因此我们建议每个人都正确配置其网络以从他们的 Lighthouse 节点获得最佳性能。作为附带好处,它有助于整个网络的连接性。应该注意的是,位于 CGNAT 之后的那些用户(有关更多详细信息,请参见调试 NAT 问题)将无法在不与他们的 ISP 联系的情况下设置端口转发。

本文档的其余部分将讨论如何执行此操作以及如何调试可能的错误。

IPv4 NAT 配置

本节旨在描述如何设置传统的路由器以及在此过程中可能发生的一些陷阱。

端口转发

这是告诉路由器,特定端口上的传入流量应重定向到特定的内部主机和端口的过程。我们希望端口转发我们所有 Lighthouse 节点的端口。默认情况下,这些端口是:

  • UDP 9000
  • TCP 9000
  • UDP 9001

大多数路由器在其防火墙中都有一个名为 端口转发 的选项。如果它不存在,你可能需要在你的特定路由器上查找如何设置端口转发。通常,你需要指定一个外部端口并将其映射到内部主机和端口。我们建议将外部端口映射到相同的内部端口,以避免混淆并使调试更容易。Lighthouse 书籍提供了如何设置端口转发的指南。

例如,如果你的 Lighthouse 节点的 IPv4 地址为 192.168.0.15。你应该设置一个端口转发,将外部端口 UDP 和 TCP 9000 映射到端口 9000 上的内部主机 192.168.0.15。以及 UDP 端口 9001 也是如此。

SNAT

在某些路由器上,还需要 SNAT(源 NAT)才能使发现正确识别你的外部 IPv4 套接字,从而在网络上通告你的 Lighthouse 节点。同样,路由器通常有多种配置此项的方式,并且在你的路由器上搜索“如何配置 SNAT 规则”可能会帮助你了解如何执行此操作。从根本上讲,这涉及到设置一个出站规则,告诉路由器来自我们的 Lighthouse 节点的流量,该流量源自 UDP 端口 9000,应该映射到路由器上的输出端口 UDP 9000

如果你无法设置 SNAT 规则或者你的路由器不支持此功能,则可以告诉 Lighthouse 不要自动查找你的 IP 地址,而是可以通过 CLI 标志 --enr-address--enr-port--disable-enr-autoupdate 手动设置你的 ENR 字段。

IPv6 配置

使用 IPv6 时,你的内部计算机通常将具有全局 IPv6 地址。因此,你的路由器将不会对 IPv6 进行 NAT(这是 IPv6 的主要动机之一)。因此,无需设置任何端口转发规则。但是,出于安全原因,即使知道内部计算机的全局 IPv6 地址,你的路由器也不会允许任意的外部流量到达你的内部计算机。路由器通常具有默认规则来阻止此流量。因此,要为 Lighthouse 设置 IPv6 支持,你需要在你的防火墙中打开一个端口。这将只是一个 IPv6 防火墙规则,该规则允许特定端口上的外部流量到达我们的特定内部 Lighthouse 计算机。

对于 Lighthouse,我们需要允许 IPv6 端口 TCP 和 UDP 9000 以及 UDP 9001(默认情况下)上的流量到达运行 Lighthouse 的特定主机。路由器防火墙通常具有一系列设置,并且可能值得在你的特定路由器上搜索允许 IPv6 流量的方法。但是,我将在此处提供一个示例,希望它有用。

假设我们在一个内部网络中有一个支持 IPv6 的 Lighthouse 节点。默认情况下,如果未指定 CLI --listen-address(Lighthouse 版本 >= 7.0.0 并且计算机具有全局可路由的 IPv6 地址)或者指定了 --listen-address ::,则 Lighthouse 将启用 IPv6。在 linux 中,你可以运行:

$ ip -6 addr

它应该向你显示本地 IPv6 地址的列表。全局可路由的 IPv6 地址存在于 2000::/3 范围内,这意味着它们以 23 开头。你可能会在 IPv6 地址的开头看到 200x,以将其标识为全局地址。你还可以使用 curl ifconfig.me 或访问 https://whatismyipaddress.com 以查看你是否具有全局可路由的 IPv6 地址。在此示例中,假设我们有一个地址 2001:5555::10。然后,我们需要在我们的路由器中设置一个 IPv6 防火墙规则,该规则允许来自互联网(通常是 WAN 接口)的流量通过我们需要的端口,并且该流量的目的地地址也必须是 2001:555::10

设置防火墙规则后,Lighthouse 应接收 IPv6 流量并注册其 IPv6 端口已打开(我们将在下一节中讨论如何确定这一点)。

调试 NAT 问题

确定网络配置是否正常工作

Lighthouse 有两种主要方式可以报告它是否具有正确的网络配置。

HTTP API

如果你使用 --http 标志运行 Lighthouse,Lighthouse 会公开其 http api。一种方法是查询 Lighthouse 关于其 NAT 配置的信息。假设你在与 Lighthouse 节点相同的计算机上运行此命令,则可以运行:

curl http://localhost:5052/lighthouse/nat

结果应该是这样的形式:

{"data":{"discv5_ipv4":true,"discv5_ipv6":false,"libp2p_ipv4":true,"libp2p_ipv6":false}}

如果你安装了 jq,它会更漂亮一点:

curl http://localhost:5052/lighthouse/nat | jq

输出:

{
  "data": {
    "discv5_ipv4": true,
    "discv5_ipv6": false,
    "libp2p_ipv4": true,
    "libp2p_ipv6": false
  }
}

它会告诉你对于每个 IP 版本,Lighthouse 是否认为它是可连接的(即 NAT 配置是否正确)。 在此示例中,IPv4 的 NAT 配置正确,但 IPv6 的 NAT 配置不正确。如果 IPv6 不受支持或未在 Lighthouse 中运行,结果将相同。

指标

Lighthouse 有一套指标,允许用户监视他们的节点。有关如何设置它们并添加仪表板的更多说明,请参见Lighthouse 指标网络仪表板显示有关 Lighthouse 节点的 NAT 状态的信息。

nat-metrics

此示例显示了 IPv4 和 IPv6 的正确配置。

调试

如果 Lighthouse 报告你期望打开的 NAT 端口已关闭,则本节列出了多种调试问题根本原因的方法。

关于 CGNAT 的说明

ISP 将其客户置于运营商级 NAT(CGNAT)之后的情况越来越普遍。在这种情况下,ISP 也会在其端进行 NAT,并且你无法在自己的家庭路由器上设置正常工作的端口转发。如果你已设置端口转发,并且 Lighthouse 报告所有端口仍处于关闭状态,则你可能位于 CGNAT 之后。确定你是否位于 CGNAT 之后的一种方法是检查路由器中的 IP 地址,并将其与 curl ifconfig.me 或从 https://whatismyipaddress.com 获取的地址进行比较。如果地址不匹配,则你可能位于 CGNAT 之后。你需要联系你的 ISP 以选择退出 CGNAT 或让他们为你端口转发这些端口。

ENR 广播

为了让我们获得节点,我们需要广播我们的 IP 地址。如上所述,这需要发现来找到其外部 IP 地址。这需要 UDP 端口 9000(默认情况下)打开,有时还需要在路由器中设置 SNAT 规则。有几种方法可以检查我们是否正确发现了我们的外部 IP 地址。

首先,我们可以检查我们的 ENR,看看它是否列出了 IP 地址。

ENR 可以(默认情况下)在以下位置找到:

~/.lighthouse/<网络>/beacon/network/enr.dat

或者通过 HTTP API(假设安装了 jq,如果没有,只需从 localhost:5052/eth/v1/node/identity 端点读取该字段即可):

curl localhost:5052/eth/v1/node/identity | jq '.[] | .enr'

可以使用在线工具 enr-viewer 或使用 cli 工具 enr-cli(通过 cargo install enr-cli 获取它)查看 ENR。以下是通过安装的 enr-cli 工具查看 ENR 的示例:

enr-cli read $(cat ~/.lighthouse/mainnet/beacon/network/enr.dat)

这应该输出如下内容:

ENR Read:
Sequence No:11070
NodeId: a2af888a72b392136d03aa3f8adc9473b1f3601afc88cfd08cc4958f37ea3fd4
EnodeId: enode://a2af888a72b392136d03aa3f8adc9473b1f3601afc88cfd08cc4958f37ea3fd4@x.x.x.x:9000
Libp2p PeerId: 16Uiu2HAkzVy1Zvayo1pjK1e6CzDiLoTEuZPStexHDwutktZgHujf
IP:x.x.x.x
IP6:x:x:x:x:x::x
TCP Port:9000
TCP6 Port:9000
UDP Port:9000
UDP6 Port:9000
Eth2 Field:
    Fork digest: 6a95a1a9
    Next fork version: 04000000
    Next fork epoch: 18446744073709551615
    SSZ Bytes: 6a95a1a904000000ffffffffffffffff
Known multiaddrs:
/ip4/x.x.x.x/udp/9000
/ip4/x.x.x.x/tcp/9000
/ip6/x:x:x:x:x::x/udp/9090
/ip6/x:x:x:x:x::x/tcp/9090

如果此处存在 IP 地址(在此示例中存在),则表示 Lighthouse 已标识出一个外部 IP 地址和端口。我们应该检查它是否与我们的实际外部 IP 地址匹配,即通过 https://whatismyipaddress.com

也可以通过在 Lighthouse 日志中查找 Address updated 来证明这一点。 可以在以下位置找到日志(默认情况下):

~/.lighthouse/<网络>/beacon/logs/beacon.log

例如,我们可以通过以下方式搜索:

grep "Address updated" ~/.lighthouse/mainnet/beacon/logs/beacon.log

如果未指定任何 IP 地址(或未返回任何日志),则表示我们的 UDP 端口转发和/或 SNAT 规则存在问题。

我们可以通过专门查看发现日志来进一步调试此问题。我们需要访问扩展的发现日志记录,这需要重启 Lighthouse。要访问增强的发现日志,请使用前缀 RUST_LOG=discv5=debug 运行 Lighthouse 二进制文件。

例如:

RUST_LOG=discv5=debug lighthouse --network mainnet ...

这将启用 discv5 的调试日志。我们不建议长时间运行此程序,因为它会生成大量日志,并且会消耗更多资源来处理和存储它们。

在此运行后,我们可以检查发现日志。具体来说,我们想要搜索 PONG 消息,这些消息告诉我们我们的节点将我们的外部 IP 地址和端口视为哪个 IP 地址和端口。

我们可以通过以下方式检查这些日志(例如):

cat ~/.lighthouse/mainnet/beacon/logs/discv5.2025-02-10.log | grep "Pong"

这提供了以下形式的日志:

2025-02-10 11:01:24 DEBUG  Received RPC response PONG: Enr-seq: 424, Ip: 2403:6322:a6f2:3ddd::8770,  Port: 9000 PING: enr_seq: 276 Node: 0x64ce..8c9e, addr: [2a01:4f9:3071:1163::2]:9000
2025-02-10 11:01:39 DEBUG  Received RPC response PONG: Enr-seq: 2870, Ip: 124.251.22.13,  Port: 43754 PING: enr_seq: 276 Node: 0xea8d..7d61, addr: 184.82.210.230:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 8, Ip: 124.251.22.13,  Port: 51332 PING: enr_seq: 276 Node: 0xe762..af80, addr: 130.61.84.237:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 8978, Ip: 124.251.22.13,  Port: 16106 PING: enr_seq: 276 Node: 0xea63..199d, addr: 136.38.76.232:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 1736163570943, Ip: 124.251.22.13,  Port: 40341 PING: enr_seq: 276 Node: 0xea70..c0ff, addr: 185.209.176.61:27403
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 34, Ip: 124.251.22.13,  Port: 37385 PING: enr_seq: 276 Node: 0xea1b..31b7, addr: 40.117.231.135:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 1719430811736, Ip: 124.251.22.13,  Port: 55887 PING: enr_seq: 276 Node: 0xeaca..ecca, addr: 75.144.254.101:30303
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 938, Ip: 124.251.22.13,  Port: 5375 PING: enr_seq: 276 Node: 0xeb1c..da60, addr: 136.27.5.47:9105
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 1720963819678, Ip: 124.251.22.13,  Port: 21979 PING: enr_seq: 276 Node: 0xe810..3766, addr: 3.8.4.18:30303
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 1288, Ip: 124.251.22.13,  Port: 14960 PING: enr_seq: 276 Node: 0xeabc..11a9, addr: 74.201.216.109:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 4, Ip: 124.251.22.13,  Port: 17470 PING: enr_seq: 276 Node: 0xeb85..836b, addr: 44.222.172.44:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 930, Ip: 124.251.22.13,  Port: 31664 PING: enr_seq: 276 Node: 0xeae6..0ea9, addr: 46.4.159.90:9000
2025-02-10 11:01:40 DEBUG  Received RPC response PONG: Enr-seq: 1721289462507, Ip: 124.251.22.13,  Port: 24825 PING: enr_seq: 276 Node: 0xeb26..70e7, addr: 172.207.83.77:30303

请注意返回的 IP 地址和端口。如果端口在波动或变化(如上面的示例中所示),则表示你的路由器正在使用随机外部端口来发送流量。这意味着你需要添加 SNAT 规则,或者如配置部分中所述手动指定 ENR。

还要注意,只返回了一个 IPv6 地址。这并非基于你的计算机,而是基于你已联系的网络上支持 IPv6 的其他节点的数量。在撰写本文时,IPv4 节点的数量更多,因此这些是最常见的响应类型。

如果日志中的 IP 地址和端口都相同,则这表示可能存在防火墙问题。你应该检查本地节点的防火墙和路由器防火墙,以确保允许在特定端口上进行流量。你可能需要自己添加这些端口。

Libp2p 调试

如果发现端口已关闭,则 Libp2p NAT 端口可能会显示为已关闭。这意味着我们需要确保发现端口已打开,然后才能可靠地调试 Libp2p 端口。这是因为我们根据是否获得传入连接来确定端口是否已打开或关闭。由于如果我们不在发现上广播我们的节点,我们将不会获得传入连接,因此即使 Libp2p 端口在网络中配置正确,它们也可能显示为已关闭。

假设发现端口已打开,则可能需要一些时间,节点才能通过 Libp2p 连接到我们的节点,以显示打开状态。这在主网上可能需要几分钟。这里没有太多要调试的。如果 Lighthouse 将这些端口标记为已关闭,则我们不会在 Libp2p 端口上接收传入节点。确保你的 Lighthouse 节点正在侦听正确的接口(通常为“0.0.0.0”或“::”)。一种方法是通过:

netstat -ntlp

并检查 Lighthouse 是否列出了预期的端口。在路由器中的 TCP 和 UDP 上仔细检查是否已为 Libp2p 端口转发端口。通常,如果发现端口注册为打开,则等效的 IP 版本 Libp2p 端口也应注册为打开。如果不是,你可能需要检查是否有任何软件可以在关闭 Lighthouse 的情况下通过这些 TCP 端口访问你的内部节点。有一些关于如何检查端口是否打开的文章,我将不在此篇文章中详细介绍这些细节。

更多帮助

如果你已经尝试了此处的所有内容,但 Lighthouse 仍报告你的 NAT 端口已关闭,请在我们的 discord 上与我们联系。

我们会尽力提供帮助:)。

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

0 条评论

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