Proxy Protocol简介
Haproxy提出的Proxy Protocol网络协议,其目的就是可以携带一些可以标记初始的TCP连接信息的字段,比如源端地址和端口、目的端地址和端口等,其本质是在三次握手结束后由代理在连接中插入了一个携带了原始连接四元组信息的数据包。通过为TCP添加一个很小的头信息,来方便的传递客户端信息,在服务端需要获取用户真实IP的场景非常有用。
Proxy Protocol中,定义了两个版本。在版本1中,头文件信息是文本形式的,在版本2中,提供了二进制形式,可以提高传输和解析效率。在V2版本中,除了address信息之外,header中还可以包含一些额外的扩展信息,这些信息被称为Type-Length-Value (TLV vectors)。
这里不多介绍Proxy Protocol的具体信息,可以参考https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
我们进行一次实施验证,直接编写客户端模拟实现该协议,服务端使用Nginx做代理,后端为简单的业务服务。我们期望验证,通过Proxy Protocol V2协议,可以把客户端信息传递到服务端,包括源端地址和端口、目的端地址和端口,通过tlv unique id传递一个特定的标识,Nginx将以上信息打印出来,并将unique id传递给后端服务。
客户端
为了触发携带Proxy Protocol的请求,我们自己写一个简单的C客户端(网上没有找到合适的触发方式),首先将相关结构体进行定义,直接拷贝Proxy Protocol官网上的内容即可,
地址和端口:
扩展字段的类型宏定义:
TLV结构:
Proxy Protocol头部信息:
客户端程序中,我们根据Proxy Protocol V2的定义,拼接处请求信息,即Proxy Protocol信息+HTTP请求,最后将请求使用socket发送出去即可。
服务端
我们使用Nginx做后台服务的代理,Nginx是支持Proxy Protocol的,但是对于tlv的支持也是最近版本才支持的,我们使用1.24版本。Nginx想配置如下,在访问日志中,增加相关变量的打印,然后在向后端转发请求时,将获取到unique id传递给后端服务;
验证结果
1、Nginx日志中,可以打印出客户端传递的信息,包括源端IP和端口,目的端IP和端口;
2、后台服务中,可以打印出Nginx转发过来的客户端指定的unique id信息;
在某些业务场景下,需要根据客户端信息进行权限验证等操作,Proxy Protocol可以非常好的支撑这种验证。