公司网站架构为:

前面2台HA负载均衡,后面3台Nginx负载均衡反向代理,然后后面有N台WEB服务器

由于要统计IP,需要在WEB服务器日志里体现客户端真实IP

那么问题来了,通过HA代理的HTTP协议是没有问题的,后端的WEB服务器可以正常获取到客户端真实IP

但是通过HA代理的HTTPS协议就不行了,为什么呢,因为我们HA设置的是代理模式就是TCP模式,TCP代理SSL协议跳转到后面的NG上

由于4层协议是不能转发heder的,那后端https自然获取不到客户端真实IP了,怎么办呢,网上找了些资料,做了些测试有2种方案

第一:HA的https不再使用HA代理,直接使用nginx来做负载均衡,这样问题就解决了,方法和配置参照我上篇随笔。

第二:是最近2天测试出来的新方案,就是用proxy protocol 协议,也就是代理协议。

什么是代理协议?解释如下,不是我自己写的,网上COPY的

1.代理协议即 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包头,导致无法成功建立连接。

以上就是解释,haproxy和Nginx都支持这个协议,nginx需要1.5版本以上,有了这个协议就好办了,haproxy依然使用tcp代理ssl(https),只需要加一点点配置就行,示例配置如下:

global
maxconn
chroot /usr/share/haproxy
uid
gid
daemon
nbproc
tune.ssl.default-dh-param
stats bind-process
stats socket /var/run/haproxy.stats level admin
defaults
log global
log 127.0.0.1 local0
mode http
option dontlognull
retries
option redispatch
option httpclose
balance roundrobin
#balance leastconn
#option forwardfor
#option forwardfor if-none maxconn
timeout http-request 5s
timeout connect
timeout client
timeout server
listen monitor_stat :
stats uri /ihaproxy-stats
stats realm Haproxy\ Statistics
stats auth ha_house:ZW5dmKRTObmOuA1nnS5U
stats hide-version
bind-process frontend yidonghttps-in
mode tcp
bind *:
default_backend yidongclient_server_https frontend http-in
bind *:
log global
option httplog
option forwardfor
backend yidongclient_server_http
server yidonghttp_41 172.17.2.110: weight check inter rise fall
backend yidongclient_server_https
mode tcp
server yidonghttps_37 172.17.2.110: send-proxy

上面配置其实没添加什么,只是在最后的backend  yidongclient_server_https的server里的最后面添加上了 send-proxy 参数,这样HA就把proxy protocol协议发送到后端Nginx上了。

配置完ha后,后面的nginx也需要配置,由于80端口自然能获取客户端IP地址,我们主要来配置443端口

配置文件如下

upstream ihouse443{
server 172.17.3.108: max_fails= fail_timeout= weight=; } server {
listen proxy_protocol;
server_name ihouse.ifeng.com;
access_log /data/logs/nginx/ihouse_access.log access;
error_log /data/logs/nginx/ihouse_error.log ;
ssl on;
ssl_certificate /data/ifengsite/htdocs/ihouse.ifeng.com.crt;
ssl_certificate_key /data/ifengsite/htdocs/ihouse.ifeng.com.key; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:HIGH:!aNULL:!MD5:!ADH:!DH;
ssl_protocols TLSv1 TLSv1. TLSv1.; location / {
proxy_pass https://ihouse443;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-IP $proxy_protocol_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_max_temp_file_size ;
proxy_connect_timeout ;
proxy_send_timeout ;
proxy_read_timeout ;
proxy_buffer_size 4k;
proxy_buffers 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
}

主要添加以上红色粗体内容,server段里添加 proxy_protocol 使之支持代理协议

location 里添加红色粗体内容,定义新的headr信息,并且发送到后端WEB上

最后需要定义下日志文件,重新定义下,这个日志文件指的是负载均衡的nginx的日志文件,至于后端的WEB则不需要

#user  www www;
worker_processes ; #error_log /data/logs/nginx/error.log;
#pid /var/run/nginx.pid; #Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile ; events {
use epoll;
worker_connections ;
} http
{
include mime.types;
#include proxy.conf;
default_type application/octet-stream; server_names_hash_bucket_size ;
client_header_buffer_size 32k;
large_client_header_buffers 32k;
client_max_body_size 300m;
#client_max_body_size 32m; #limit_req_zone $baidu_spider zone=baidu_spider:10m rate=15r/m;
sendfile on;
tcp_nopush on; keepalive_timeout ; tcp_nodelay on;
#ssi on;
#ssi_silent_errors on;
fastcgi_connect_timeout ;
fastcgi_send_timeout ;
fastcgi_read_timeout ;
fastcgi_buffer_size 128k;
fastcgi_buffers 128k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
proxy_headers_hash_max_size ;
proxy_headers_hash_bucket_size ;
gzip on;
gzip_min_length 2k;
gzip_buffers 16k;
gzip_http_version 1.0;
gzip_comp_level ;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
#log_format access '$proxy_protocol_addr-,$remote_addr--,$proxy_add_x_forwarded_for---,$http_x_forwarded_for----,$remote_user,$time_local,$host,$request,$status,$http_referer,$HTTP_X_UP_CALLING_LINE_ID,$request_time,$http_user_agent $upstream_addr $upstream_response_time $upstream_cache_status';
log_format access '-$proxy_protocol_addr-,--$remote_addr--,---$http_x_forwarded_for---,----$proxy_add_x_forwarded_for----,$remote_user,$time_local,$host,$request,$status,$http_referer,$HTTP_X_UP_CALLING_LINE_ID,$request_time,$http_user_agent $upstream_addr $upstream_response_time $upstream_cache_status';
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_x_forwarded_for" "$http_user_agent"'; #upstream backend {
# server 127.0.0.1: weight= max_fails= fail_timeout=30s;
#} include conf.d/*; }

主要添加上以上红色粗体日志参数,这样在负载均衡的nginx上就可以看到https过来的客户端真实IP了,后端的WEB的https也可以获取真实IP了

另外如果是HA后面不再通过NG做反向代理转发的话,那么NG的主机文件配置需要如下配置

    server {
listen ssl proxy_protocol;
server_name ihouse.ifeng.com;
ssl_certificate /data/ifengsite/htdocs/ihouse.ifeng.com.crt;
ssl_certificate_key /data/ifengsite/htdocs/ihouse.ifeng.com.key; ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
set_real_ip_from 172.17.3.0/24;
real_ip_header proxy_protocol;
location / {
root html;
index index.html index.htm;
}
}

依然需要设置 proxy_protocol

设置real_ip的前端代理主机IP或者IP段

设置real_ip 的header

参考文献

https://www.52os.net/articles/PROXY_protocol_pass_client_ip.html

https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/

haproxy + nginx + proxy protocol 获得客户真实IP方法的更多相关文章

  1. 添加nginx新模块,获取客户真实ip

    当前是客户端登录软件后台获取不到客户的真实ip而是云盾的代理ip 为了获取到真实ip后来发现通过配置nginx的read_ip模块就可以了 获取客户的真实ip使用Nginx的realip模块 当Ngi ...

  2. nginx 获取源IP 获取经过N层Nginx转发的访问来源真实IP

    1. nginx 配置文件中获取源IP的配置项 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; #一般的we ...

  3. nginx反向代理nginx,RealServer日志打印真实ip

    title: nginx反向代理nginx,RealServer日志打印真实ip date: 2016-05-11 19:15:37 tags: --- nginx反向代理nginx,RealServ ...

  4. nginx反向代理如何获取真实IP?

    由于客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址. 1.安装--with-http_realip_ ...

  5. linux 获取经过N层Nginx转发的访问来源真实IP

    linux 获取经过N层Nginx转发的访问来源真实IP 学习:http://blog.csdn.net/zhenzhendeblog/article/details/49702575 学习:http ...

  6. nginx反向代理获取用户真实ip

    nginx做反向代理时,默认的配置后端获取到的ip都是来自于nginx,如何转发用户的真实ip到后端程序呢?如是是java后端,用request.getRemoteAddr();获取到的是nginx的 ...

  7. 11种绕过CDN查找真实IP方法

    0x01 验证是否存在CDN 方法1: 很简单,使用各种多地 ping 的服务,查看对应 IP 地址是否唯一,如果不唯一多半是使用了CDN, 多地 Ping 网站有: http://ping.chin ...

  8. 绕过CDN查找真实IP方法总结

    CDN的全称是Content Delivery Network,即内容分发网络.CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡.内容分发.调度等功能模 ...

  9. 绕过CDN查找真实IP方法

    0x01 验证是否存在CDN 方法1: 很简单,使用各种多地 ping 的服务,查看对应 IP 地址是否唯一,如果不唯一多半是使用了CDN, 多地 Ping 网站有:http://ping.china ...

随机推荐

  1. CS229 4.Logistic Regression

  2. 「HNOI2015」开店(树链剖分, 主席树)

    /* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...

  3. sql中的in与not in,exists与not exists的区别

    1.in和exists in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的.如果查询的两个表 ...

  4. spring boot区分生产环境和开发环境

    回顾一下spring boot使用基础,做个笔记. 通过配置文件,设置项目的开发环境和生成环境. 项目目录结构: application-dev.yml是开发环境配置文件,application-pr ...

  5. lunix 集群,负载均衡,location

       nginx location语法: location支持的语法优先级: 复制代码location匹配顺序 #  www.s14hanju.com/1.location = / {  我是代码1} ...

  6. mac“打不开身份不明的开发者”

    在mac安装软件发现这样的提示 解决方法: 打开系统偏好设置-->安全与隐私-->通用-->选择任何来源 不能选择的话点击按钮锁即可编辑 没有“任何来源”选项(比如我的mac) 打开 ...

  7. python- 日志学习

    # @File : learn_logging.py #-*- coding:utf-8 -*- """ 日志:log 记录代码执行的过程 一旦记录下来,就可以根据日志去 ...

  8. 3.Appnium的安装

    Appnium:移动端的自动测试话工具,类似selenium,可利用其驱动手机端去模拟点击.滑动.输入操作. 下载地址:https://github.com/appium/appium-desktop ...

  9. 57.1拓展之纯 CSS 创作黑暗中的眼睛和嘴巴

    效果地址:https://scrimba.com/c/cJ8NPpU2 HTML code: <div class="eyes"> <span class=&qu ...

  10. 26.纯 CSS创作按钮被从纸上掀起的立体效果

    原文地址:https://segmentfault.com/a/1190000014930183 感想:主要2D和3D转换.阴影效果. HTML代码: <nav> <ul> & ...