proxy protocol是HAProxy的作者Willy Tarreau于2010年開發(fā)和設(shè)計(jì)的一個(gè)Internet協(xié)議蟀俊,通過為tcp添加一個(gè)很小的頭信息沈善,來方便的傳遞客戶端信息(協(xié)議棧暴心、源IP雪位、目的IP惋增、源端口箩张、目的端口等)阎肝,在網(wǎng)絡(luò)情況復(fù)雜又需要獲取用戶真實(shí)IP時(shí)非常有用挤渔。其本質(zhì)是在三次握手結(jié)束后由代理在連接中插入了一個(gè)攜帶了原始連接四元組信息的數(shù)據(jù)包。
- 目前 proxy protocol有兩個(gè)版本风题,v1僅支持human-readable報(bào)頭格式(ASCIII碼)蚂蕴,v2需同時(shí)支持human-readable和二進(jìn)制格式,即需要兼容v1格式
- proxy protocol的接收端必須在接收到完整有效的 proxy protocol 頭部后才能開始處理連接數(shù)據(jù)俯邓。因此對(duì)于服務(wù)器的同一個(gè)監(jiān)聽端口骡楼,不存在兼容帶proxy protocol包的連接和不帶proxy protocol包的連接。如果服務(wù)器接收到的第一個(gè)數(shù)據(jù)包不符合proxy protocol的格式稽鞭,那么服務(wù)器會(huì)直接終止連接鸟整。
proxy_protocol流程
proxy protocol 格式
version 1 header
- 每個(gè)字段中間為空格(\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
version 2 header
- 12字節(jié)的固定signature
\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A
- 4bits 協(xié)議版本號(hào)
\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字節(jié)地址長度字段(網(wǎng)絡(luò)字節(jié)序),指接下來剩余的報(bào)頭長度
L3 S_ADDR
L3 D_ADDR
L4 S_ADDR (如果有)
L4 D_ADDR (如果有)
Tips
- 目前nginx的v2版本的讀取只支持 cmd 為 PROXY朦蕴,transport protocol 為 STREAM
- v2版本支持了很多新特性篮条,詳情可參考官方文檔(見reference)
nginx proxy protocol 配置
- 1.5.12 support accept for http
- 1.9.3 support TCP write
- 1.11.4 support accept for tcp
- 1.13.11 support v2 read
proxy protocol 插入配置
stream {
server {
listen 12345;
proxy_pass backend.example.com:8080;
proxy_protocol on;
}
}
proxy protocol 接收配置
http {
log_format elb_log '$proxy_protocol_addr';
server {
listen 8080 proxy_protocol;
root /usr/local/nginx/html;
index index.html index.htm;
server_name hello-world.com;
set_real_ip_from 192.168.10.0/24;
real_ip_header proxy_protocol;
}
location / {
try_files $uri $uri/ /index.html;
proxy_pass http://backend.example2.com:8088;
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
}
access_log /usr/local/nginx/stream.log elb_log;
}