摘要

  • Mobile IPv4 让移动节点保留归属地址,但接入网络的源地址过滤可能认为,这个地址不该从当前连接进入。地址真实与拓扑合适并不是同一件事。
  • 反向隧道把移动节点的数据先送回归属代理;在外地代理到归属代理这一段,外层源地址采用转交地址,内层仍保留通信端点。
  • 两种交付方式、注册时的 T 位、TTL 检查和归属代理的绑定核对各有边界。它们不等于加密,不保证穿越防火墙,也不把注册受理变成端到端交付承诺。

一个在别处仍然有效的地址

互联网地址既用于标识通信的两端,也参与网络对位置和路径的判断。多数时候,这两项用途没有显著冲突:主机从地址所属的网络发包,路由器依据目的地址转发,接收者知道该向哪里回应。移动把原本重合的两件事拆开了。

1996年10月的 RFC 2002 描述了一种 IPv4 移动机制:节点跨越子网时保留归属地址,同时通过转交地址表示当前可达位置。归属代理可以截获送往归属地址的数据,再用隧道交给节点当前所在的一侧。应用看到的端点不必随每一次位置变化而更换。

这里有两种安排。转交地址可以属于外地代理,由它为多个移动节点终结隧道;也可以由移动节点自己取得并使用,此时节点自行终结隧道。不能把后一种独占地址的直觉,套到前一种共享代理的场景里。

原来的模型有一个重要前提:路由主要看目的地址,而不是源地址。因此,回来的数据可以经过归属代理,发出去的数据却不一定要先回去。节点在外地发出的包,源地址仍是归属地址,目的地址则是通信对端。只要中间网络愿意照常转发,这个安排就能工作。

问题在于,网络并不总是只看目的地址。

过滤器没有指控它偷了地址

2000年5月的 RFC 2827,也就是 BCP 38,讨论在网络入口限制伪造源地址。提供商接收下游网络流量时,可以检查来源是否属于该连接应当使用的地址范围。来自不合适范围的包应被挡住,而不是因为目的地址可路由,就一路向前。

对攻击者而言,这是在收窄伪造空间。对移动节点而言,却出现一个棘手的交集:它没有冒用别人的归属地址,但那个地址不属于眼前这个访问网络。过滤器作的是拓扑判断,不是对用户诚实与否的裁决。

BCP 38 本身就承认了 Mobile IP 的这个问题,并提到反向隧道作为兼容办法。因此,这段历史不宜写成“安全规则意外毁掉移动性”,更不能据此主张边界不该检查来源。两个目标都合理:通信端点希望保持稳定,网络希望知道流量为什么从这个入口出现。

过滤同样不能完成全部身份验证。攻击者若伪造允许范围内的地址,前缀检查未必能分辨。把通过过滤等同于“发送者已认证”,会从另一端犯同一个错误:让一个只负责局部条件的机制,替所有其他条件背书。

回家,是为了换一层地址

1998年5月的 RFC 2344 定义了相关反向隧道扩展;2001年1月的 RFC 3024 替代了它。所谓反向,是相对于归属代理把数据送到当前位置的既有方向而言。移动节点发出的数据反过来先到归属代理,再向通信对端转发。

关键不在于把原来的源地址抹掉,而在于多出一层具有不同任务的包头。RFC 2003 所描述的 IP 内封装,让外层地址负责隧道这段路,内层地址继续描述原来通信的两端。外地代理发往归属代理时,外层源地址是外地代理的转交地址,外层目的地址是归属代理;里面的数据仍来自移动节点的归属地址。

于是,访问网络看到的是从本地合适位置发出的隧道包。归属代理收到后去掉外层,再处理里面的原始通信。这个设计并没有证明每一个网络都接受这种封装,只是让源地址与所在拓扑重新对上。

封装也不是加密。多一个头部,不会自动让内容保密。内层包亦不能笼统说成“每一位都完全不动”,因为作为转发的一部分,TTL 等字段可能变化。保存通信端点与保存整包字节,是不同的承诺。

谁来包裹,决定哪些包会回去

RFC 3024 给外地代理场景规定了两种交付方式。直接交付要求移动节点把外地代理当作默认路由器,先发送未封装的数据。外地代理识别需要反向隧道处理的流量,再加上外层包头送回归属代理。这种方式支持单播,但不提供选择性反向隧道。

另一种方式由移动节点先作封装,明确把包交给外地代理。代理拆开这一层,再封装成发往归属代理的包。这里容易讲错一个细节:移动节点到外地代理的本地外层包,源地址仍是移动节点的归属地址。不能把下一段才使用的转交地址,提前放到这一段上。

为什么值得多做一次包装?因为这种方式让移动节点能够表示选择。协商使用封装交付之后,外地代理不得把该节点未封装的数据也一并送进反向隧道,而应按普通转发处理。节点可以尝试访问当地可达的资源,而不必先把每一个包都送回归属网络。

当地打印机是容易理解的例子。打印请求不应仅因设备具有远处的归属地址,就注定绕回归属代理。不过,普通转发仍受路由和访问策略约束;规范没有为打印机的可达性作保证。它给出的是一种明确选择,而不是免除所有限制的通行证。

广播和组播经外地代理反向传送时也需要封装交付。由此可见,两种方式不是同一个功能的两种随意写法:它们改变了哪些流量会进入隧道,以及谁有能力作这项选择。

一次注册,不能代表整条路

代理通告中的 T 位表示提供反向隧道能力,注册请求中的 T 位表示节点要求使用。通告、请求、受理和数据转发,依次回答不同问题。看见通告并不等于请求已经被接受,请求被接受也不等于发出的数据已经通过后续网络。

RFC 3024 特别提醒,一次不支持反向隧道的注册失败,可能在清掉 T 位后变成成功。但若当前环境正需要反向隧道才能让数据通过源地址过滤,这个“成功”对实际通信仍可能没有用。退回较少功能不总是恢复服务,有时只是把明确的拒绝变成稍后才显现的失败。

封装交付通过类型130、长度为零的扩展提出;没有这个扩展,意味着请求直接交付。它不能与清零的 T 位搭配使用,并在认证扩展之间有规定的位置。外地代理消费这个本地交付选择,不把它继续转给归属代理。协商对象并不是“全网都支持某种包”,而是这几个角色之间具体要怎样交付。

1998年的文本要求提供反向隧道的外地代理同时实现两种方式;2001年的修订保留直接交付为必须,把封装交付改为推荐。错误码79使“不支持所选交付方式”可以被明确表达。如今的 IANA Mobile IP 登记表 也列明了这项分配。旧规范正文里残留的一句“79尚未分配”,不能压过同一文档后面的分配说明和现行登记。

距离检查,不是邻居的身份证

允许外地代理替人把数据送回归属代理,也产生了冒用这条路径的风险。RFC 3024 要求注册请求使用255的 TTL,外地代理检查收到的值仍为255。经过 IP 路由器转发的请求会损失 TTL,因此不能轻易装成来自同一链路的请求。

这个办法限制的是来自链路之外的某类注册劫持,不是对本地发送者的密码学认证。同一链路上的攻击者并未因此消失。历史规范中的认证安排还需独立处理,不能由一个最大 TTL 值代替。

归属代理也不应只要看见一个隧道包就替它转发。规范要求实现绑定检查,并建议默认启用:外层来源要符合已登记的转交地址,内层来源要符合移动节点的归属地址,封装方式也要与协商一致。没有相应绑定或方式不符时,规定的处理是丢弃,而不是猜测对方可能是谁。

绑定更新的描述还有一处已核实的 RFC 3024 技术勘误:原文把注册请求写成了注册回复。修正消息方向看似细小,却关系到究竟依据哪个输入改变状态。历史阅读若只摘取一行,很容易把流程讲反。

私有地址,并没有因此变成全球唯一

RFC 3024 的主体假定公共的地址空间,附录才讨论受约束的不同地址空间安排。外地代理与归属代理仍须在外层路径上相互可达,内层地址也须在相关通信范围里有正确含义。一个包裹不能替所有地址空间自动建立对应关系。

在特定配置中,不同归属代理背后可以重复使用私有归属地址。外地代理必须结合归属代理、转交地址及移动节点的上下文分辨数据;面向本地节点时,已建立的链路层关联尤其重要。相关安全章节要求可靠的链路层身份,不推荐在未经认证的共享以太网上直接套用这种安排。

2010年的 RFC 5944 仍在入口过滤问题下引用反向隧道。延续下来的不是“所有路径都回家”的教条,而是一种职责分离:归属地址可以继续服务于端点连续性,当前位置可以用另一个外层地址说明,接入边界仍保留自己的接纳条件。

这段历史的价值也在它没有声称解决的事情里。RFC 3024 明确不提供普遍的防火墙穿越方案。回到归属代理,换来的是一个在特定条件下可解释的出口,不是对整张网络的支配权。