[ipsec] 特别硬核的ike/ipsec NAT穿越机制分析

〇 前言

这怕是最后一篇关于IKE,IPSEC的文字了,由于不能没完没了。html

因此,我一直在想这个标题该叫什么。总的来讲能够将其归纳为:IKE NAT穿越机制的分析。安全

可是,同时它也回答了如下问题:网络

(1)IKE协议交互消息概述。(2)为何IKE除了端口500还用了端口4500 。(3)IKE MOBIKE是什么。app

(4)迷之端口500和迷之端口4500 。(5)IKE/IPsec为何要将端口500换成端口4500。ide

(6)ike/ipsec为何使用了两个端口。ui

另外,本篇的全部内容与讨论仅局限在IKE V2的定义域内。加密

好的,开始。idea

 Author: classic_tongspa

一 IKE消息简述

我也不想简述,可是不述后边的事情说不清楚。并且,若是是最后一篇的话,也但愿可以作一个总结。操作系统

若是有的选的话,我建议你不要读个人这一小节,而是读RFC7296的第一章 。而后进入第二小节。

首先,约定一下概念,IKE交互的两端分别叫作发起端响应端。基本的通讯模式是,发起端发送一个请求报文,响应端回复一个响应报文。

这两个报文在一块儿称为一次交互。一个报文里包含这多个报文段,每一个报文段都有其特别的功能和特别的报文段类型,用以和彼此区分。

 

屡次IKE交互以后,IKE通讯两端将成功(或者失败)创建一个安全的可信信道。这条信道的创建,删除,状态维护即是IKE交互的任务。

信道创建以后通讯任务将交由ESP/AH协议完成。ESP消息承载的通讯信息,依据信道标识(SPI)在可信信道间穿梭。

深刻到协议细节里的话。IKE交互其实创建了两条信道,一条叫IKE SA,一条叫IPSEC SA(child SA)。在这里,咱们将SA理解为信道

的等价物。IKE SA负责信道的可信任性,IPSEC SA负责信道机密性。

 

下面单独讨论IKE SA。

为了获得可信性IKE须要(1)对双方身份进行AUTH(验证)。同时为了完成信道的创建过程还须要(2)帮助IPSEC SA进行秘钥交换。以及

(3)完成自身信道(ike sa)的秘钥交换。(4)其余特性协商。

以上是IKE的要完成的任务,下面基于对以上任务的理解,咱们来看一下IKE的主要交互过程。

先来一张感性的截图,进行一下直观的认识:

 

主要的IKE交互,按照逻辑顺序,有:

1. IKE_SA_INIT (截图中1,2包)

在这个交互里,完成上文提到的功能3),4)。该交互完成以后IKE SA信道便已经成功创建了。

2. IKE_AUTH  (截图中3,4包)

在这个交互中,完成上文提到的功能1)。该交互已是在IKE SA的保护之下进行的了。并完成了对彼此双方信任的创建。

3. CHILD_SA_CREATE (上面的截图中没有,下面的截图中9,10包)

在这个交互中,完成上文提到的功能2)。在此以后便完成了IPSEC SA信道的创建。

从这个时刻开始,即可以开始进行ESP消息(截图中7,8包,由于解密了,他们带有ESP头)的通讯了。可是在实际应用中,在2完成以后,ESP消息交互便已经开始了,是暂时使用的IKE SA的秘钥。

在3完成以后,ESP会切换使用新的秘钥。REKEY也就是秘钥的更新,也是这样的一个过程,使用CHILD_SA_CREATE交互来进行秘钥更新。

4 INFORMATION (截图9,10包)

信道的拆除,探活等其余housekeeping(家务活)任务,都使用该消息完成。

 

简述到此为止,更多内容能够深刻的读上边引用的RFC。下一小节将进入主题NAT穿越。

 

二 端口

再来一张图。咱们惊奇的发现,除了port 500 ,怎么又跑出来一个port 4500 ?尼玛,这到底怎么回事?(为何上面的图都是500? 这个最后的最后,你就懂了。先剧透一下,上图关了MOBIKE特性)

 

 首先,我详细的描述一下这个现象。 咱们前边讨论了,这个IPsec过程分两类报文,一类是IKE报文,一类是ESP报文。而后咱们抛开ESP报文不讨论。如今,这个现象是这样的。除了第一次交互(也就是

前两个包)使用500端口以外。以后的因此报文都使用4500端口进行通讯。

即便是在发送IKE的rekey或reauth时,也使用4500端口。也就是说500端口,后续的报文序列里不再会使用了。如图:

 

接下来,我先说结论,也就是什么状况下什么样的条件会触发这个现象发生。这里边分为两个场景,每一个场景有各自的触发条件,以下:

 

场景A:IKE通讯双方至少有一端处于NAT网关的后边。

1. 当通讯双方检测到彼此都支持NAT穿越。(固然支持,否则这个场景也没有意义。因此,处于该场景下自然就是触发条件。)

这个时候,在第二次交互开始,通讯双方将使用4500端口开始通讯。同时ESP包(一般状况下ESP包是IP承载的)会被封包为UDP承载,并使用4500端口。

场景B:IKE通讯双方之间没有NAT网关的存在。

1. 通讯双方检测到彼此都支持NAT穿越。

2. 通讯双方都启用了MOBIKE特性。(原谅我排版很差,你能够先翻到下面去看看mobike是个啥)

 

场景B下的1,2条件同时知足时,IKE双方将在第二次交互时改用4500端口。由于这两个特性的同时存在,会致使场景B在以后的某个时刻有回落进场景A的可能。

因此,为了防止在忽然落入场景A时着急忙慌的切换端口,还不如一开始就切了。(忘记了出处,好像是在 RFC4555 中提到)

 

因此除了上面的条件,其余状况下,500端口会一直使用。

须要特别说明的是,当使用4500承载的时候,IKE报文头与UDP报文头之间,会插入4个字节的0,用来区分ESP报文和IKE报文。

其余,一样要明确说明的时候,即便在没有出现NAT的状况下,也就是场景B中,4500的报文里一样存在这4个字节的0. 如图留下证据:

 

 图中的两个IP,是个人两个虚拟机,在同一个网段中在host上使用网桥链接。

 

三 WHY

说了这么多,都是前提。我真正想说的,以及总结了这么多知识并编写了整篇内容的所有动机,其实只是要回答这样一个问题:为何要换端口?难道不能一直用500端口么?

坦白的说,(通过了大概有怕是4个小时的研究以后)不知道。我收集并总结了以下两个理由,可是,都不能说服我!

理由一和二是整个思考过程,能够跳过。理由三是正解(我差很少都写完了以后,忽然无心间找到了理由三,因此,写了不能不写,就索性置灰了)

理由一:因为NAT设备的某种限制。

由于,rfc7296里有这样一段话,说NAT设备会对4500进行特殊处理,同时也会对500进行特殊处理。

Port 4500 is reserved for UDP-encapsulated ESP and IKE.  An IPsec
   endpoint that discovers a NAT between it and its correspondent (as
   described below) MUST send all subsequent traffic from port 4500,
   which NATs should not treat specially (as they might with port 500).

咱们知道,500与4500的区别在于500是做为知名端口存在的。总之这里比较含糊。可是做为RFC它给予和我足够多的重视(误导)。

 

理由二:500与4500表明着不一样的抽象含义。

什么意思呢? 就是说做为知名端口(1~1024)和注册端口(1024~49151)每个都不是随便乱用的。必须有明确的定义和正确的使用方法。

因此,若是用500端口来承载ESP/AH包的话,就含糊了500端口的定义。这样的适合是很差的,因此要用4500来单独承载。

思科如是说:这是一个一样困惑于此的人,也提出了这样的问题给思科以后,思科的回答。我只能说,这听起来好像挺对的,但是存在着无力的逻辑支持。

 

另外,也是思科,还有,同时一我的特逗,一直耿耿于怀与为何IKE的源port也必须是500 。以致于由于得不到想要的答案而愤怒。

https://learningnetwork.cisco.com/thread/83219

 

理由三(精华精华精华)

这个,就是强有力的,无懈可击的,我想要的,答案:https://serverfault.com/questions/937763/ipsec-nat-traversal-on-port-4500

The problem is multiplexing IKE and ESP on the same UDP port. To distinguish between the two protocols one or the other has to be marked somehow (otherwise some potentially error-prone heuristic had to be employed).

So continuing on UDP port 500 would have meant to mark the ESP packets as non-IKE packets, in order for the recipient to properly decide whether to process a packet as ESP or hand it to the IKE process. The first two drafts of UDP Encapsulation of IPsec ESP Packets (RFC 3948) actually defined it that way. An all-zero eight byte non-IKE marker in the location where the initiator's IKE SPI is stored in IKE packets was defined as prefix to the actual ESP packet (between UDP header and ESP header).

The problem with that was, of course, that there are usually a lot more ESP packets than IKE packets and imposing an overhead of eight bytes (in addition to the UDP header) to every one of them was not ideal.

The alternative was to mark the IKE packets, which is what version 02 of the draft defined and eventually ended up in the RFC. An all-zero non-ESP marker of four bytes in the location where the SPI is stored in an ESP packet is inserted between UDP and IKE header.

However, that meant port 500 couldn't be used for such packets because all IKE messages (even the first ones) would have to be marked that way, which wouldn't have been backward compatible to IKE/IPsec implementations that didn't support NAT-Traversal. Instead, a separate port is used for UDP-encapsulated ESP and IKE with non-ESP marker. And in order to create a mapping on the NAT before any UDP-encapsulated ESP packets are transmitted (i.e. so inbound traffic can be processed even before any outbound traffic is sent) the switch to port 4500 happens as soon as IKE detects that a NAT is present.
源答复

下面,用个人话翻译一下:

首先咱们知道,当出现NAT场景时,发起端和响应端直接存在着三种报文。

1. 由UDP4500承载的ESP报文。2. 由UDP4500承载的IKE报文。3.由UDP500承载的IKE报文。

而后咱们假设不使用4500端口,而所有使用500端口来承载。以后会发生什么? 首先,NAT设备是没有问题的,对于咱们这里讨论或假设的任何场景。

它均可以处理,并且NAT设备也不关心500是否是知名端口,也不对其进行特殊处理。

好,而后,这三种报文都由UDP 500端口来承载。这个时候操做系统收到了udp 500的包的时候是没有办法区分出它究竟是IKE仍是ESP的。

因而,咱们面临一个选择。

A:让操做系统首先进入IKE报文的处理流程,而后为ESP报文加一个特殊的MARK,从而进行区分,识别到ESP报文。

B:让操做系统首先进入ESP报文的处理流程,而后为IKE报文加一个特殊的MARK,从而进行区分,识别到IKE报文。

 

最终,这个选择里,RFC们选择了B。理由是ESP报文的数量远远多余IKE报文。在每个包上加mark(也就是四个字节的0)做为一种资源消耗。两种陷害择其轻,天然便选择了IKE。

但是,这依然不能解释,为何要用两个端口来作。咱们能够在最开始的两个包里,便加上这个mark。这样的话全部包都使用500端口也是没有问题的。

而后,并不行。由于为了向前兼容,包格式是不能随便改的。因此只能让带mark的ike报文用新的端口,也就是udp 4500,从而将一开始咱们提到的三种报文区分开来。

另外。还能再引伸出一个新的问题:为何不能保持ike的包继续沿用500端口,而只是将UDP封装的esp放在4500端口上?

这样便不须要修改ike的格式(添加四个字节的0)了。

这是由于NAT设备中的端口map关系是须要长期保持的,也就是首选须要NAT内的包使用4500端口触发NAT设备创建映射关系,这样NAT外的设备才可以将ESP包发进来。

设想,若是仍是使用500的IKE报文的话。若是NAT内的设备不主动发送ESP包,NAT设备的map表就创建不起来。外边的ESP包也就没法发送回来。

另外,NAT后的信道须要一个NAT-keepalive包来长期保活。有NAT内的一端发送,从而保证NAT设备中的map不会超时。以下图:

 

 

四 MOBIKE

虽然解了惑。可是挖了的坑不能不填。MOBIKE在这里:https://tools.ietf.org/html/rfc4555

MOBIKE不是摩拜单车。MOBIKE是 mobile ike。是mobility and multihoming ike。

就是IKE支持,发起端的网络移动,也就是IP变化。以及响应端的多个IP Interface切换,其实也是IP变化。

他们并非在第一次交互的时候,就协商好了你们都支不支持,而是由发起端根据是否,是否支持NAT,是否MOBIKE等几个条件来决定是发给500仍是发给4500

而后,将这个mobike消息段放在第二次交互中传输。(我猜这样设计的目的是为了安全考虑?)以下图:

 

 

我看了第三个包的几种状况。包括是否在NAT后,是否支持NAT,是否设置了MOBIKE等。这个message段是否存在都有着不一样的状况。

这里就再也不进行扩展作详细研究了。由于它并不影响本文所要讨论的全部结论。

不过有一点格外要说的是,它会改变SA的IP!咱们回到xfrm与strongswan交互的层面上,再看这个问题。他会致使一个什么样的消息下发呢?

以及xfrm如何兼容,如何作到这个场景下的SA管理呢? 这个话题,有点大。须要做为独立内容进行分析,不在此扩展了。

不过咱们仍是来撇一下这个交互吧,rfc里的一个示意图:(注意看其中的UPDATE_SA_ADDRESSES部分,我揣测它会触发一个SA UPDATE消息?)

 

 

 

五 NAT穿越协商

本小节讲:通讯两端如何知道对方和本身是否是在NAT以后。这里边两方是独自得知的,而不是相互告知。一方要独自回答两个问题,

1. 对面在不在NAT后,2,我在不在NAT后。

再讲这个方法以前,有一个前提,就是在创建链接前每一端都须要被配置一对local IP和remote IP的已知条件。这一对IP就是在该点它所能直接访问(直接到达)的那个两个IP。

 

因此这个探测方法就是,在第一次交互的第一个包中。发起方将上边提到的配置的两个IP都在payload里发给对方。而后,对方会获得4个IP。两个是报文里边的,另两个是承载

这个报文的IP头里的。因此,只要一对比,响应端就回答了上边那两个问题。反方向机制与过程彻底相同,在第一次交互的第二个包里进行。

 

只不过,意思虽然是这个意思,可是在RFC中规定的实现上,略有区别。payload里存的不是IP而是散列值。收到散列值的一方只须要一样对IP头里的IP作散列,而后进行比较是否一至,就能够判断了。这样即达到了目的,也隐藏了对方的真实IP。

这两个报文段类型的名称是:NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP

计算散列的具体方法是: SHA1(SPI + SPI + IP addr + Port number)

详见:https://tools.ietf.org/html/rfc7296#section-2.23

如示例:

 

 

六 报文样式

为了理解直观,总结了几种报文的结构,以下图:

 

其中,须要注意的是,传输模式下TCP报文头中的checksum是错的。由于它保存在加密报文中,因此没法被NAT网关设备修正。这也是为何

IKE必须关心NAT穿越,而不能无视它的缘由之一。

固然,另外一个缘由是非TCP/UDP承载的报文,会被NAPT设备丢掉?(i dont know..)