我们已经详细介绍了haproxy提出的proxy protocol协议。借助这一协议,服务器端得以获取客户端的真实IP地址和端口,从而能执行许多具有深远意义的功能。
那么,为何获取客户端的真实IP地址会显得如此重要呢?
设想背后藏有proxy的数据库。当多个客户端通过proxy进行数据库连接时,由于所有连接均经由代理进行,数据库记录的IP地址实际上都是proxy服务器的IP,这对数据库性能的监控与优化带来不便,因为我们无法知晓真实异常的服务器IP地址。
这时,proxy protocol协议便派上了用场。它使得数据库能够反映出真实的客户端IP地址,从而极大地便利了数据库的监控与问题定位。
实际上,数据库只是众多应用场景中的一个例子。在许多其他情况下,我们同样可能需要知道客户端的真实IP。
以当前热门的http服务器和代理服务器nginx为例,让我们探讨如何在nginx中配置proxy protocol。
nginx作为一个web服务器和代理服务器,经常工作在proxy server或负载均衡软件(如Haproxy、Amazon Elastic Load Balancer (ELB))的后面。
当客户端首次向proxy server或负载均衡软件发出请求时,其后续会转至nginx进行真实的web访问。由于多层软件的介入,客户端的一些信息如IP地址和端口号可能会被隐藏,这对我们进行问题分析、数据统计极为不利。
为了获取真实的客户端环境信息,尤其是其IP地址,我们需要借助PROXY protocol。
若前面的proxy或负载均衡软件支持PROXY protocol协议,无论是以HTTP、SSL、HTTP/2、SPDY、WebSocket还是TCP协议进行通信,nginx都能获取到客户端的原始IP地址。基于这一原始IP地址,我们可以执行一系列操作,如恶意IP访问、根据IP展示不同语言或页面、以及更简单的日志记录与统计等。
要支持PROXY protocol,nginx的版本有一定要求。具体版本需求如下所述:
- 若要支持PROXY protocol v2,需使用NGINX Plus R16或NGINX Open Source 1.13.11。
- 对于支持ROXY protocol for HTTP的情况,需使用NGINX Plus R3或NGINX Open Source 1.5.12。
- 若需支持TCP client‑side PROXY protocol,则需NGINX Plus R7或NGINX Open Source 1.9.3。
- 若要支持PROXY protocol for TCP情况,应选用NGINX Plus R11或NGINX Open Source 1.11.4。
在nginx中,我们可以通过特定的变量来获取对应的客户端信息。
$proxy_protocol_addr和$proxy_protocol_port分别代表原始客户端的IP地址和端口号。
$remote_addr和$remote_port则表示负载均衡器的IP地址和端口。
若使用了RealIP扩展模块,该模块会重写$remote_addr和$remote_port的值,替换为原始客户端的IP地址和端口号。$realip_remote_addr和$realip_remote_port则用于表示负载均衡器的IP地址和端口。
以上我们概述了nginx中proxy protocol的基本应用。接下来,我们将详细介绍如何在nginx中进行具体配置。
若您的nginx版本支持proxy protocol,启用该功能相当简单。只需在server的listen指令中添加proxy_protocol即可。
可能您对http block较为熟悉,这是nginx对http/https支持的表现。而stream模块则是nginx对tcp/udp协议支持的体现,可能较为陌生。
通过上述配置,nginx得以实现在tcp/udp协议和http/https协议中同时支持proxy protocol。
Real‑IP模块是nginx自带的一个模块。您可以通过特定命令检查nginx是否安装了real-ip模块。