IPsec與NAT Traversal(NAT-T)

travalsal

背景

IPsec在兩個通信實體之間建立安全的數據傳輸通道, 但它卻與網絡中廣泛存在的NAT設備(以及PAT)有天生的不兼容性(incompatible)。

我們以一個TCP報文爲例來看看在不同IPsec的不同模式(TransportTunnel)和協議(AHESP)下,這種不兼容是如何發生的。

先來看Transport模式

圖-transport

AH協議,由於其Authenticate範圍是整個IP報文,所以如果兩個IPsec之間存在NAT設備,修改了報文IP Header中的地址,就會導致接收方的Authenticate失敗。
ESP協議,其Authenticate返回不包括IP Header,所以接收方的Authenticate會通過,但如果中間的NAT設備修改了IP Header中的地址,理論上後面的TCP checksum也會隨之修改,但這部分在ESP協議中是
加密的,NAT設備沒有辦法修改,所以接收端在TCP接收時會出現checksum校驗失敗。

再來看Tunnel模式

圖-tunnel

AH協議, Tunnel模式和Transport模式沒什麼不同,Authenticate範圍包含了外層IP Header,因此同樣會造成接收方Authenticate失敗。
ESP協議,與Transport模式不同的是,經過NAT設備。內層IP Header並不會改變,所以TCP checksum也不會變化,接收方不會出現checksum校驗失敗。

這樣看起來,ESP-Tunnel似乎成爲了在有NAT設備環境下,唯一可行的協議-模式組合。但即使是這種組合也是有缺點的:它只能支持一對一NAT(NAT設備後面只有一臺內網主機)。在很多組網中,NAT設備通常作爲網關使用,其背後可能有很多臺主機。這時地址轉換就不夠了,它還需要端口轉換,顯然,NAT設備對ESP-Tunnel的報文是無能爲力的,因爲TCP部分已經被加密了,已經沒有端口字段了。
所以,IPsec需要想辦法能繞開NAT設備的影響,也就是進行NAT穿越(NAT-Tranversal)。

UDP-Encapsulate

IPsec採用的辦法是在ESP Header前加上一個UDP Header, 這個方法同時適用於ESP-TransportESP-Tunnel模式。
下圖展示了ESP-Transport下的UDP-Encapsulate過程。

udp-encap

UDP Header是有端口字段的,有了端口,NAT設備便可以進行端口轉換。RFC3948中規定UDP Header中的端口要使用和IKE協商時相同的端口號,這個端口號在RFC3947中規定爲4500.

在下面這樣的拓撲中,NAT設備背後有兩臺內網主機,它們都與Server建立IPsec連接。

pat

Host 1Host 2發出的IPsec報文都附加了一個UDP HeaderNAT網關替換該報文的Source IPSource Port

還有一個問題, 對於ESP-Transport模式, 內層TCP報文的checksum校驗的問題如何解決呢?要知道,經過NAT設備之後,報文的IP地址發生了變化,這勢必導致接收端校驗失敗。IPsec採用的方法是在IKE協商時,就將自己原始IP地址信息發給對端,這樣Server在解密出TCP報文後,可以根據這個信息修正checksum

NAT-T 協商過程

IPsec的通信實體之間需要在IKE時完成協商才能使用上面UDP-Encapsulate,完成NAT-T

IKEPHASE1

  • 雙方探測出雙方都支持NAT-T
  • 雙方探測出了報文傳輸路徑上存在NAT設備

IKEPHASE2

  • 雙方協商NAT-T的封裝模式,UDP-Encapsulated-Tunnel還是UDP-Encapsulated-Transport
  • (UDP-Encapsulated-Transport)模式向對方發送自己的原始IP地址, 讓對方可以據此修正後續TCP報文的checksum

爲了更好的說明我用虛擬機搭建了下面這個拓撲,用來展示IPsecNAT-T協商過程

圖-topo

其中AliceCarol上運行Strongswan, 而Moon作爲NAT設備。配置IPsecTransport模式,使用IKEv1進行協商

探測支持 NAT-T

IPsec的兩端在PHASE1的消息1和消息2中會通過交換vendor ID payload來向對方通告自己支持NAT, 其內容正是字符串"rfc3947"

圖msg1

探測是否存在 NAT

IKE PHASE1的消息3和消息4,通信雙方會交換自己的和自己眼中對方的IPPort的哈希值,如果中間存在NAT設備,則該值一定與該報文本身的IPPort計算出的值不一致。

圖msg3

改變端口從500到4500

IKE PHASE1的前4個消息都是使用Sport=Dport=500進行通信。但當探測到NAT設備存在時,作爲InitiatorAlice就再消息5需要將端口切換到Sport=Dport=4500, 作爲ResponderCarol在收到該消息後,如果解密成功,也會使用新的4500端口

圖Msg4500

在此之後,後續的IKE PHASE2和業務流量都會使用4500端口進行UDP-Encapsulate。爲了與業務流量進行區分,IKE階段的流量緊隨UDP Header後的是一個32bit全爲0的Non-ESP Marker (業務流量的這個地方是填寫的是非零的SPI)

圖NonESP

內核相關實現

內核使用xfrm框架完成IPsec報文收發功能。普通情況下, IP根據協議字段分流IPsec報文和TCP UDP報文。

圖

NAT-T場景中,IPsec爲報文進行了UDP-Encapsulate,那麼,接收端看到的就是一個UDP報文了,會調用udp_rcv()進行報文接收。那麼此時又如何進入xfrm框架呢?

答案是:Strongswan通過設置UDP套接字UDP_ENCAP選項,內核爲套接字綁定一個回調函數xfrm4_udp_encap_rcv()

int udp_lib_setsockopt(struct sock *sk, int level, int optname,
               char __user *optval, unsigned int optlen,
               int (*push_pending_frames)(struct sock *))
{
    // code omitted
    switch (optname) {
        case UDP_ENCAP:
        switch (val) {
            case 0:
            case UDP_ENCAP_ESPINUDP:
            case UDP_ENCAP_ESPINUDP_NON_IKE:
                up->encap_rcv = xfrm4_udp_encap_rcv;
        // code omitted
    }
}

而在udp_rcv()接收過程中,最終會調用到該回調函數

圖decap

REF

RFC 3947 Negotiation of NAT-Traversal in the IKE
RFC 3948 UDP Encapsulation of IPsec ESP Packets

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