使用代理协议 v2 和网络负载均衡器保留

保留客户端 IP 地址的方法:Proxy 协议 v2 与网络负载均衡器

关键要点

在负载均衡器或代理无法保留客户端原始 IP 地址的情况下,Proxy 协议 v2提供了一种有效的解决方案,通过在数据流中插入必要的客户端连接信息,确保后端服务能够掌握这些信息。无论是用于日志记录、监控,还是网络流量管理,Proxy协议都是一种提升安全性和可见性的好选择。


在青睐于使用负载均衡器或代理的场景中,若无法保留客户端的原始 IP 地址,系统可能会改写 IP 地址或者使用自身 IP地址进行路由。在这种情况下,广泛采用的做法包括将原始 IP 地址插入请求头(例如 X-Forwarded-For)或利用 来确保后端服务仍然可以访问到这些信息。 在第七层运行,利用 X-Forwarded-For HTTP 头将客户端 IP传递给目标。相比之下, 在第四层(TCP/UDP 层)运行,此时 Proxy 协议就展现出其优势。通过在代理头中编码所需的客户端详细信息,Proxy协议可以实现准确的日志记录、监控和网络流量管理,从而提升分布式环境下的安全性和可见性。

本文将探讨 如何与网络负载均衡器配合使用,学习其适当的使用场景,并部署一个 CloudFormation 模板,将网络负载均衡器置于 NGINX 或 HAProxy 服务器之前,使用 Proxy 协议 v2 保留客户端连接信息。

本文主要聚焦于 TCP 连接上的 Proxy 协议 v2,尽管同样支持 UDP。

Proxy 协议的工作原理

Proxy 协议在 TCP 数据流的开头添加一个头部。当客户端与服务器建立 TCP 连接时,首先进行三次握手,随后数据流开始传输。Proxy 协议 v2头部将客户端连接的详细信息进行编码,并在三次握手后立即插入到数据流中,如图 1 所示。在 TLS 连接的情况下,Proxy 协议 v2 头部会在 TLS握手之前出现。

![图 1: 带有 Proxy 协议 v2 头部插入的 TCP连接流](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

Proxy 协议 v2 与网络负载均衡器协作时,可能包含以下客户端连接信息:

字段名说明
源地址发起连接的客户端原始 IP 地址
目标地址接收连接的代理或负载均衡器的 IP 地址
源端口连接发起方客户端使用的端口号
目标端口连接指向的代理或负载均衡器一侧的端口号
协议连接所用的网络协议(例如 TCP 或 UDP)
版本使用的 Proxy 协议版本(例如 v2)
地址族源和目标 IP 地址的地址族(例如 IPv4 或 IPv6)
长度Proxy 协议头的长度
校验和确保头部完整性的校验值
类型-长度-值(TLV)自定义数据(例如,虚拟私有云 (VPC) 终端 ID)

这些详细信息编码在 Proxy 协议 v2头部中,由代理或负载均衡器使用,以准确传递客户端连接信息给后端服务器,从而使后端服务器能够保持对原始客户端连接的可见性。

Proxy 协议的常见使用场景

虽然网络负载均衡器默认保留客户端 IP 地址,但某些情况可能会影响这一能力。如需详细信息,请参考我们的 。在以下情况中,网络数据包中保留客户端 IP地址可能不切实际或不可能,因此您可以使用 Proxy 协议 v2,以便您的目标应用需要了解客户端连接的详细信息。

  1. 远程目标 - 路由到位于网络负载均衡器 VPC 外部的目标
  2. PrivateLink - 服务消费者与服务提供者之间的私有连接
  3. Hairpinning - 客户端和服务器位于同一主机上,通常出现在容器化环境中

在您启用代理协议之前,请确保您的应用能够解析 Proxy 协议 v2 头部,否则将会失败。

1. 远程目标

当目标位于网络负载均衡器 VPC 外部时,需要使用 IP 目标,这会自动停用客户端 IP 保留功能。这种情况与跨 VPC、混合云和多云架构相关。例如,网络负载均衡器可以部署用于管理位于本地的目标流量,如图 2 所示。

![图 2: 网络负载均衡器路由到远程目标](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

在网络安全和隐私方面, 是保护内部服务的广泛应用解决方案,同时允许多个消费者安全访问这些服务。它从 VPC 终端通过 AWS网络流向网络负载均衡器及其目标,形成单向流。然而,与任何安全措施一样,使用 PrivateLink 可能会带来一些权衡。当使用 PrivateLink时,客户端连接的详细信息会被隐藏,这使流量跟踪和管理变得复杂。通过 Proxy 协议 v2,不仅能够保留客户端 IP 地址,还能编码其他上下文信息,例如 VPC 终端 ID。此组合提供了 PrivateLink 流量来源的洞察,见图 3。

![图 3: PrivateLink连接](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

3. Hairpinning

在此背景下,hairpinning 指客户端和目标均源自同一主机的流量,通过网络负载均衡器进行传输,如图 4所示。这种情况最有可能出现在运行容器化负载的环境中。由于处理客户端 IP 保留的方式,在通过网络负载均衡器进行 hairpinning流量时,连接可能会失败。停用客户端 IP 保留可以使得 hairpin 路由得以实现,但这会隐藏客户端 IP。您可以在此场景下使用 Proxy 协议 v2来保留客户端连接的详细信息。

![图 4: 通过网络负载均衡器 hairpinning流量](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

Proxy 协议 v2 演示

接下来的部分,我们将执行以下步骤:

  1. 部署一个 模板。
  2. 连接到一个位于网络负载均衡器后的 (Amazon EC2) Web 服务器。
  3. 捕获并显示含有 Proxy 协议 v2 头部的网络数据包。
  4. 查看 EC2 Web 服务器的访问日志。

1. 部署 CloudFormation 模板

要开始实践演示,请访问 ,并使用 或

CloudFormation 模板来部署一个完整的网络负载均衡器和支持 Proxy 协议 v2 的目标环境。图 5 展示了 CloudFormation部署的结构。

在部署模板时,请将 ClientCIDR 参数的默认值(0.0.0.0/0)替换为您自己的 IP 地址。您可以通过访问网站 https://checkip.amazonaws.com 来查看您的公共 IP 地址。ClientCIDR参数用于安全组中,以限制对互联网可见的网络负载均衡器的访问。

请勿在生产环境中使用此 CloudFormation 模板。生产网络负载均衡器应部署在多个可用区中,并开启日志记录。

![图 5: 模板部署的基础设施](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

该模板设置了所有网络并部署了一个简单的 Web 应用程序,演示了如何在网络负载均衡器负载均衡流量时接收 Proxy 协议 v2 头部中的客户端详细信息。

模板执行的关键操作包括:

  • 创建 VPC,公共和私有 ,一个 ,一个 和相关 ,以便从私有子网访问互联网。
  • 定义一个允许从网络负载均衡器对端口 80 进行通信的 Amazon EC2 安全组。
  • 创建一个 (IAM) 角色和实例配置文件,以便 EC2 实例可以访问 以便进行远程访问。
  • 在私有子网上启动一个 EC2 实例,并设置一个 CloudFormation 初始化配置,安装并配置 NGINX 或 HAProxy 以及 PHP-FPM。该配置定义了一个支持 Proxy 协议 v2 的监听器,以便将请求传递给 PHP-FPM。
  • index.php 将显示通过网络负载均衡器传递的 Proxy 协议 v2 头部中的客户端源 IP 和端口。

2. 连接到位于网络负载均衡器后的 Amazon EC2 Web 服务器

部署模板的过程需要几分钟,之后需要额外时间让 EC2 实例进行健康检查以激活。一旦变为可用状态,请使用模板生成的 URL(在已部署的堆栈的 输出 选项卡中获取 URL)访问一个展示客户端连接详细信息的网页。

连接后,您应该会看到一个类似于图 6 所示的网页。

![图 6: 从 Proxy 协议 v2头部获取客户端详细信息的网页](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/blog- 删除)

3. 捕获并显示含有 Proxy 协议 v2 头部的网络数据包

现在,我们将使用协议分析器捕获并显示来自 EC2 实例命令行的 Proxy 协议 v2 头部内容。首先使用 连接到 CloudFormation模板部署的 EC2 实例。连接后,运行以下 tshark 命令以捕获和显示 Proxy 协议 v2 头部,如图 7 所示。

bash sudo tshark --disable-protocol http -VY proxy.v2.protocol==0x01

![图 7: 使用 tshark 捕获与显示含 Proxy 协议 v2头部的网络数据包](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/tshark- 删除)

在协议分析器运行时,打开您的工作站上的网页浏览器或任何兼容 HTTP 的客户端,指向模板提供的 URL。例如,您可以选择使用 cURL,如下代码片段所示,替换 URL 为模板提供的 URL。

bash curl http://replace-me.elb.region.amazonaws.com/index.php

在 EC2 实例上,协议分析器应捕获并显示包含 Proxy 协议 v2 头部的网络数据包内容。见图 8 示例。输出省略以保持简洁。

![图 8: 解码的 Proxy 协议 v2头部的截屏](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/ppv2-packet- 删除)

4. 查看 EC2 Web 服务器访问日志

最后,您将查看已配置为记录 Proxy 协议 v2 头部中发现的客户端 IP 地址的 Web 服务器访问日志。从 Web 服务器命令行运行如图 9 或图 10 中所示的命令。日志条目中不包含 IP 地址或包含您的网络负载均衡器 IP 地址的条目是健康检查,用于定期探测服务器,但不提供任何客户端连接详细信息。

一旦查看访问日志,从您的工作站连接到 URL 以生成新的日志条目。注意,访问日志中的源 IP 地址是来自 Proxy 协议 v2 头部所找到的地址。

图 9 和图 10 中显示的命令将在具有提升权限的情况下实时输出日志条目。确保根据您部署的 CloudFormation 模板使用正确的日志文件位置。

如果您部署了 NGINX,可以使用以下命令(输出见图 9):

bash sudo tail -f /var/log/nginx/access.log

![图 9: NGINX访问日志的截图](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/nginx- 删除)

如果您部署了 HAProxy,可以使用以下命令(输出见图 10):

bash sudo tail -f /var/log/haproxy/access.log

![图 10: HAProxy访问日志的截图](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4cac0a22bb029e8/2024/07/15/haproxy- 删除)

这次实践演示到此结束。尽管本文集中于 NGINX 和 HAProxy 作为网络负载均衡器的目标,但这些概念也适用于 Envoy、Traefik和其他类似的平台。大多数企业级代理和 Web 服务器支持 Proxy 协议 v2,但有些可能不支持。

清理工作

完成后删除 CloudFormation 堆栈,以避免不必要的费用。

结论

网络负载均衡器与 Proxy 协议 v2共同构成了一种协议无关的方法,以克服使用代理和负载均衡器时面临的保留客户端连接信息的挑战。通过在代理头中编码客户端详细信息,Proxy 协议 v2能够实现准确的日志记录、监控和网络流量管理,从而增强分布式环境中的安全性和可见性。

在本文中,我们深入探讨了 Proxy 协议 v2 的内部工作原理,探索了常见使用场景,并利用 CloudFormation模板进行了实践演示。掌握了这些知识和实践经验之后,您将更加自信地 。

关于作者

![Ken Kitts](https://d2908q01vomqb2.cloudfront.net/5b384ce32d8cdef02bc3a139d4

Leave a Reply

Required fields are marked *