简介

咱们曾经介绍了haproxy提出的proxy protocol协定,通过proxy protocol协定,服务器端能够取得客户端的实在IP地址和端口,从而能够进行一些十分有意义的操作。

为什么取得客户端的实在IP地址会十分有意义呢?

思考一个藏在proxy背地的数据库,如果有多个客户端通过proxy进行数据库的连贯,事实上因为都是通过代理进行连贯,所以数据库中的所有的操作都是proxy服务器的IP地址,这在对数据库的性能监控和优化是不利的,因为咱们不晓得实在异样的服务器IP地址。

这种状况下就须要用到proxy protocol协定,让数据库能够反映出实在客户端的IP地址,从而便于数据库的监控和问题定位。

事实上,数据库只是一个特定的例子,咱们在很多其余的状况下也可能须要晓得客户端实在IP的状况。

以当初最风行的http服务器和代理服务器nginx为例,咱们来看一下如何在nginx中配置proxy protocol。

proxy protocol在nginx中利用

咱们晓得nginx是一个web服务器和代理服务器,它个别工作在proxy server或者负载平衡软件(Haproxy,Amazon Elastic Load Balancer (ELB)的前面。

客户端首先申请proxy server或者LSB负载平衡软件,而后再到nginx进行实在的web拜访。

因为通过了多层软件,所以客户端的一些信息比方ip地址,端口号等可能就会被暗藏,这对于咱们问题剖析,数据统计都是不利的。因为对于nginx来说,咱们心愿可能取得实在的客户端IP地址,这样能力获取实在的申请环境。

这种状况下就须要用到PROXY protocol了。

如果后面所说的proxy或者LSB都实现了PROXY protocol协定的话,不论是HTTP, SSL, HTTP/2, SPDY, WebSocket 还是 TCP协定,nginx都能够拿到客户端的原始IP地址,从而依据原始IP地址进行一些非凡的操作,比方屏蔽歹意IP的拜访,依据IP不同展现不同的语言或者页面,或者更加简略的日志记录和统计等,都十分无效。

当然,如果想要反对PROXY protocol,对nginx的版本也是有要求的,具体版本需要如下:

  • 想要反对PROXY protocol v2,须要NGINX Plus R16或者NGINX Open Source 1.13.11。
  • 想要反对ROXY protocol for HTTP,须要NGINX Plus R3或者NGINX Open Source 1.5.12。
  • 想要反对TCP client‑side PROXY protocol,须要NGINX Plus R7或者 NGINX Open Source 1.9.3。
  • 想要反对PROXY protocol for TCP,须要NGINX Plus R11 或者 NGINX Open Source 1.11.4。

在nginx中能够通过上面的变量来取得对应的客户端信息,具体而言如下所示:

$proxy_protocol_addr$proxy_protocol_port 别离示意的是原始客户端的IP地址和端口号。

$remote_addr$remote_port示意的是load balancer的的IP地址和端口。

如果你应用了RealIP扩大模块,那么这个模块会重写$remote_addr$remote_port这两个值,将其替换成原始客户端的IP地址和端口号。

而后应用$realip_remote_addr$realip_remote_port来示意load balancer的的IP地址和端口。

在RealIP扩大模块中,$proxy_protocol_addr$proxy_protocol_port 示意的含意不变,还是原始客户端的IP地址和端口号。

在nginx中配置应用proxy protocol

下面咱们提到了nginx中proxy protocol的根本利用,上面来讲一下如何在nginx中进行具体的配置。

在nginx中启用proxy protocol

如果你的nginx曾经是反对proxy protocol的版本,那么启用proxy protocol非常简单,只须要在server中的listen中增加proxy_protocol即可,如下所示:

http {    #...    server {        listen 80   proxy_protocol;        listen 443  ssl proxy_protocol;        #...    }}   stream {    #...    server {        listen 112233 proxy_protocol;        #...    }}

可能大家比拟相熟的是http block,这示意的是nginx对http/https的反对。stream模块可能大家比拟生疏,这是nginx提供的对tcp/udp协定的反对。

通过下面的配置,nginx能够实现在tcp/udp协定和http/https协定同时反对proxy protocol。

应用Real‑IP modules

Real‑IP modules是nginx自带的一个模块,能够通过上面的命令来查看nginx是否有装置real-ip模块:

nginx -V 2>&1 | grep -- 'http_realip_module'nginx -V 2>&1 | grep -- 'stream_realip_module'

如果你以后应用的版本没有real ip,也不要急,这时候你可能须要从源代码进行编译。

在编译的过程中,咱们须要执行一个configure命令,在这个configure命令中能够指定要开启的性能,比方stream或者http_ssl_module:

$ ./configure--sbin-path=/usr/local/nginx/nginx--conf-path=/usr/local/nginx/nginx.conf--pid-path=/usr/local/nginx/nginx.pid--with-pcre=../pcre-8.44--with-zlib=../zlib-1.2.11--with-http_ssl_module--with-stream--with-mail

如果要开启real-ip性能,则能够增加:

--with-http_realip_module

如果nginx是运行在SLB或者proxy之后的,那么能够通过set_real_ip_from命令来指定代理或者负载平衡服务器的IP范畴,如下所示:

server {    #...    set_real_ip_from 192.168.1.0/24;   #...}

而后咱们须要将proxy或者SLB的IP地址替换成为实在客户端的地址,那么能够这样应用:

http {    server {        #...        real_ip_header proxy_protocol;      }}

申请转发

不论是http还是stream block,都可能遇到申请向后续的upstream进行转发的状况,对于upstream来说,他们心愿收到的是实在客户端IP地址,而不是proxy或者slb的地址,那么能够通过上面的设置来解决:

http {    proxy_set_header X-Real-IP       $proxy_protocol_addr;    proxy_set_header X-Forwarded-For $proxy_protocol_addr;}
stream {    server {        listen 12345;        proxy_pass example.com:12345;        proxy_protocol on;    }}

http和stream的设置形式是不同的。

日志记录

日志是一个十分重要的性能,对于定位问题,执行数据统计分析都十分有用,当然咱们须要的是实在的客户端IP地址。

咱们能够通过应用变量$proxy_protocol_addr在http和stream block中记录对应的日志,如下所示:

http {    #...    log_format combined '$proxy_protocol_addr - $remote_user [$time_local] '                        '"$request" $status $body_bytes_sent '                        '"$http_referer" "$http_user_agent"';}
stream {    #...    log_format basic '$proxy_protocol_addr - $remote_user [$time_local] '                      '$protocol $status $bytes_sent $bytes_received '                      '$session_time';}

总结

通过下面的设置,nginx曾经能够应用proxoy protocol了,这会让咱们的后续剖析工作变得更加轻松。

更多内容请参考 http://www.flydean.com/02-nginx-proxy-protocol/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不

欢送关注我的公众号:「程序那些事」,懂技术,更懂你!