IPsec與NAT穿越

  1. 前言

IPSec提供了端到端的IP通信的安全性,但在NAT環境下對IPSec的支持有限,AH協議不能進行NAT,這和AH設計的理念是相違背的;ESP協議在NAT環境下最多只能有一個***主機能建立***通道,無法實現多臺機器同時在NAT環境下進行ESP通信。關於IPSecNAT環境下的需求問題在RFC3715中進行了描述。

 

NAT穿越(NAT TraversalNAT-T)就是爲解決這個問題而提出的,在RFC39473948中定義,在RFC4306中也加入了NAT-T的說明,但並沒廢除RFC39473948,只是不區分階段1和階段2。該方法將ESP協議包封裝到UDP包中(在原ESP協議的IP包頭外添加新的IP頭和UDP頭),使之可以在NAT環境下使用的一種方法,這樣在NAT的內部網中可以有多個IPSec主機建立***通道進行通信。

 

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-ICKY-R是協商發起方和響應方的cookie

 

協商中雙方各自至少要發送兩個NAT-D載荷,第一個載荷是對方的地址和端口的HASH,後面的載荷是自己的地址和端口,如果本地有多個地址,則要發送多個載荷,包括所有地址和端口的HASH,對方接收到載荷後重新根據收到的包的實際地址端口來計算HASH值後進行比較,就可以知道是否有NAT設備以及哪一方在NAT設備之後了。

 

有些的NAT設備具有端口固定的功能,也就是進行NAT轉換後只改變地址而不改變端口,而且針對IKE通信使用cookie來區分內部各個IPSec設備的IKE連接,後續IKE協商如果繼續用500端口協商就會出現問題。對於這類設備,解決方法是改變IKE協商端口從5004500,因爲這些設備只對500端口進行特殊處理而不對4500端口處理。在協商時,發現了自己在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-TID載荷中的端口值要設置爲0

 

2.2 UDP封裝協商

UDP封裝方式有兩種,一種是UDP通道模式封裝,一種是UDP傳輸模式封裝,取值爲:

  UDP-Encapsulated-Tunnel       3

  UDP-Encapsulated-Transport     4

 

當發現存在NAT設備後,就要選擇這兩者模式中的一種,而一般正常的通道模式封裝和傳輸模式封裝取值分別爲12。在協商封裝模式時,提議一方或者是提議NAT模式下的34,或者是提議非NAT下的12,而不應該同時提議1234這四種模式。

 

由於在計算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字段來進行的,SPI0表示是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頭,源端口和目的端口都必須是相同的,校驗和字段應該設爲0ESP本身有完整性認證功能,不需要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載荷,解封處理只需要按順序依次解開UDPESP就能還原原始數據包。

 

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]               |

  ~                                           ~

  |                                           |

  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 

源和目的端口是4500UDP校驗和可以計算也可以不用設,沒作限定,但該字段絕不能作爲判斷包類型的依據;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     |

  +-+-+-+-+-+-+-+-+

 

源和目的端口是4500UDP校驗和字段應該設爲0;數據部分就一個字節0xff,接收方不進行迴應。

 

4. 衝突

在某些情況下NAT-T會導致一些衝突,如在通道模式下,對於下面的拓撲結構:

 

  +----+         \ /

  |   |-------------|----\

  +----+         / \   \

    A         NAT 1   \

                    \

  10.1.2.3               \

  +----+         \ /     \     +----+       +----+

  |   |-------------|----------+------|   |----------|   |

  +----+         / \           +----+       +----+

    B         NAT 2         遠程***網關     遠程服務器

  10.1.2.3

 

AB具有相同的內部IP都通過NAT後訪問遠程服務器,但對於遠程***網關和服務器來說,解開包後看到的內部IP都是相同的,因此就不知道該將數據發給誰,這時就會發生衝突,解決方法是***通信的內部IP完全由***網關來進行分配,而不是本地設置,這樣***網關就能區分不同的遠程***客戶的訪問,在IKEv2(RFC4306)中已經包括了內部IP分配的內容。

 

在傳輸模式下更容易發生問題,對於下面的拓撲結構:

 

        +----+

        |   |

        +----+ \

          A   \

        10.1.2.3 \

              \

        +----+   \ /           +----+

        |   |-----+-----------------|   |

        +----+   / \           +----+

          B   NAT           服務器

        10.1.2.4 /

              /

            /

        +----+ /

        |   |/

        +----+

        C

      10.1.2.5

 

AB通過***通道和服務器連接,如果都訪問服務器上的相同服務,由於傳輸模式沒有原始IP頭信息,因此服務器包無法區分包到底是來自A還是B的,因此不能確定使用哪個SA來加密通信;如果增加第3個客戶端C,使用的是明文訪問服務器,服務器將更暈頭轉向了。解決方法還是需要用通道模式進行通信。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章