保留地址段 | 地址起始 | IP 地址数量 | 用途 |
---|---|---|---|
0.0.0.0/8 | 0.0.0.0 – 0.255.255.255 | 16,777,216 | 软件 |
10.0.0.0/8 | 10.0.0.0 – 10.255.255.255 | 16,777,216 | 内网 |
100.64.0.0/10 | 100.64.0.0 – 100.127.255.255 | 4,194,304 | 内网 |
127.0.0.0/8 | 127.0.0.0 – 127.255.255.255 | 16,777,216 | 主机 (本机) |
169.254.0.0/16 | 169.254.0.0 – 169.254.255.255 | 65,536 | 本地子网 (DHCP Failed) |
172.16.0.0/12 | 172.16.0.0 – 172.31.255.255 | 1,048,576 | 内网 |
192.0.0.0/24 | 192.0.0.0 – 192.0.0.255 | 256 | 内网 |
192.0.2.0/24 | 192.0.2.0 – 192.0.2.255 | 256 | "TEST-NET" |
192.88.99.0/24 | 192.88.99.0 – 192.88.99.255 | 256 | 6to4 anycast |
192.168.0.0/16 | 192.168.0.0 – 192.168.255.255 | 65,536 | 内网 |
198.18.0.0/15 | 198.18.0.0 – 198.19.255.255 | 131,072 | 内网 |
198.51.100.0/24 | 198.51.100.0 – 198.51.100.255 | 256 | "TEST-NET-2″ |
203.0.113.0/24 | 203.0.113.0 – 203.0.113.255 | 256 | "TEST-NET-3″ |
224.0.0.0/4 | 224.0.0.0 – 239.255.255.255 | 268,435,455 | 预留 |
240.0.0.0/4 | 240.0.0.0 – 255.255.255.254 | 268,435,455 | 预留 |
255.255.255.255/32 | 255.255.255.255 | 1 | 广播 |
我经常拿这个问题去刁难人,能说出三个段的人,至少是具备网络基础知识的,说出 5 个以上的,一般我会请他喝酒。
连保留 IP 是啥都不知道的,我就得尝试用另外一种方式去跟他解释这个问题了。
保留 IP 可以说是 TCP/IP 协议的约定吧,每一个段都有相应的使用说明,都有与之对应的 RFC 文档。
比如,中国境内,移动设备在 4G 环境下获取到的内网 IP,一般是 10.0.0.0/8 或者 100.64.0.0/10 的。
非物理隔离的网络系统,一般会是用 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 内划分内网地址,比较常见。
据 @高春辉说,除了这些之外,还有一些很小的保留 IP 段,如果不详细去看完整的 whois 数据,可能都不会发现。
X-Forwarded-For(XFF)是用来识别通过 HTTP 代理或负载均衡方式连接到 web 服务器的客户端最原始的 IP 地址的 HTTP 请求头字段。 Squid 缓存代理服务器的开发人员最早引入了这一 HTTP 头字段,并由 IETF 在 HTTP 头字段标准化草案中正式提出。
XFF 的工作机制是,每经过一层代理,由代理服务器,把 tcp 报文中的 Source IP,添加到 XFF 的末尾,多个 IP 以逗号分隔。这里说的代理是广义的,包括负载均衡 (比如阿里云 SLB),反向代理 (比如 Nginx),缓存服务器 (比如 Squid)。
一方面,XFF 提供了向后端业务系统传递用户 IP 的机制,后端业务系统,可以通过 XFF 感知到访问者的真实 IP。
另一方面,XFF 非常易于伪造。很多浏览器插件,可以随机填充 XFF 字段,如果没有一套正确的机制来处理 XFF 字段,而盲目地提取 XFF 中第一个 IP 作为访问者的 IP,就一定会出问题。
前面提到了,来源 IP 是保留 IP 的情况,其实大多数是由于业务系统直接以 TCP 报文中的 remote address 作为来源 IP 使用了。而这个 IP,一般是企业自己的反向代理服务器。
除此之外,XFF 伪造的过程中,IP 地址是随机生成的,可能会出线保留 IP,非法 IP,有少数情况可能会出现 "未启用 IP",也就是说这个 IP 已经分配给特定的运营商,但是运营商还没有添加这个 IP 的路由,这个 IP 无法被外界访问,也不会访问任何人。
这些 IP 是动态变化的,据老高说,只有分析 BGP 数据的时候,才能看到哪些 IP 是没有被启用的。
下面是一个简单的示意图,简单地把整个访问链路划分成可信区域和不可信区域。
可信区域,就是平台自己,或者友商建立的系统,可以保证从这些系统中获取并传递的数据是真实的、可信的。
获取来源 IP 的正确方式,是提取并记录本次请求首次进入可信区域时的 remote address。不论这个 IP 是不是代理。
XFF 伪造的情况其实非常普遍,也陆续地出现了一些替代方案,我司目前使用的,是设置一个专用的字段来传递这个 IP,不会和 XFF 相覆盖。
此外,某些 CDN 服务商,会有自己定制化的 Header 字段,情况比较多,建议结合具体的情况来决定如何获取用户的来源 IP。
比如,之前遇到一个客户,使用了阿里云的 SLB 负载均衡,SLB 会给每一个请求都加上 X-Forwarded-For 字段,他们自己的反向代理又加一次。那么其实只要获取 XFF 中倒数第三个 IP,作为来源 IP 即可。
一种参考方式如下:
在反向代理 (Nginx) 上配置,增加 Real-IP 字段:
- location / {...proxy_set_header Real - IP $remote_addr;...
- }
业务系统中,获取来源 IP 的代码如下 (Java 示例):
- @SuppressWarnings("unchecked") public static ClientIps getClientIpAddr(HttpServletRequest request) {
- // 获取真实ip
- String ip = request.getHeader("real-ip");
- if (StringUtils.isBlank(ip) || ("unknown".equalsIgnoreCase(ip.trim()))) {
- ip = request.getHeader("remote-host");
- }
- if (StringUtils.isBlank(ip) || ("unknown".equalsIgnoreCase(ip.trim()))) {
- ip = request.getRemoteAddr();
- }
- ClientIps clientIps = new ClientIps();
- clientIps.setTrueIp(StringUtils.trimToEmpty(ip));
- // 获取代理ip
- ip = request.getHeader("x-forwarded-for");
- StringBuilder proxyIps = new StringBuilder();
- if (StringUtils.isNotBlank(ip) && (StringUtils.contains(ip, ","))) {
- String temp = StringUtils.substringBeforeLast(ip, ",");
- if (StringUtils.isNotBlank(temp)) {
- proxyIps.append("x-forwarded-for:");
- proxyIps.append(temp);
- proxyIps.append("\n");
- }
- }
这个问题实在是简单到爆炸,懂技术的同学看到,肯定会喷我,居然写这种没水平的文章。
但是呢,作为一个数据分析师,看着每天系统里辣么多保留 IP,非法 IP 传进来,真的很憋屈。体谅下咯~
而且,每每看别人说攻击溯源…. 我满脑子想的都是:你连获取到的 IP 是不是真的你都不知道,你在追溯个啥?
By the way,欢迎有兴趣深入研究 IP 地址的童鞋一起交流,没准能带你跟老高一块儿喝羊汤。
来源: http://www.tuicool.com/articles/viamUf