在DDoS防护的实际部署中,一个核心的技术矛盾是:当流量经过高防代理或负载均衡器清洗后,后端服务器收到的请求源IP都变成了代理节点的IP,从而丢失了访问者的真实IP。这直接导致服务器无法进行精准的访问控制、日志审计和业务分析。解决这一问题的关键技术,就是在代理层启用Proxy Protocol协议,将客户端的原始连接信息(包括真实IP地址和端口)以明文或二进制头的方式,“透传”给后端服务器。

一、 问题根源:为什么真实IP在代理后会丢失?

这源于网络通信的基本模型。当客户端直接连接你的服务器时,服务器的网络栈(如Nginx、Apache)可以直接从TCP/IP数据包的报头中读取客户端的源IP和端口。然而,一旦在客户端和服务器之间插入了一层DDoS高防代理、CDN或负载均衡器,网络连接就变成了两段:第一段是“客户端到代理”,第二段是“代理到后端服务器”。对于后端服务器而言,所有TCP连接都来自代理节点,它看到的源IP自然就是代理的IP。传统的HTTP协议头,如X-Forwarded-For(XFF),可以在应用层(HTTP)传递IP,但它仅适用于HTTP/HTTPS流量,并且依赖于代理服务器主动添加,存在被伪造的风险。

二、 Proxy Protocol是什么?它如何工作?

Proxy Protocol是由HAProxy的作者Willy Tarreau提出的一种互联网协议。它不是一个独立的新协议,而是一个轻量级的“协议头”,工作在传输层(TCP)之上。其核心思想是:在代理服务器与后端服务器建立TCP连接后,在发送任何应用数据(如HTTP请求)之前,先发送一行包含原始连接信息的头部。这样,后端服务器在解析应用数据前,就能先获取到客户端的真实信息。

Proxy Protocol主要有两个版本:

1. 版本1(文本版,v1):使用人类可读的ASCII文本格式。代理在建立连接后,首先发送一行如“PROXY TCP4 203.0.113.1 192.168.1.1 42322 443\r\n”的字符串。此行明确声明了客户端协议(TCP4/TCP6)、客户端真实IP、代理IP、客户端端口和代理端口。随后才开始正常的应用数据传输。

2. 版本2(二进制版,v2):使用紧凑的二进制格式,效率更高,支持更多信息(如IPv6、UNIX套接字、TLV扩展等)。它以固定的12字节魔数(0x0D 0x0A 0x0D 0x0A 0x00 0x0D 0x0A 0x51 0x55 0x49 0x54 0x0A)开头,后端程序可以据此快速识别。

三、 与X-Forwarded-For(XFF)的关键区别

很多人混淆Proxy Protocol和X-Forwarded-For,但它们有本质不同:

工作层级:Proxy Protocol工作在传输层(TCP),早于任何应用层协议(HTTP、SSL、SMTP等)。XFF是HTTP协议的一个头部字段,仅适用于HTTP上下文。

适用范围:Proxy Protocol可以透传任何基于TCP的协议的真实IP,包括HTTP、HTTPS、SSH、MySQL、SMTP等。XFF仅限于HTTP/HTTPS。

安全性与可信度:Proxy Header由第一个代理在建立TCP连接时立即添加,且通常配置在可信的内部网络或与可信代理之间,伪造难度大。XFF是应用层头部,可以被任何中间节点(包括恶意客户端)随意添加或篡改,需要谨慎验证。

信息完整性:Proxy Protocol传递的是建立TCP连接时的原始网络四元组信息。XFF通常只传递IP地址,不包含端口。

四、 在主流DDoS防护和高防代理中的配置实践

要使真实IP透传生效,必须在代理侧(DDoS高防/负载均衡)和后端服务器侧同时进行正确配置。

1. 代理侧(发送方)配置示例:

以常见的HAProxy和Nginx为例:

HAProxy:在对应的backend或defaults配置段中,添加"send-proxy"或"send-proxy-v2"指令。

backend web_servers
    mode tcp # 或 http
    server server1 10.0.0.2:80 check send-proxy-v2

Nginx(作为TCP/UDP代理):在stream模块的"proxy_pass"指令后,使用"proxy_protocol"参数。

stream {
    server {
        listen 80;
        proxy_pass backend_servers;
        proxy_protocol on; # 启用Proxy Protocol v1
    }
}

大多数主流云服务商的高防IP或负载均衡服务,都在控制台提供了“启用Proxy Protocol”或“真实IP透传”的选项,只需勾选即可。

2. 后端服务器(接收方)配置示例:

后端服务必须被配置为能够解析Proxy Protocol头,否则会将这个头误认为是应用数据而导致错误。

Nginx(作为后端Web服务器):在监听指令中增加"proxy_protocol"参数,并使用"$proxy_protocol_addr"变量获取真实IP。

http {
    server {
        listen 80 proxy_protocol; # 告诉Nginx,这个端口接收的连接带有Proxy Protocol头
        set_real_ip_from 10.0.0.0/8; # 信任的代理IP段
        real_ip_header proxy_protocol; # 从Proxy Protocol头中提取真实IP
        # 现在,$remote_addr变量存储的就是客户端真实IP
        location / {
            proxy_set_header X-Real-IP $proxy_protocol_addr;
        }
    }
}

Apache:需要安装并启用"mod_remoteip"模块,并进行相应配置。

# 在配置文件中
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader proxy_protocol # 指定头类型
RemoteIPInternalProxy 10.0.0.1 # 指定可信代理IP

其他软件:如MySQL、PostgreSQL、Redis等,通常需要特定的插件或版本支持来解析Proxy Protocol。

五、 安全考量与最佳实践

虽然Proxy Protocol解决了IP透传问题,但错误配置会引入严重风险。

1. 严格限制接收源:必须在后端服务器上通过防火墙(如iptables)或软件配置(如Nginx的"set_real_ip_from")严格限定允许发送Proxy Protocol头的代理IP地址范围。绝不允许来自公网任意地址的连接携带此头,否则攻击者可以直接伪造身份。

2. 优先使用版本2(v2):v2二进制格式更高效,且具有魔数前缀,更容易被准确识别,减少解析错误。v1文本格式可能存在歧义。

3. 加密与认证:Proxy Protocol头本身不加密。在非可信网络环境中,代理与后端服务器之间的通信应使用TLS/SSL加密(如数据库连接),或结合IPsec/VPN隧道,防止头信息被窃听或篡改。

4. 混合架构下的处理:在多层代理架构(如CDN -> 高防 -> 源站)中,通常只有最后一跳(高防到源站)使用Proxy Protocol。前面的跳转可以使用XFF,但源站最终应从Proxy Protocol头中取IP,并验证其与最后一跳代理IP的对应关系。

六、 总结:何时使用及核心价值

Proxy Protocol并非适用于所有场景。它的核心价值体现在以下环境:

1. 非HTTP(S)协议的真实IP透传:当你需要为SSH、游戏服务、邮件服务、数据库等提供DDoS防护并保留客户端IP时,它是几乎唯一的标准解决方案。

2. 对IP真实性要求极高的场景:如金融、政务系统的访问控制,需要比XFF更可信的IP来源。

3. 简化后端日志与分析:后端服务日志中的"$remote_addr"直接就是真实IP,无需额外解析HTTP头,日志系统更简洁可靠。

总而言之,在部署DDoS高防或任何TCP代理架构时,若业务依赖客户端真实IP,Proxy Protocol是实现可靠、通用、安全的真实IP透传的基石技术。正确理解和实施它,是保障业务安全与可观测性的关键一步。