客户端ip获取蹲坑启示: 不要侥幸

栏目: 数据库 · 发布时间: 7年前

内容简介:怎么获取一个客户端ip ? 我想这个问题,在网上遍地都是答案!而且多半是像下面这样:我也没说要去研究这玩意,我只是不想重复造轮子,然后努力找到了了代码仓库里有这么一段代码,所以,我就用来去获取ip了!

怎么获取一个客户端ip ? 我想这个问题,在网上遍地都是答案!

而且多半是像下面这样:

    
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return ip;
    }

我也没说要去研究这玩意,我只是不想重复造轮子,然后努力找到了了代码仓库里有这么一段代码,所以,我就用来去获取ip了!

测试环境一切ok。然后稀拉拉地,上线了!

嘿,一上线之后,发现了数据库ip字段竟然有两个ip: 10.11.0.6, 202.116.0.83 。

好嘛,一看就知道是怎么回事了,这个用户的请求是通过代理进来的,而代理只是一种很正常的转发行为,所以必须处理这种情况!

由于原来我设置的ip字段大小为varchar(32), 所以装下这两个ip,是松的事! 大概查了下日志,并没有发现什么异常!

我想着吧,一般的用户也就是一级代理下,就差不多了。所以应该不会有什么问题,这个问题留给下个版本修复吧!

我就这么想着,玩去了。

然后,就被邮件报警了!数据库插入失败!

妈蛋,该来的始终要来!我还是太年轻了。

有一句叫: 如果你发现有个问题可能会发生,那么它就一定会发生!

不要侥幸,没人能跑得掉!

修复办法自然简单到没朋友,截取第一个',' 前的ip就行了!

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        // 多级代理问题修复
        if (ip.indexOf(',') > 0) {
            ip = ip.substring(0, ip.indexOf(',')).trim();
        }

        return ip;
    }

好了,问题解决了,警告咱们要有敬畏之心。

下面,咱们来看看多级代理的ip是怎么回事?

在 nginx 中,咱们可以这么设置:

    location /api {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://10.11.20.22/api;
    }

这样的话,后续服务端就可以通过获取 X-Forwarded-For 来进行获取所有的代理ip地址链了!

格式为: X-Forwarded-For:10.11.247.1, 10.11.38.131, 10.11.255.1 ...

也就是说 X-Forwarded-For 是呈叠加的方式的,所以,我们应该只需要取到 第一个ip 就可以了!

事实上,X-Forwarded-For 是可以伪造的。

比如: curl -H "X-Forwarded-For:11.11.22.22" http://a.com/api

可以看到,确实很容易就进行伪造了。而按照后端代理服务器的设置,其只会往该header里添加自己的值,所以,如果此时咱们按照获取第一个值为ip,也就判断失误了。不过这种失误,一般我们还是可以接受的。不过有的场景就不适用了,比如我们通过ip来做权限管理时!所以,在做ip白名单时,还要考虑实际情况而行了!

好了,看得出通过代理标识获取ip是不可靠的,那么,有没有一种可靠的获取ip的方式呢?

其实是一个值是不可以改的:REMOTE_ADDR. 这个字段源于 tcp/udp 请求中,就会带有源地址,目标地址!

REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。但是如果你使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。

所以,REMOTE_ADDR 虽然是不可改的,但是它却只能代表一级服务器ip,而面对现在复杂的网络环境,那是太无能为力了!

所以,没办法,还得通过约定的变量来,而这个变量又要依赖于使用的代理设置了。如上!虽然可以伪造,但是至少绝大部分是对的!

最后,给一个 tcp 发送数据样例( src -> dst):

客户端ip获取蹲坑启示: 不要侥幸


以上所述就是小编给大家介绍的《客户端ip获取蹲坑启示: 不要侥幸》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Music Recommendation and Discovery

Music Recommendation and Discovery

Òscar Celma / Springer / 2010-9-7 / USD 49.95

With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具