Ipsec Nat-Traversal

IPsec(IP security)协议族是IETF制定的一系列协议,它为IP数据报提供了高质量的、可互操作的、基于密码学的安全性。特定的通信方之间在IP层通过加密与数据源验证等方式,来保证数据报在网络上传输时的私有性、完整性、真实性和防重放。

IPsec作为一种重要的安全技术得到越来越广泛的应用,但是客户网络边缘大量使用的NAT地址转换操作可能影响到IPsec的正常操作。目前,NAT和IPsec之间存在的不兼容性问题主要可以分为以下三类:

l           IP地址和端口不匹配的问题

l           IPsec不能验证NAT报文的问题

l           NAT超时影响IPsec的问题

在IKE野蛮模式的基础上实现NAT穿越,很好地解决了此问题。

为了使IKE支持目前广泛应用的通过ADSL及拨号方式构建VPN的方案中的特殊情况――即局端设备的IP地址为固定分配的,用户端设备的IP地址为动态获取的情况,在IKE阶段的协商模式中增加了IKE野蛮模式,它可以选择根据协商发起端的IP地址或者ID来查找对应的身份验证字,并最终完成协商。IKE野蛮模式相对于主模式来说更加灵活,能够支持协商发起端为动态IP地址的情况。

在IPsec/IKE组建的VPN隧道中,若存在NAT网关设备,且NAT网关设备对VPN业务数据流进行了NAT转换的话,则必须配置IPsec/IKE的NAT穿越功能。该功能删去了IKE协商过程中对UDP端口号的验证过程,同时实现了对VPN隧道中NAT网关设备的发现功能,即如果发现NAT网关设备,则将在之后的IPsec数据传输中使用UDP封装(即将IPsec报文封装到IKE协商所使用的UDP连接隧道里)的方法,避免了NAT网关对IPsec报文进行篡改(NAT网关设备将只能够修改最外层的IP和UDP报文头,对UDP报文封装的IPsec报文将不作修改),从而保证了IPsec报文的完整性(IPsec数据加密解密验证过程中要求报文原封不动地被传送到接收端)。目前仅在IKE野蛮模式下支持NAT穿越,主模式下不支持。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

另一篇:

1. 前言
NAT 技术和IPsec 技术的应用都非常广泛。但从本质上 来说,两者是存在着矛盾的。

1.IPsec的角度上说,IPsec要保证数据的安全,因此它会加密和校验数据。
2.NAT的观点来看,为了完成地址转换,势必会修改IP地址。

IPSec提供了端到端的IP通信的安全性,但在NAT环境下对IPSec的支持有限。AH协议是肯定不能进行NAT的了,这和AH设计的理念是相违背的无论传输模式还是隧道模式,AH都会认证整个数据包。并且AH还会认证位于AH头之前的IP 头。当NAT 设备修改了IP 头之后,IPSec 就会认为这是对数据包完整性的破坏,从而丢弃数据包。因此AH是不可能和NAT 在一起工作的。);
ESP协议传输模式也不能进行nat穿越,因为TCP/UDP的验证不能通过。
ESP协议 隧道模式在NAT环境下最多只能有一个VPN主机能建立VPN通道,无法实现多台机器同时在NAT环境下进行ESP通信。 关于IPSec在NAT环境下的需求问题在RFC3715中进行了描述。
NAT穿越(NAT Traversal,NAT-T)就是为解决这个问题而提出的,在RFC3947,3948中定义,在RFC4306中也加入了NAT-T的说明,但并没废除RFC3947,3948,只是 不区分阶段1和阶段2该方法将ESP协议包封装到UDP包中(在原ESP协议的IP包头外添加新的IP头和UDP头),使之可以在NAT环境下使用,这样在NAT的内部网中可以有多个IPSec主机建立VPN通道进行通信。

2. IKE协商使用UDP封装
RFC3947主要描述如何检测是否存在NAT设备,并如何在IKE中协商使用UDP来封装IPSec数据包。
2.1 检测
功能是检测通信中是否存在NAT设备和对方是否支持NAT-T。
正常的IKE协商使用的UDP包的源和目的端口都是500,如果存在NAT设备,大多数情况下该UDP包的源端口部分会改变,只有少数情况不改。接收方如果发现UDP源端口不是500,那可以确定数据是经过了NAT设备。 另外,确定NAT的位置也是重要的,在检测对方失效(DPD)时,应该尽量由在NAT设备后面的一方主动进行DPD探测,而从另一方探测有可能会失败。
检测对方是否支持NAT-T是通过交换vendor ID载荷来实现的,如果自身支持NAT-T,在IKE开始交互就要发送这种载荷,载荷内容是“RFC 3947”的MD5值,也就是十六进制的“4a131c81070358455c5728f20e95452f”。
判断是否在NAT设备后面是通过发送NAT-D(NAT-Discovery)载荷来实现的,载荷内容是IP地址和UDP端口的HASH值,NAT-D载荷格式如下,载荷类型值是20:
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
+---------------+---------------+---------------+---------------+
| Next Payload | RESERVED      | Payload length                |
+---------------+---------------+---------------+---------------+
~                 HASH of the address and port                  ~
+---------------+---------------+---------------+---------------+

HASH值的计算方法如下,具体HASH是根据协商来确定的:
        HASH = HASH(CKY-I | CKY-R | IP | Port)
CKY-I和CKY-R是协商发起方和响应方的cookie。
协商中双方各自至少要发送两个NAT-D载荷,第一个载荷是对方的地址和端口的HASH,后面的载荷是自己的地址和端口,如果本地有多个地址,则要发送多个载荷,包括所有地址和端口的HASH。对方接收到载荷后重新根据收到的包的实际地址端口来计算HASH值后进行比较,就可以知道是否有NAT设备以及哪一方在NAT设备之后了。
有些的NAT设备具有端口固定的功能 ,也就是进行NAT转换后只改变地址而不改变端口,而且针对IKE通信使用cookie来区分内部各个IPSec设备的IKE连接,后续IKE协商如果继续用500端口协商就会出现问题。 对于这类设备,解决方法是改变IKE协商端口从500到4500,因为这些设备只对500端口进行特殊处理而不对4500端口处理 Moving IKE fromport 500 to port 4500 is known as port floating )。在协商时,发现了自己在NAT设备之后的一方立即要将协商端口从500改为4500,源和目的端口都是4500,此时协商数据包格式为:
   IP UDP(4500,4500) <non-ESP marker> HDR*, IDii, [CERT, ] SIG_I
其中“non-ESP marker”为4字节,在后面介绍其值。
接收方接收此包解密并认证通过后,要改变自己的状态将原来处理500端口状态改为处理4500端口,后续的协商过程都使用4500端口进行,以后500端口收到的不是新协商的包都将被丢弃,协商过程为:
   Initiator                           Responder
   ------------                        ------------
   UDP(500,500) HDR, SA, VID -->
                                       <-- UDP(500,X) HDR, SA, VID
   UDP(500,500) HDR, KE, Ni,
       NAT-D, NAT-D -->
                                       <-- UDP(500,X) HDR, KE, Nr,
                                               NAT-D, NAT-D
   UDP(4500,4500) HDR*#, IDii,
       [CERT, ]SIG_I -->
                                       <-- UDP(4500,Y) HDR*#, IDir,
                                               [ CERT, ], SIG_R
如果支持NAT-T,在ID载荷中的端口值要设置为0。

2.2 UDP封装协商
UDP封装方式有两种,一种是UDP通道模式封装,一种是UDP传输模式封装,取值为:
   UDP-Encapsulated-Tunnel         3
   UDP-Encapsulated-Transport      4
当发现存在NAT设备后,就要选择这两者模式中的一种,而一般正常的通道模式封装和传输模式封装取值分别为1和2。在协商封装模式时,提议一方或者是提议NAT模式下的3、4,或者是提议非NAT下的1、2,而不应该同时提议1、2、3、4这四种模式。
由于在计算TCP/UDP校验和的时候要用到IP地址部分,因此需要知道对方的实际原始地址值,因此协商时双方要发送各自的原始地址,使用NAT-OA (NAT Original Address)载荷进行发送。对应发起方来说,NAT-OA载荷中的地址就是自己实际地址和对方的公网地址,而对于响应方来说,NAT-OA载荷中的对方的公网地址和自己的实际地址。
NAT-OA载荷格式为,这种载荷的类型为21:
   1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
+---------------+---------------+---------------+---------------+
| Next Payload  | RESERVED      | Payload length                |
+---------------+---------------+---------------+---------------+
| ID Type       | RESERVED      | RESERVED                      |
+---------------+---------------+---------------+---------------+
|           IPv4 (4 octets) or IPv6 address (16 octets)         |
+---------------+---------------+---------------+---------------+
其中ID Type只能为ID_IPV4_ADDR或者ID_IPV6_ADDR,保留字段值都要置0。

值得注意的是只是在传输模式下需要传NAT-OA载荷,但通道模式下就没必要传了,具体原因看下节UDP封装方法后再说明。

交换过程如下:
   Initiator                           Responder
   ------------                        ------------
   HDR*, HASH(1), SA, Ni, [, KE]
       [, IDci, IDcr ]
       [, NAT-OAi, NAT-OAr] -->
                                       <-- HDR*, HASH(2), SA, Nr, [, KE]
                                                 [, IDci, IDcr ]
                                                 [, NAT-OAi, NAT-OAr]
   HDR*, HASH(3) -->
3. UDP封装通信数据
RFC3948描述如何对ESP包进行UDP封装和解封装,主要面向实际的通信数据处理。
封装ESP包的UDP包所用的端口和IKE协商的端口是相同的,一般都是4500,这样NAT设备也不需要处理两个端口了。 区分一个UDP封装包的是IKE协商数据还是实际ESP数据是根据ESP头中的SPI字段来进行的,SPI为0表示是IKE数据,否则为实际ESP数据。
3.1. UDP封装ESP包格式
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        Source Port            |      Destination Port         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Length              |           Checksum            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      ESP header [RFC4303]                     |
~                                                               ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
所定义的 UDP头是由RFC768定义的标准UDP头,源端口和目的端口都必须是相同的,校验和字段应该设为0,ESP本身有完整性认证功能,不需要UDP的校验和,ESP头的最开始4个字节是SPI字段,该字段绝不能是0。

因此传输模式下,一个TCP上层包被封装为:
            应用ESP/UDP之前
       ----------------------------
  IPv4 |orig IP hdr  |     |      |
       |(any options)| TCP | Data |
       ----------------------------
            应用ESP/UDP之后
       -------------------------------------------------------
  IPv4 |orig IP hdr  | UDP | ESP |     |      |   ESP   | ESP|
       |(any options)| Hdr | Hdr | TCP | Data | Trailer |Auth|
       -------------------------------------------------------
                                 |<----- encrypted ---->|
                           |<------ authenticated ----->|

数据包经过NAT设备后,只修改外部IP头和UDP头中的数据,TCP头中的数据是不可能修改的(实际NAT设备也根本看不到TCP头数据,因为是被ESP加密了的)。经过ESP/UDP协议解封装处理,到达应用层时的数据包剩下修改后的外部IP头和原始TCP头,因此TCP头中的校验和必须和修改后的IP头中的地址匹配,否则在应用层看来就是错误的。因此IKE时必须交换NAT-OA载荷,使ESP/UDP处理层知道如何修改TCP校验和,而对于上层的UDP协议,可以简单的将校验和置0即可。

通道模式下数据封装为:
            应用ESP/UDP前
       ----------------------------
  IPv4 |orig IP hdr  |     |      |
       |(any options)| TCP | Data |
       ----------------------------
            应用ESP/UDP后
     --------------------------------------------------------------
IPv4 |new h.| UDP | ESP |orig IP hdr  |     |      |   ESP   | ESP|
     |(opts)| Hdr | Hdr |(any options)| TCP | Data | Trailer |Auth|
     --------------------------------------------------------------
                        |<------------ encrypted ----------->|
                  |<------------- authenticated ------------>|

内部IP头也是ESP载荷的一部分,因此TCP校验和已经是根据内部IP头计算的了,因此在IKE时不用交换NAT-OA载荷,解封处理只需要按顺序依次解开UDP和ESP就能还原原始数据包。
 
3.2 UDP封装IKE包格式
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Source Port            |      Destination Port         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Length              |           Checksum            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Non-ESP Marker                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      IKE header [RFC4306]                     |
   ~                                                               ~
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
源和目的端口是4500;UDP校验和可以计算也可以不用设,没作限定,但该字段绝不能作为判断包类型的依据;Non-ESP Marker字段必须设置为0,该字段位置等价于ESP头的SPI字段,因此该字段为0表示是IKE数据,不为0表示是ESP数据。
3.3. NAT连接保持包
NAT连接保持包是为了检查NAT映射是否一直存在,或者是在没有其他包发送给对方是发送此包用来保持连接,但接收到该包不能用作连接有效的判据。
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Source Port            |      Destination Port         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Length              |           Checksum            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    0xFF       |
   +-+-+-+-+-+-+-+-+
源和目的端口是4500;UDP校验和字段应该设为0;数据部分就一个字节0xff,接收方不进行回应。

4. 冲突
在某些情况下NAT-T会导致一些冲突,如在通道模式下,对于下面的拓扑结构:
     +----+            \ /
     |    |-------------|----\
     +----+            / \    \
       A             NAT 1     \
                                \
    10.1.2.3                     \
     +----+            \ /        \       +----+          +----+
     |    |-------------|----------+------|    |----------|    |
     +----+            / \                +----+          +----+
       B             NAT 2             远程VPN网关       远程服务器
    10.1.2.3
A和B具有相同的内部IP,都通过NAT后访问远程服务器(这个远程服务器跟A,B都不是同一个网络),但对于远程VPN网关和服务器来说,解开包后看到的内部IP都是相同的,因此就不知道该将数据发给谁,这时就会发生冲突。
解决方法是VPN通信的内部IP完全由VPN网关来进行分配,而不是本地设置,这样VPN网关就能区分不同的远程VPN客户的访 问,在IKEv2(RFC4306)中已经包括了内部IP分配的内容。

传输模式下更容易发生问题,对于下面的拓扑结构:

             +----+
             |    |
             +----+ \
               A     \
            10.1.2.3 \
                       \
             +----+    \ /                +----+
             |    |-----+-----------------|    |
             +----+    / \                +----+
                B     NAT                 服务器
            10.1.2.4 /
                     /
                    /
            +----+ /
            |    |/
            +----+
              C
           10.1.2.5
A和B通过VPN通道跟服务器连接,如果都访问服务器上的相同服务,由于传输模式没有原始IP头信息,因此服务器包无法区分包到底是来自A还是B,因此不能确定使用哪个SA来加密通信;如果增加第3个客户端C,使用的是明文访问服务器,服务器将更抓瞎了。解决方法还是需要用通道模式进行通信。
5. 结论
NAT-T技术解决了IPSec在NAT环境下的使用异常的问题,虽然也可能会引起一些新问题,但都是可以解决的。
---------------------------------------------------------------------------------------------------------
 
在建立IPsec通道时,如果通道路径上有NAT设备,也不会影响第一阶段的IKE SA的协商和第二阶段IPSec SA的协商,因为通常将IKE的数据包封装在UDP数据包中。 但是,在完成第二阶段协商后, IPsec数据包上的NAT会导致通道失败,(也就是说IPsec的通道可以建立,但是真正的User的数据无法传输)
      原因可能有多个,但是最关键的原因就是:
      1. 对于IPsec-ESP来说,NAT设备不能找到要做端口转换的port和src IP address的位置(因为它已经被加密了)
      2.对外IPsec-AH协议,NAT设备虽然可以看到port和Src IP and Dst IP address,但不可以修改,如果一修改整个IPsec数据包的完整性验证就会失败。IPsec 数据包就会被丢弃。

      二 IPsec和NAT和平共处的解决方法:NAT-T
      在 IPsec第一阶段IKE SA协商过程中,两端支持NAT-T的VPN 设备会在IPSec 协商路径上检测是否有NAT设备,
      1. 如果没有NAT设备,IPSec数据包正常发送,接着进入IKE第二阶段
      2. 如果监测到NAT设备,就给要发送出去的IPSec数据包再添加一层UDP封装。可以解决认证检查失败的问题。NAT设备将其作为 UDP 封包处理,更改UDP 包头中的源端口,不修改 AH 或 ESP 中的 SPI 包头。对端的VPN设备将剥开UDP 层并处理 IPSec 封包,这样处理就会通过认证检查,因为对认证过的内容并没有做任何更改。
      1.启用NAT-T之后,也只要两端的VPN Gateway之间存在NAT设备时才会激活。
      2.要使用NAT-T功能,两端的VPN Peer都必须支持。

下面是ipsec启动日志
两端都位于网关之后,其中接收端添加了两个内网网段192.168.3.0/24和192.168.0.0/24,发起端只添加了一个内网网段192.168.1.0/24。
发起端日志:
added connection description "shiyantoxili/1x1"
added connection description "shiyantoxili/1x2"
initiating all conns with alias='shiyantoxili' 
"shiyantoxili/1x2" #1538: initiating Aggressive Mode #1538, connection "shiyantoxili/1x2"
"shiyantoxili/1x2" #1538: received Vendor ID payload [Dead Peer Detection]
"shiyantoxili/1x2" #1538: received Vendor ID payload [RFC 3947] method set to=115 
"shiyantoxili/1x2" #1538: Aggressive mode peer ID is ID_FQDN: '@xili'
"shiyantoxili/1x2" #1538: NAT-Traversal: Result using draft-ietf-ipsec-nat-t-ike (MacOS X): both are NATed
"shiyantoxili/1x2" #1538: transition from state STATE_AGGR_I1 to state STATE_AGGR_I2
"shiyantoxili/1x2" #1538: STATE_AGGR_I2: sent AI2, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}
"shiyantoxili/1x2" #1538: Dead Peer Detection (RFC 3706): enabled
"shiyantoxili/1x1" #1539: initiating Quick Mode PSK+ENCRYPT+TUNNEL+PFS+UP+AGGRESSIVE+IKEv2ALLOW+SAREFTRACK {using isakmp#1538 msgid:2954fd80 proposal=3DES(3)_192-SHA1(2)_160 pfsgroup=OAKLEY_GROUP_MODP1024}
"shiyantoxili/1x2" #1540: initiating Quick Mode PSK+ENCRYPT+TUNNEL+PFS+UP+AGGRESSIVE+IKEv2ALLOW+SAREFTRACK {using isakmp#1538 msgid:236ba11e proposal=3DES(3)_192-SHA1(2)_160 pfsgroup=OAKLEY_GROUP_MODP1024}
"shiyantoxili/1x1" #1539: Dead Peer Detection (RFC 3706): enabled
"shiyantoxili/1x1" #1539: transition from state STATE_QUICK_I1 to state STATE_QUICK_I2
"shiyantoxili/1x1" #1539: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode {ESP=>0xc417d95b <0x3f4913c4 xfrm=3DES_0-HMAC_SHA1 NATOA=none NATD=113.91.86.106:4500 DPD=enabled}
"shiyantoxili/1x2" #1540: Dead Peer Detection (RFC 3706): enabled
"shiyantoxili/1x2" #1540: transition from state STATE_QUICK_I1 to state STATE_QUICK_I2
"shiyantoxili/1x2" #1540: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode {ESP=>0xc417d95c <0x3f4913c5 xfrm=3DES_0-HMAC_SHA1 NATOA=none NATD=113.91.86.106:4500 DPD=enabled}

接收端日志:
packet from 113.104.226.246:500: received Vendor ID payload [Dead Peer Detection]
packet from 113.104.226.246:500: received Vendor ID payload [RFC 3947] method set to=115 
packet from 113.104.226.246:500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-03] meth=108, but already using method 115
packet from 113.104.226.246:500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-02_n] meth=106, but already using method 115
packet from 113.104.226.246:500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-02] meth=107, but already using method 115
packet from 113.104.226.246:500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-00]
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: Aggressive mode peer ID is ID_FQDN: '@shiyan'
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: responding to Aggressive Mode, state #404, connection "xilitoshiyan/1x1" from 113.104.226.246
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: enabling possible NAT-traversal with method RFC 3947 (NAT-Traversal)
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: transition from state STATE_AGGR_R0 to state STATE_AGGR_R1
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: STATE_AGGR_R1: sent AR1, expecting AI2
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: NAT-Traversal: Result using draft-ietf-ipsec-nat-t-ike (MacOS X): both are NATed
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: transition from state STATE_AGGR_R1 to state STATE_AGGR_R2
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: new NAT mapping for #404, was 113.104.226.246:500, now 113.104.226.246:4500
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: STATE_AGGR_R2: ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=oakley_3des_cbc_192 prf=oakley_sha group=modp1024}
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: the peer proposed: 192.168.3.0/24:0/0 -> 192.168.1.0/24:0/0
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: responding to Quick Mode proposal {msgid:2954fd80}
"xilitoshiyan/1x1"[1] 113.104.226.246 #405:     us: 192.168.3.0/24===192.168.0.188[@xili]
"xilitoshiyan/1x1"[1] 113.104.226.246 #405:   them: 113.104.226.246<0.0.0.0>[@shiyan]===192.168.1.0/24
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: keeping refhim=4294901761 during rekey
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: transition from state STATE_QUICK_R0 to state STATE_QUICK_R1
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: STATE_QUICK_R1: sent QR1, inbound IPsec SA installed, expecting QI2
"xilitoshiyan/1x1"[1] 113.104.226.246 #404: the peer proposed: 192.168.0.0/24:0/0 -> 192.168.1.0/24:0/0
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: responding to Quick Mode proposal {msgid:236ba11e}
"xilitoshiyan/2x1"[1] 113.104.226.246 #406:     us: 192.168.0.0/24===192.168.0.188[@xili]
"xilitoshiyan/2x1"[1] 113.104.226.246 #406:   them: 113.104.226.246<0.0.0.0>[@shiyan]===192.168.1.0/24
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: keeping refhim=4294901761 during rekey
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: transition from state STATE_QUICK_R0 to state STATE_QUICK_R1
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: STATE_QUICK_R1: sent QR1, inbound IPsec SA installed, expecting QI2
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: transition from state STATE_QUICK_R1 to state STATE_QUICK_R2
"xilitoshiyan/1x1"[1] 113.104.226.246 #405: STATE_QUICK_R2: IPsec SA established tunnel mode {ESP=>0x3f4913c4 <0xc417d95b xfrm=3DES_0-HMAC_SHA1 NATOA=none NATD=113.104.226.246:4500 DPD=none}
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: transition from state STATE_QUICK_R1 to state STATE_QUICK_R2
"xilitoshiyan/2x1"[1] 113.104.226.246 #406: STATE_QUICK_R2: IPsec SA established tunnel mode {ESP=>0x3f4913c5 <0xc417d95c xfrm=3DES_0-HMAC_SHA1 NATOA=none NATD=113.104.226.246:4500 DPD=none}

附:openswan代码中流程文档

docs\HACKING\PlutoPacketStory

-*- emacs-wiki -*-
The document describes the steps that a packet goes through when it is
received by pluto.  This is not a state machine, but rather a call graph,
in general each run through the process causes a single state change.

* read_packet()

The packet is received from the network and the origin and destination
address and the ports of the packet are recorded. Based upon the destination
port, a particular interface definition is chosen.

The packet is stored into an object called the "msg_digest"

A single common (statically allocated) msg_digest is used to receive all
packets, if it needs to be saved (not the common case), it is copied.

* process_packet()

process_packet() is the primary function which parses the incoming packet.
In the diagram, this is why all other functions appear to be called from this
function. 

* de-marshal payloads (in_struct)

The first step is to take the packet apart. This is done by the in_struct()
routine, which turns the wire format into a structure, found in md->hdr.

* examine isa_xchg

The first step is to look at the exchange type. Many exchange types are not
supported.  In general each type will cause a new state to be created when
the msgid is different than a different code was done.

* find/create state object

Each type will search for a state object that matches the set of cookies, and
the message id. If no state object is found, a new one may be created.

If the state is not found by the message ID, then we look for state with a
zero message ID. If that is found, then the state is adjusted to now be for
this message ID. 

* determine valid transitions

Once we have a state object, it can determined what are valid transitions
from this state to another state. The selection is typically based upon what
payloads are present in the message. The transition microcode has a bit for
each payload type, and based upon this we determine if there would be a valid
state transition. 

This microcode also then indicates things such as whether or not the message
should be encrypted, and whether or not additional options payloads may appear.

* verify state is not suspended

The state may be suspended. This will occur if there is computation (such as
a Diffie-Hellman exponentiation) occuring or a network lookup is occuring
(DNS). If so, the packet will be dropped. Likely, it is a retransmission
anyway. 

Retransmissions are also detected --- if we have already replied to this
message, then we will have saved the outgoing packet, and it is simply
resent. 

* decrypt packet if appropriate

The message may have been encrypted. The state transition may be valid only
with an encrypted message. These two conditions are compared, and if they
match, then the message is decrypted. 

The resulting new data will have new payloads, and these will be
de-marshalled.
 
* calculate hash if appropriate

Prior to losing track of the newly decrypted message, we calculate 
over the plaintext, which may be used later on to authenticate the message.

* enforce ordering of payloads

Some ordering of payloads is mandated, and without this ordering the message
may not make sense. This is then checked.

* state specific func

The state transition microcode ("smc") will have designated a particular
function handle the state transition.  The function will be passed a pointer
to the pointer to the message digest, and a pointer to the microcode.

The reason a pointer to a pointer is passed is so that the state specific
function can set the message digest to NULL. It will do this in situations
where it needs to keep a copy of the message for later examination by a
continuation function. Since the pointer will now be NULL, the enclosing
read_packet() function will not free the message digest, and a new one will
be allocated for the next packet.

State specific functions are named for the exchange type, and message number
they expect. For instance, [[quick_inI1_outR1]] is part of a QuickMode (aka
"Phase 2") exchange, and is called by the responder when it receives message
I1 in order to prepare the R1 message 

A typical negotiation looks like this:

     [[main_outI1]]
                       ------I1----->
                                       [[main_inI1_outR1]]
                       <-----R1------
     [[main_inR1_outI2]]
                       ------I2----->
                                       [[main_inI2_outR2]]
                       <-----R2------
     [[main_inR2_outI3]]
                       ------I3----->
                                       [[main_inI3_outR3]]
                       <-----R3------
     [[main_inR3]]
         |             PHASE 1 ESTABLISHED            
         | 
         V
     [[quick_outI1]]
                       ------I1----->
                                      [[quick_inI1_outR1]]
                       <-----R1------
     [[quick_inR1_outI2]]
         |             ------I2----->
         |                            [[quick_inI2]]
         |                                 |
         V                                 V
     PHASE 2 ESTABLISHED            PHASE 2 ESTABLISHED


Details about each state transition is covered in additional pages above.

* complete_state_transition()

The state specific function is expected to return one of the following
returns of type stf_status (State Transition Function Status).

** STF_IGNORE

An ignore value means that this message should not cause any change to the
current stat. No further processing is done.

** STF_INLINE

A return of INLINE is a meta value, and means that the state transition has
already been performed.

** STF_SUSPEND

A return of SUSPEND means that the state transition function could not (yet)
complete the state transition. A continuation function (to be called later)
will likely complete the transition.

** STF_FATAL

A return of FATAL means that something is wrong in the configuration of this
connection pluto, and likely that it will be unable to continue processing. 

** STF_INTERNAL_ERROR

An internal error means that a system wide resource is misconfigured, and it
is likely that no connection will succeed.

** STF_FAIL

A simple failure means that the message was not successfully processed. This
could be due to inability to authenticate the message, mismatches in policy,
etc. It may also be due to malicious corruption of the exchange.

** STF_TOO_MUCH_CRYPTO

The message could not be processed at this time because the system is too
busy processing other (more important) messages. The message is dropped, and
retransmission will take care of resending it.

** STF_OK

The message was successfully processed, and the state should be advanced.
The received message is record (in case it is retransmitted), and if this
state requires a response, any response message will then be sent.

*** send_packet()

The send_packet() process actually transmits the reply. It uses the remote
address and port that has been stored in the state structure, since the
NAT-traversal code may have updated these values.

* encrypt packet

The state specific function, if it prepares a reply packet, may need to
encrypt it. This is done in a single function.

* continuation

Many state specific functions require that some work be done: this may
involve one or more DNS or LDAP lookups to retrieve public keys, or may
involve performing lengthy cryptographic operations. In this case, the state
specific function will arrange to have the operation started. A continuation
structure is created when the operation is started, and the state specific
function will return STF_SUSPENDED.

When the asynchronous operation is completed, a continuation function (often
called the _tail function) is called, it is provided with the continuation
structure, and a reply message is fashioned. Typically, the continuation
function will then call complete_state_transition() itself.

http://blog.csdn.net/jianchaolv/article/details/7903882

http://blog.csdn.net/jianchaolv/article/details/8454991

https://tools.ietf.org/html/draft-ietf-ipsec-nat-t-ike-03#page-5

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值