nginx做负载CDN加速获取端真实ip在不用cdn的情况下,nginx做负载获取真实ip时,nginx配置如下:Java代码 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 然后后端服

nginx 做负载CDN加速获取端真实ip   在不用cdn的情况下,nginx做负载获取真实ip时,nginx配置如下:   Java代码   proxy_set_header        Host            $host;   proxy_set_header        X-Real-IP       $remote_addr;   proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;     然后后端服务器获取ip代码:   Java代码   String address = request.getHeader("X-Forwarded-For");   if (address != null && address.length() > 0           && !"unknown".equalsIgnoreCase(address)) {       return address;    www.cit.cn   }   address = request.getHeader("Proxy-Client-IP");   if (address != null && address.length() > 0           && !"unknown".equalsIgnoreCase(address)) {       return address;   }   address = request.getHeader("WL-Proxy-Client-IP");   if (address != null && address.length() > 0           && !"unknown".equalsIgnoreCase(address)) {       return address;   }   return request.getRemoteAddr();   这样就能获取到真实的IP,服务器测试一下:
  不加cdn,获取得IP:123.116.126.51(我当前客户端机器的真实IP) 然后加上加了cdn后,后去到的IP:123.116.126.51, 202.108.251.166(hosts指向cdn的ip) 即:client 真实IP,代理IP,google之, X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项 。
  标准格式如下: X-Forwarded-For: client1, proxy1, proxy2 从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡 的ip地址,经过几个就会出现几个。   当Nginx设置X-Forwarded-For等于$proxy_add_x_forwarded_for后会有两种情况发生   www.cit.cn   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,CDN的ip“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。   这个比较头疼,如果只想获取客户端真实ip,那么只能修改我们后端代码,如果有多个,那么取第一个。这不是我想要的, 那么怎么样才能不修改就能真实IP呢? 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或者干脆不设置!   上面这段话的意思是我们不加 $proxy_add_x_forwarded_for, 但是这样不在cdn的情况下去会取不到真实IP,有没有一个两全齐美的方法呢? 经过几种配置之后,发现做如下配置:   Java代码    www.cit.cn   proxy_set_header X-Forwarded-For  $http_x_forwarded_for;   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;         这样配置第一次获取 $http_x_forwarded_for,如果不存在,那么获取$proxy_add_x_forwarded_for。 这样不管是否在cdn环境,都可以获得一个客户端IP。   (注:多层代理未测试)     作者 lavafree

使用了$http_x_forwarded_for后,测试nginx配置时可能报

nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size

nginx: [warn] could not build optimal proxy_headers_hash, you should increase either proxy_headers_hash_max_size: 512 or proxy_headers_hash_bucket_size: 64; ignoring proxy_headers_hash_bucket_size

解决方法:

在http {}时增加

proxy_headers_hash_max_size 2048;

proxy_headers_hash_bucket_size 256;

oxy_set_headerThis directive allows to redefine and to add some request header lines which will be transferred to the proxied server.
这个不是change而是add,我了割草....我分析了好久日志才发现,然后对照官网,果不其然

ex:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,由于默认是空,所以也可以理解为change,但是切记不要搞乱

X-Forwarded-ForX-Forwarded-For: client1, proxy1, proxy2
The X-Forwarded-For (XFF) HTTP header is a de facto standard for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer. This is a non-RFC-standard request header which was introduced by the Squid caching proxy server's developers.
这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,
每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址
由于他是非rfc标准,所以默认是没有的,需要强制添加
在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip

└(^o^)┘

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

Code block

测试环境: nginx+resin
IP: 内网:172.16.100.10

客户端IP:123.123.123.123

测试页面: test.jsp
<%
out.println("x-forwarded-for: " + request.getHeader("x-forwarded-for"));
out.println("remote hosts: " + request.getRemoteAddr());
%>

nginx 配置一
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

wget测试
wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"
页面返回结果:
x-forwarded-for: 192.168.0.1, 123.123.123.123
remote hosts: 172.16.100.10

curl测试
curl -H "X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"
x-forwarded-for: 192.168.0.1, 123.123.123.123
remote hosts: 172.16.100.10

nginx 配置二
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

wget测试:
wget -O aa --header="X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"
页面返回结果:
x-forwarded-for: 123.123.123.123
remote hosts: 172.16.100.10

curl测试
curl -H "X-Forwarded-For:192.168.0.1" "http://2hei.net/test.jsp"
x-forwarded-for: 123.123.123.123
remote hosts: 172.16.100.10

测试结果:
1、配置  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
增加了一个真实ip X-Forwarded-For,并且顺序是增加到了“后面”。

2、配置  proxy_set_header X-Forwarded-For $remote_addr;
清空了客户端伪造传入的X-Forwarded-For,
保证了使用request.getHeader("x-forwarded-for")获取的ip为真实ip,
或者用“,”分隔,截取X-Forwarded-For最后的值。

特别说明:

a、Fikker 通过 HTTP 头传递用户 IP 地址给源站,例如:X-Forwarded-For: 21.23.44.78 。
b、如出现多个 IP 时,例如:X-Forwarded-For: 21.23.44.78; 156.24.66.231,表明用户请求经过多次 Fikker 转发,这时有效起始地址为第一个,即 21.23.44.78 。

asp 获得用户 IP 代码举例:

<%
Private Function getIP() 
Dim strIPAddr 
If Request.ServerVariables("HTTP_X_FORWARDED_FOR") = "" OR InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), "unknown") > 0 Then 
strIPAddr = Request.ServerVariables("REMOTE_ADDR") 
ElseIf InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ",") > 0 Then 
strIPAddr = Mid(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), 1, InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ",")-1) 
ElseIf InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ";") > 0 Then 
strIPAddr = Mid(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), 1, InStr(Request.ServerVariables("HTTP_X_FORWARDED_FOR"), ";")-1) 
Else 
strIPAddr = Request.ServerVariables("HTTP_X_FORWARDED_FOR") 
End If 
getIP = Trim(Mid(strIPAddr, 1, 30)) 
End Function

ip=getIP()
response.write(ip)
%>

java 获得用户 IP 代码举例:

public String getRemortIP(HttpServletRequest request) 
{
    if (request.getHeader("X-Forwarded-For") == null) 
    {
        return request.getRemoteAddr(); 
    }
    
    return request.getHeader("X-Forwarded-For");  /* 多个 IP 列表时, 则取第一个! */ 
}

asp.net 获得用户 IP 代码举例:

void getSourceIP() 

    string SourceIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; /* 获得用户 IP 地址 */ 
    if (string.IsNullOrEmpty(SourceIP))
    { 
        SourceIP = Request.ServerVariables["REMOTE_ADDR"]; /* 兼容已有程序 */ 
    }
    
    Response.Write(SourceIP); 
}

php 获得用户 IP 代码举例:

function getRemortIP()
{
    if (!isset($_SERVER["HTTP_X_FORWARDED_FOR"])) /* 存在 X-Forwarded-For 吗? */ 
    {
        return $_SERVER["REMOTE_ADDR"];
    }
    
    return $_SERVER["HTTP_X_FORWARDED_FOR"]; /* 返回用户 IP */ 
}

echo getRemortIP();

转载于:https://blog.51cto.com/tianshili/1638554

nginx做负载CDN加速获取端真实ip相关推荐

  1. nginx做负载均衡 tomcat获得客户端真实ip

    转 http://www.cnblogs.com/netsa/p/6985990.html 因项目需要做tomcat2台机器的负载均衡,配置好负载环境后,发现tomcat的日志一律是我前置nginx代 ...

  2. 使用nginx代理的情况下获取用户真实IP

    ##1.背景知识 1.1. 前提知识点: 还有nginx中的几个变量: remote_addr 代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站 ...

  3. nginx利用反向代理实现获取用户真实ip

    我们访问互联网上的服务时,大多数时,客户端并不是直接访问到服务端的,而是客户端首先请求到反向代理,反向代理再转发到服务端实现服务访问,通过反向代理实现路由/负载均衡等策略.这样在服务端拿到的客户端IP ...

  4. Nginx网站使用CDN之后禁止用户真实IP限制访问方法

    做过面向公网WEB运维的苦逼们肯定见识过各种恶意扫描.拉取.注入等图谋不轨行为吧?对于直接对外的WEB服务器,我们可以直接通过 iptables . Nginx 的deny指令或者是程序来ban掉这些 ...

  5. Nginx反向代理后无法获取客户端真实IP地址

    当我们使用 Nginx 代理转发服务后,会发现我们无法获取客户端的真实IP地址,从而无法获取客户端的地理位置等信息. 1.原始配置文件如下 worker_processes 1;events {wor ...

  6. 获取客户端真实ip的方法

    为什么需要获取客户端真实ip ip地址是按地域分布的,服务器获取到客户端ip后可以做流量统计和分析,服务器也可以针对客户端ip做一些定制化的功能,比如限流和黑白名单. 网络环境十分复杂,客户端发出的一 ...

  7. CDN下nginx获取用户真实IP地址

    为什么80%的码农都做不了架构师?>>>    随着nginx的迅速崛起,越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能 ...

  8. Nginx 获取客户端真实IP $remote_addr与X-Forwarded-For

    nginx配置 首先,一个请求肯定是可以分为请求头和请求体的,而我们客户端的IP地址信息一般都是存储在请求头里的.如果你的服务器有用Nginx做负载均衡的话,你需要在你的location里面配置X-R ...

  9. Nginx获取客户端真实ip

    三.如何在使用代理后获取用户ip 在<实战nginx>中,有这么一句话: 经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$rem ...

最新文章

  1. Yolo(2)Yolo v2
  2. C# 利用net 命令获取域用户列表
  3. c 语言文字输出函数,c/c++语言中文字输出函数总结
  4. AJAX 异步加载技术
  5. Git学习笔记:常用命令总结
  6. linux常用命令-第一篇
  7. 5.VMware View 5.0安装与部署-安装view agent与模版
  8. AutoCAD2020命令提示框信息设置
  9. python调用v8_Python 安装 V8 引擎 – pyv8
  10. 献礼厦门大学百年校庆!亿联网络「沉浸式交互教室」首次亮相即惊艳
  11. matlab斜抛运动不用公式,分享斜抛运动中算末速度的公式
  12. 力扣LeetBook<链表>学习笔记
  13. 相机溯源之传统方法(PRNU提取)
  14. JavaBean 是什么?JavaBeans 概念介绍
  15. 基于HFS快速搭建HTTP文件服务器
  16. centos下面,解压.gar.gz文件
  17. 精通Java事务编程(8)-可串行化隔离级别之可串行化的快照隔离
  18. Python应用与实践
  19. 计算机运算器实验原理,运算器实验原理.ppt
  20. ElasticSearch数据迁移工具Transporter

热门文章

  1. 利用UICollectionView实现瀑布流
  2. EBS R12.2 创建应用层的启动和关闭脚本
  3. HttpClient的使用方法
  4. ZOJ 1315【Excuses, Excuses!】------2015年2月9日
  5. android double值排序,android根据Double类型数据经纬度算出距离再根据距离实现排序功能...
  6. android 3.10. 内核,编译android 3.10内核源码时出错
  7. 螃蟹保存方法保存时间_蜂巢蜜应该怎么保存,蜂巢蜜怎么保存的时间更长
  8. 渣男,你为什么有这么多小姐姐的照片?因为我Python爬虫学的好啊❤️!
  9. primefaces_Primefaces单选按钮,复选框示例
  10. android 底边框_Android底表