Haproxy
简介
代理协议即 proxy protocol, 是 haproxy
的作者 Willy Tarreau
于 2010 年开发和设计的一个 Internet
协议,通过为 TCP
添加一个很小的头信息,来方便的传递客户端信息(协议栈、源 IP
、目的 IP
、源端口、目的端口等),在网络情况复杂又需要获取客户 IP
时非常有用。如:
- 多层
NAT
网络 TCP
代理(四层)或多层TCP
代理https
反向代理http
(某些情况下由于keep-alive
导致不是每次请求都传递x-forword-for
)
代理协议分为 v1
和 v2
两个版本, v1
人类易读, v2
是二进制格式,方便程序处理。 proxy protocol
是比较新的协议,但目前已经有很多软件支持,如 haproxy
、 nginx
、 apache
、 squid
、 mysql
等等,要使用 proxy protocol
需要两个角色 sender
和 receiver
, sender
在与 receiver
之间建立连接后,会先发送一个带有客户信息的 tcp header
, 因为更改了 tcp
协议,需 receiver
也支持 proxy protocol
,否则不能识别 tcp
包头,导致无法成功建立连接。
https://www.haproxy.com/blog/haproxy/proxy-protocol/
协议解析
v1
- 每个字段中间为空格(
\x20
)
//PROXY AF L3_SADDR L3_DADDR L4_SADDR L4_DADDR\r\n PROXY TCP4 202.112.144.236 10.210.12.10 5678 80\r\n PROXY TCP6 2001:da8:205::100 2400:89c0:2110:1::21 6324 80\r\n PROXY UKNOWN\r\n
v2
//12字节的固定signature \x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A //4bits 协议版本号 \x2 // v2 //4bits cmd \x0 // LOCAL \x1 // PROXY //4bits 地址族 \x0 // AF_UNSPEC \x1 // AF_INET \x2 // AF_INET6 \x3 // AF_UNIX //4bits transport protocol \x0 // UNSPEC \x1 // STREAM \x2 // DGRAM //2字节地址长度字段(网络字节序),指接下来剩余的报头长度 L3 S_ADDR L3 D_ADDR L4 S_ADDR (如果有) L4 D_ADDR (如果有)
struct
struct HaproxyHeader { uint8_t sig[12]; uint8_t ver_cmd; uint8_t fam; uint16_t len; union { struct { /* for TCP/UDP over IPv4, len = 12 */ uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port; } ip4; struct { /* for TCP/UDP over IPv6, len = 36 */ uint8_t src_addr[16]; uint8_t dst_addr[16]; uint16_t src_port; uint16_t dst_port; } ip6; struct { /* for AF_UNIX sockets, len = 216 */ uint8_t src_addr[108]; uint8_t dst_addr[108]; } unx; } addr; };