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;
};