TTL,IP包存活时间

宝剑锋从磨砺出,梅花香自苦寒来。

—— 佚名·《警世贤文·勤奋篇》

参与网络通信的各种主体可以抽象成一张 graph ),每个主体是图的 节点node ),连接关系则是图的 edge )。

cycle ),一种首尾相连的特殊路径,是图论中重点研究的对象。那么,IP 包有没有可能陷入环形的路径,在回路中空转呢?如果这样的话,它不就永远无法到达目的地了吗?

在特殊的路由规则下,IP 包确实会陷入回路,下面是一个简单的例子:

请注意 3 台路由器中,关于 10.0.10.0/24 这个网段的路由规则:R1 上的规则说,应该发给 R2 来转发;R2 上的规则说,应该发给 R3 来转发;R3 上的规则说,应该发给 R1 来转发。

这 3 台路由器,就像三个挑水和尚,互相推诿。一个去往 10.0.10.0/24 网段的 IP 包进来后,傻转了一圈又回到入口处。此后,该包将不停打转,永远无法逃逸出去,更别说到达目的地。

IP 包无法达到目的地事小,拖垮路由事大。如果陷入环路的包无法清理,最终将耗尽线路的带宽和路由器的处理资源,影响正常数据的传输,造成大量丢包。

那么,有什么办法可以解决这个问题吗?

第一个思路是从根源解决问题,减少路由规则因缺陷形成回路的可能。由于网络拓扑通常很复杂,我们很难完全避免路由环路。以配置静态路由规则为例,很难保证配置规则的人不会犯错。

因此,我们还需要第二个思路,降低路由环路的影响。

还记得 IP 包的 TTL 字段吗?TTL 是 time to live 缩写,表示 IP 包的存活时间。一旦 IP 包存活时间超过 TTL ,路由便将它丢弃。这样一来,就算 IP 包陷入环路,经过一小段时间后,它也会从网络中消失,不会造成更大的影响。

网络中路由器数量巨大,很难做到时间同步。因此,在实际工程实现中,TTL 并不是直接保存存活时间,而是保存 IP 包失效前可以经过的路由跳数。IP 包每经过一跳路由,TTL 都会减一;当 TTL 减到 0 ,路由便将它丢弃。

有了 TTL 机制后,就算 IP 包陷入路由环路,循环若干次后,最终将自行消失,不会造成更大的影响:

回到 TTL 字段,它的长度是 8 比特。因此,一个 IP 包失效前最多可以经过 255 跳路由。你可能会有点诧异,区区 255 跳就可以将 IP 包送达目的地吗?

现行的 IP 网络看似非常庞大,但得益于骨干网络优化,任意两点的最短路径并不长。笔者在大洋彼岸的美国加州有一台 VPS 服务器,如果从广州家中出发,只需大约 13 跳即可达到。如此看来,TTL 最大值为 255 ,其实绰绰有余。

实际上,在很多系统协议栈中, IP 包默认 TTL 都不会有 255 跳之多;而且因系统不同还略有差异:

  • Windows 系统,IP 包默认 TTL 为 128 ;
  • Linux 系统,IP 包默认 TTL 为 64 ;

当然了,我们可以根据实际情况调整系统的默认 TTL 。以 Linux 为例,默认 TTL 是一个内核参数,可以通过 procfs 来访问,路径是 /proc/sys/net/ipv4/ip_default_ttl

执行 cat 命令,将该 procfs 文件内容输出即可查看当前配置:

1
2
root@netbox [ ~ ]  ➜ cat /proc/sys/net/ipv4/ip_default_ttl
64

将新值写入该 procfs 文件即可完成设置,例如将它改成 128 :

1
root@netbox [ ~ ]  ➜ echo 128 > /proc/sys/net/ipv4/ip_default_ttl

再次查看配置,可以确认它已经生效了:

1
2
root@netbox [ ~ ]  ➜ cat /proc/sys/net/ipv4/ip_default_ttl
128

小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: