热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于nginx多层uptstream转发获取客户端真实IP的问题

因为公司有个需求需要获取客户端的真实IP,前端是haproxy,后面是nginx,本来这个需求不难完成,但是难就难在是https请求也就是ssl由于个人水平有限,在网上爬了很多资料

因为公司有个需求需要获取客户端的真实IP,前端是haproxy,后面是nginx,本来这个需求不难完成,但是难就难在是https请求也就是ssl

由于个人水平有限,在网上爬了很多资料,刚开始的ha是通过tcp代理443端口的,但是无法转发7层的X-Forwarded-For到后面的nginx,那么后面的ng肯定拿不到真实IP了

怎么办呢,网上爬资料

第一在HA上做ssl中断,中断后https协议就变成http协议了这样可以转发到后面nginx上,后面nginx不需要用ssl,但是问题来了,弄好页面出了点问题,并且暂时没法解决,只好暂时作罢

这条路行不通怎么办,那就用nginx做负载吧,谁让自己Low呢,nginx总在7层了吧

说干就干,安装nginx,配置下配置文件,启动,走起

主配置文件如下:

 1 user  www www;
 2 worker_processes 20;
 3 
 4 error_log  /data/logs/nginx/error.log;
 5 pid        /var/run/nginx.pid;
 6 
 7 #Specifies the value for maximum file descriptors that can be opened by this process.
 8 worker_rlimit_nofile 51200;
 9 
10 events {
11     use epoll;
12     worker_connections 51200;
13 }
14 
15 http
16 {
17     include       mime.types;
18     #include       proxy.conf;
19     default_type  application/octet-stream;
20     
21     server_names_hash_bucket_size 128;
22     client_header_buffer_size 32k;
23     large_client_header_buffers 4 32k;
24     client_max_body_size    300m;
25     #client_max_body_size    32m;
26     
27     #limit_req_zone $baidu_spider zOne=baidu_spider:10m rate=15r/m;
28     sendfile on;
29     tcp_nopush     on;
30     
31     keepalive_timeout 30;
32     
33     tcp_nodelay on;
34     #ssi on;
35     #ssi_silent_errors on;
36     #ssi_types text/shtml;
37     
38     fastcgi_connect_timeout 180;
39     fastcgi_send_timeout 180;
40     fastcgi_read_timeout 180;
41     fastcgi_buffer_size 128k;
42     fastcgi_buffers 8 128k;
43     fastcgi_busy_buffers_size 128k;
44     fastcgi_temp_file_write_size 128k;
45     proxy_headers_hash_max_size 51200;
46     proxy_headers_hash_bucket_size 6400;
47     gzip on;
48     gzip_min_length      2k;
49     gzip_buffers         4 16k;
50     gzip_http_version     1.0;
51     gzip_comp_level    6;
52     gzip_types           text/plain application/x-Javascript text/css application/xml;
53     gzip_vary         on;
54         log_format  access     '$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';    
55     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
56         #              '$status $body_bytes_sent "$http_referer" '
57         #              '"$http_x_forwarded_for" "$http_user_agent"';
58 
59     #upstream backend {
60     #    server 127.0.0.1:9000 weight=5  max_fails=3  fail_timeout=30s;
61     #}
62 
63     include conf.d/*;
64 
65 }

然后我们配置子配置文件:

 1 upstream ihouse443{
 2   server 10.0.30.37:443 max_fails=3 fail_timeout=60 weight=1;
 3   server 10.0.30.38:443 max_fails=3 fail_timeout=60 weight=1;
 4   server 10.0.30.39:443 max_fails=3 fail_timeout=60 weight=1;
 5 
 6 }
 7 
 8 
 9 
10 server {
11   listen 443;
12   server_name www.abc.com;
13   access_log /data/logs/nginx/abc_access.log access;
14   error_log  /data/logs/nginx/abc_error.log ;
15   ssl on;
16   ssl_certificate /data/ifengsite/htdocs/abc.sss.com.crt;
17   ssl_certificate_key /data/ifengsite/htdocs/abc.sss.com.key;
18 
19   ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:HIGH:!aNULL:!MD5:!ADH:!DH;
20   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
21 
22   #location /stub_status {
23   #  stub_status;
24   #}
25 
26 
27   location / {
28     proxy_pass https://ihouse443;
29     proxy_redirect off;
30     proxy_set_header Host $host;
31     proxy_set_header X-Real-IP $remote_addr;
32     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
33     #proxy_set_header X-Forwarded-For $http_x_forwarded_for;
34     proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
35     proxy_max_temp_file_size 0;
36     proxy_connect_timeout 90;
37     proxy_send_timeout 90;
38     proxy_read_timeout 90;
39     proxy_buffer_size 4k;
40     proxy_buffers 4 32k;
41     proxy_busy_buffers_size 64k;
42     proxy_temp_file_write_size 64k;
43     #include        fastcgi_params;
44   }
45 }
46 
47 server {
48   listen 443;
49   server_name *.abc.def.com;
50   access_log /data/logs/nginx/ihouse_access1.log access;
51   error_log  /data/logs/nginx/ihouse_error.log ;
52   ssl on;
53   ssl_certificate /data/ifengsite/htdocs/_.sss.xxx.com.crt;
54   ssl_certificate_key /data/ifengsite/htdocs/_.sss.xxx.com.key;
55   ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:HIGH:!aNULL:!MD5:!ADH:!DH;
56   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
57   location / {
58     proxy_pass https://ihouse443;
59     proxy_redirect off;
60     proxy_set_header Host $host;
61     proxy_set_header X-Real-IP $remote_addr;
62     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
63     #proxy_set_header X-Forwarded-For $http_x_forwarded_for;
64     proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
65     proxy_max_temp_file_size 0;
66     proxy_connect_timeout 90;
67     proxy_send_timeout 90;
68     proxy_read_timeout 90;
69     proxy_buffer_size 4k;
70     proxy_buffers 4 32k;
71     proxy_busy_buffers_size 64k;
72     proxy_temp_file_write_size 64k;
73     #include        fastcgi_params;
74   }
75 }

然后启动nginx,去后面的ng上一看,哎怎么没真实IP呢?都是内网IP

后来在网上找了点 资料,如下解释,这是摘抄的

下面来分析请求头到达Nginx负载均衡服务器的情况;在默认情况下,Nginx并不会对X-Forwarded-For头做任何的处理,除非用户使用proxy_set_header 参数设置:

  1. proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for; 

$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr用逗号分开,如果没有"X-Forwarded-For" 请求头,则$proxy_add_x_forwarded_for等于$remote_addr。$remote_addr变量的值是客户端的IP。

当Nginx设置X-Forwarded-For于$proxy_add_x_forwarded_for后会有两种情况发生:

1、如果从CDN过来的请求没有设置X-Forwarded-For头(通常这种事情不会发生),而到了我们这里Nginx设置将其设置为$proxy_add_x_forwarded_for的话,X-Forwarded-For的信息应该为CDN的IP,因为相对于Nginx负载均衡来说客户端即为CDN,这样的话,后端的web程序时死活也获得不了真实用户的IP的。

2、CDN设置了X-Forwarded-For,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for的话,那么X-Forwarded-For的内容变成 ”客户端IP,Nginx负载均衡服务器IP“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。

    如上两点所说,如果我们知道了CDN设置了X-Forwarded-For信息,且只有客户端真实的IP的话,那么我们的Nginx负载均衡服务器可以不必理会该头,让它默认即可。

    其实Nginx中还有一个$http_x_forwarded_for变量,这个变量中保存的内容就是请求中的X-Forwarded-For信息。如果后端获得X-Forwarded-For信息的程序兼容性不好的话(没有考虑到X-Forwarded-For含有多个IP的情况),最好就不要将X-Forwarded-For设置为 $proxy_add_x_forwarded_for。应该设置为$http_x_forwarded_for或者干脆不设置!

#########################################################################################################

找到了以上内容,然后就测试

首先上面配置文件蓝色内容是后来加上去的,红色内容是原本就有的

蓝色的配置加上去后,红色的注释掉后,后端的nginx就可以获取真实IP了,具体原理就是上面所说的但是我还是不太明白,后续还要好好研究下。

附上后端nginx的配置

 1 user  www www;
 2 worker_processes 20;
 3 
 4 error_log  /data/logs/nginx/error.log;
 5 pid        /var/run/nginx.pid;
 6 
 7 #Specifies the value for maximum file descriptors that can be opened by this process.
 8 worker_rlimit_nofile 51200;
 9 
10 events {
11     use epoll;
12     worker_connections 51200;
13 }
14 
15 http
16 {
17     include       mime.types;
18     #include       proxy.conf;
19     default_type  application/octet-stream;
20     
21     server_names_hash_bucket_size 128;
22     client_header_buffer_size 32k;
23     large_client_header_buffers 4 32k;
24     client_max_body_size    300m;
25     #client_max_body_size    32m;
26     
27     #limit_req_zone $baidu_spider zOne=baidu_spider:10m rate=15r/m;
28     sendfile on;
29     tcp_nopush     on;
30     
31     keepalive_timeout 30;
32     
33     tcp_nodelay on;
34     #ssi on;
35     #ssi_silent_errors on;
36     #ssi_types text/shtml;
37     
38     fastcgi_connect_timeout 180;
39     fastcgi_send_timeout 180;
40     fastcgi_read_timeout 180;
41     fastcgi_buffer_size 128k;
42     fastcgi_buffers 8 128k;
43     fastcgi_busy_buffers_size 128k;
44     fastcgi_temp_file_write_size 128k;47     gzip on;
48     gzip_min_length      2k;
49     gzip_buffers         4 16k;
50     gzip_http_version     1.0;
51     gzip_comp_level    6;
52     gzip_types           text/plain application/x-Javascript text/css application/xml;
53     gzip_vary         on;
54         log_format  access     '$remote_addr,$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';    
55     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
56         #              '$status $body_bytes_sent "$http_referer" '
57         #              '"$http_x_forwarded_for" "$http_user_agent"';
58 
59     #upstream backend {
60     #    server 127.0.0.1:9000 weight=5  max_fails=3  fail_timeout=30s;
61     #}
62 
63     include conf.d/*;
64 
65 }

子配置文件

upstream ihouse443{
  server 10.0.30.38:34785 max_fails=3 fail_timeout=60 weight=1;
  server 10.0.30.38:34787 max_fails=3 fail_timeout=60 weight=1;
  server 10.0.10.50:34404 max_fails=3 fail_timeout=60 weight=1;

}

server {
  listen 443;
  server_name www.abc.com;
  access_log /data/logs/nginx/sss_access.log access;
  error_log  /data/logs/nginx/ihouse_error.log ;
  ssl on;
  ssl_certificate /data/ifengsite/htdocs/ss.xx.com.crt;
  ssl_certificate_key /data/ifengsite/htdocs/ssxx.com.key;

  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:HIGH:!aNULL:!MD5:!ADH:!DH;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  #location /stub_status {
  #  stub_status;
  #}

  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-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_max_temp_file_size 0;
    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
    #include        fastcgi_params;
  }
}

 后端nginx不需要配置

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

推荐阅读
  • 本文介绍了如何在 Spring Boot 项目中使用 spring-boot-starter-quartz 组件实现定时任务,并将 cron 表达式存储在数据库中,以便动态调整任务执行频率。 ... [详细]
  • 在 CentOS 7 环境中使用 MySQL 5.6 镜像启动数据库时遇到权限问题,本文将详细探讨并提供解决方案。 ... [详细]
  • HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送www方式的数据。HTTP协议采用了请求响应模型。客服端向服务器发送一 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 本文详细介绍了在Linux系统上编译安装MySQL 5.5源码的步骤。首先,通过Yum安装必要的依赖软件包,如GCC、GCC-C++等,确保编译环境的完备。接着,下载并解压MySQL 5.5的源码包,配置编译选项,进行编译和安装。最后,完成安装后,进行基本的配置和启动测试,确保MySQL服务正常运行。 ... [详细]
  • 深入解析 OpenSSL 生成 SM2 证书:非对称加密技术与数字证书、数字签名的关联分析
    本文深入探讨了 OpenSSL 在生成 SM2 证书过程中的技术细节,重点分析了非对称加密技术在数字证书和数字签名中的应用。非对称加密通过使用公钥和私钥对数据进行加解密,确保了信息传输的安全性。公钥可以公开分发,用于加密数据或验证签名,而私钥则需严格保密,用于解密数据或生成签名。文章详细介绍了 OpenSSL 如何利用这些原理生成 SM2 证书,并讨论了其在实际应用中的安全性和有效性。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • 一、Tomcat安装后本身提供了一个server,端口配置默认是8080,对应目录为:..\Tomcat8.0\webapps二、Tomcat8.0配置多个端口,其实也就是给T ... [详细]
author-avatar
1986欠我一个拥抱_567
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有