构造HTTP请求Header实现“伪造来源IP”(重在原理)

转载自:

http://zhangxugg-163-com.iteye.com/blog/1663687

 

http://www.walkerjava.com/index.php?m=blog&f=view&id=10

1. 伪造原理

在阅读本文前,大家要有一个概念,在实现正常的TCP/IP 双方通信情况下,是无法伪造来源 IP 的,也就是说,在 TCP/IP 协议中,可以伪造数据包来源 IP ,但这会让发送出去的数据包有去无回,无法实现正常的通信。这就像我们给对方写信时,如果写出错误的发信人地址,而收信人按信封上的发信人地址回信时,原发信人是无法收到回信的。

 

一些DDoS 攻击,如 SYN flood,  就是利用了 TCP/ip 的此缺陷而实现攻击的。《计算机网络》教材一书上,对这种行为定义为“发射出去就不管”。

 

因此,本文标题中的伪造来源IP 是带引号的。并非是所有 HTTP 应用程序中存在此漏洞。

 

那么在HTTP 中, " 伪造来源 IP",  又是如何造成的?如何防御之?

在理解这个原理之前,读者有必要对HTTP 协议有所了解。 HTTP 是一个应用层协议,基于请求 / 响应模型。客户端(往往是浏览器)请求与服务器端响应一一对应。

 

请求信息由请求头和请求正文构成(在GET 请求时,可视请求正文为空)。请求头类似我们写信时信封上的基本信息,对于描述本次请求的一些双方约定。而请求正文就类似于信件的正文。服务器的响应格式,也是类似的,由响应头信息和响应正文构成。

 

为了解这个原理,可使用Firefox Firebug,  或 IE 浏览器插件 HTTPwatch 来跟踪 HTTP 请求 / 响应数据。

 

左边即是请求数据,右边即是服务器响应数据。

特点:

请求 header 中除第一行外,其它行均由 header 名称, header 值组成,如  Accept-Encoding: gzip, deflate , header 名称与值之间有冒号相隔,之间的空格是可有可无的。

那么,在HTTP 应用程序中,如何取得指定的请求 header 信息呢?

以下是js获取ip地址:

 

 
  1. public String getIpAddr(HttpServletRequest request) {

  2. String ip = request.getHeader("x-forwarded-for");

  3. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

  4. ip = request.getHeader("Proxy-Client-IP");

  5. }

  6. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

  7. ip = request.getHeader("WL-Proxy-Client-IP");

  8. }

  9. if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

  10. ip = request.getRemoteAddr();

  11. }

  12. return ip;

  13. }

由上可知: 服务器通过request中的 x-forwarded-for 和 client-ip 来获取 客户端的ip.

那么,如果客户端伪造 Client-Ip, X-Forward-For ,可以欺骗此程序,达到“伪造 IP ”之目的.

 

2. 那么如何伪造这项值(X-Forward-For)?

方法一: 如果你会写程序,并了解HTTP 协议,直接伪造请求 header 即可

方法二: 使用 Firefox 的Moify Headers 插件即可(推荐)

 

3. 如何避免伪造ip

方法:服务器重新配置X-Forward-For 为正确的值

 

服务器集群之间的通信,是可以信任的。我们要做的就是在离用户最近的前端代理上,强制设定X-Forward-For 的值,后端所有机器不作任何设置,直接信任并使用前端机器传递过来的 X-Forward-For 值即可。

 

即在最前端的Nginx 上设置:

location  ~  ^/static {

proxy_pass  ....;

proxy_set_header X-Forward-For $remote_addr ;

}

 

如果最前端(与用户直接通信)代理服务器是与php fastcgi 直接通信,则需要在其上设定:

location ~ "\.+\.php$" {

fastcgi_pass localhost:9000;

fastcgi_param  HTTP_X_FORWARD_FOR  $remote_addr;

}

记住,$remote_addr 是 nginx 的内置变量,代表了客户端真实(网络传输层) IP 。通过此项措施,强行将 X-Forward-For 设置为客户端 ip,  使客户端无法通过本文所述方式“伪造 IP ”。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值