浅析NAT

NAT基本概念

NAT(network address translation),NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址提供公网可达性和上层协议的连接能力。

对于有Internet访问需求而内部又使用私有地址的网络,在出口位置部署NAT网关,在报文离开私网进入Internet时,将源IP替换为公网地址,通常是出口设备的接口地址。一个对外的访问请求在到达目标以后,表现为由本组织出口设备发起,因此被请求的服务端可将响应由Internet发回出口网关。出口网关再将目的地址替换为私网的源主机地址,发回内部。这样一次由私网主机向公网服务端的请求和响应就在通信两端均无感知的情况下完成了。依据这种模型,数量庞大的内网主机就不再需要公有IP 地址了。

注意
网络访问只能先由私网侧发起,公网无法主动访问私网主机

NAT常见类型

NAT类型是由映射类型过滤方式组合而成的,有如下四种组合方式:

  • NAT映射:指NAT设备对内网主动发到外网的报文进行映射。当内网主机向外网主机发起访问时,NAT设备会建立内网Endpoint和外网Endpoint之间的映射关系表,并根据该映射关系将报文的内网Endpoint转换成外网Endpoint转发出去。

  • NAT过滤:指NAT设备对外网主动发到内网的报文进行过滤。为了防止内网主机受到攻击,NAT设备会对外网主动发到内网的报文进行过滤,即过滤非法报文,转发正常通信报文。

NAT映射类型

NAT映射类型包括三种:EIM、ADM和APDM。假设内网主机Host A的内网Endpoint为(X,x),经过NAT映射后的外网Endpoint为(Y,y)。外网Host B的Endpoint为(M,m),外网Host C的Endpoint为(N,n)。

  • EIM(Endpoint-Independent Mapping,外部地址无关映射):同一个内网Endpoint发送到任何外部网络的报文,NAT映射后的结果相同。如图所示,对于内网Endpoint(X,x),NAT映射后的外网Endpoint均为(Y,y)。 image.png

  • ADM(Address-Dependent Mapping,外部地址相关映射):同一个内网Endpoint发送到外部网络中相同IP地址、任意端口号的报文,NAT映射后的结果相同。如图所示,对于内网Endpoint(X,x)访问Host B的报文,NAT映射后的外网Endpoint为(Y1,y1);内网Endpoint(X, x)访问Host C的报文,NAT映射后的外网Endpoint为(Y2,y2)。只要M=N,无论m和n是否相同,都有Endpoint(Y1,y1)=Endpoint(Y2,y2)。 image.png

  • APDM(Address and Port-Dependent Mapping,外部地址和端口相关映射):同一个内网Endpoint发送到外部网络中的同一个外网Endpoint,NAT映射后的结果相同。如图所示,对于内网Endpoint(X,x)访问Host B的报文,NAT映射后的外网Endpoint为(Y1,y1);内网Endpoint(X,x)访问Host C的报文,NAT映射后的外网Endpoint为(Y2,y2)。只有当M=N,且m=n时,才有Endpoint(Y1, y1)=Endpoint(Y2, y2)。 image.png

NAT过滤类型

NAT过滤方式包括三种:EIF、ADF和APDF。假设内网主机Host A的内网Endpoint为(X,x),经过NAT映射后的外网Endpoint为(Y,y)。外网Host B的Endpoint为(M,m),外网Host C的Endpoint为(N,n)。

  • EIF(Endpoint-Independent Filtering,外部地址无关过滤):对于内网Endpoint(X,x),只要它曾经向外网发送过数据,外网主机就可以获取到NAT映射后的外网Endpoint(Y,y)。那么,对于任意外部网络的主机发送到Endpoint(Y,y)的报文,NAT设备都会进行地址转换并转发到内网。除此之外的外部报文都会被NAT设备过滤。 image.png

  • ADF(Address-Dependent Filtering,外部地址相关过滤):对于内网Endpoint(X,x),只有它曾经向IP地址为M的外网主机Host B发送过报文,NAT设备才会对外网主机Host B使用外网地址M、任意端口号发送到Endpoint(Y,y)的报文进行地址转换。除此之外的外部网络报文都会被NAT设备过滤。 image.png

  • APDF(Address and Port-Dependent Filtering,外部地址和端口相关过滤):对于内网Endpoint(X,x),如果它仅向外网Endpoint(M1,m1)发送过报文,那么NAT设备只会对Endpoint(M1,m1)发送到Endpoint(Y,y)的报文进行地址转换并转发到内网。除此之外的外网网络报文都会被NAT设备过滤。 image.png

NAT类型

  • Full Cone NAT是EIM和EIF的组合。

  • Restricted Cone NAT是EIM和ADF的组合。

  • Port Restricted Cone NAT是EIM和APDF的组合。

  • Symmetric NAT是APDM和APDF的组合。

  • Full Cone NAT(完全锥型NAT):所有从同一个私网IP地址和端口(IP1:Port1)发送到NAT设备的报文都会被映射成同一个公网IP地址和端口(IP:Port)。并且,任何外部主机都可以通过该公网IP地址和端口(IP:Port)和内部主机进行通信。

  • Restricted Cone NAT(IP限制锥型NAT)。所有从同一个私网IP地址和端口(IP1:Port1)发送到NAT设备的报文都会被映射成同一个公网IP和端口号(IP:Port)。与Full Cone NAT不同的是,不是所有外部主机都可以通过(IP:Port)和内部主机进行通信,除非内部主机之前已经向此外部主机发送过报文。

  • Port Restricted Cone NAT(端口限制锥型NAT)。所有从同一个私网IP地址和端口(IP1:Port1)发送到NAT设备的报文都会被映射成同一个公网IP和端口号(IP:Port)。与Restricted Cone NAT不同的是,一台公网主机(IP2:Port2)能够和内网主机进行通信的前提是,这台公网主机通过(IP2:Port2)收到内网主机发送的数据包。

  • Symmetric NAT(对称NAT)。所有从同一个私网IP地址和端口(IP1:Port1)发送到一个特定的目的IP地址和端口的报文,都会被映射到同一个IP地址和端口。如果同一台私网主机使用相同的源地址和端口号发送报文,但是发往不同的目的地,NAT将会使用不同的映射。此外,公网主机与某个内网主机通信的前提是,这台公网主机收到该内网主机发送的数据报文。

对称型和端口限制型的区别在于:内网设备同一IP和端口访问不同外网主机时,在端口限制锥型中,会被映射成同一个公网IP和端口号;而在对称型中会被映射成新的(IP+端口号),这里需要注意的是,可能只是换端口。比如1.1.1.1:30–>3.3.3.3:40会被映射为2.2.2.2:1111–>3.3.3.3:40;1.1.1.1:30–>4.4.4.4:50会被映射为2.2.2.2:2222–>4.4.4.4:50

打洞过程之探测NAT类型

在实现内网穿透时,需要探测2个内网客户端所处的NAT环境。

STUN报文格式

讲探测类型前,先讲一下STUN报文的格式。

  • STUN基于UDP传输协议报文,包含消息头和消息属性两部分,消息头为20字节。

消息头结构如下: image.png

  • STUN Message Type:STUN消息类型,长度为14比特。当前仅支持STUN捆绑请求和STUN捆绑响应两种类型的消息。

  • Message Length:STUN消息长度,长度为16比特(不包括消息头长度)。

  • Magic Cookie:魔术字,长度为32比特。魔术字包含固定值0x2112A442,用于STUN服务器检测STUN客户端是否可以识别特定属性。此外,当STUN与其他协议使用相同的端口号时,通过魔术字可以将STUN和其他协议区分开。

  • Transaction ID:事务ID,长度为96比特,用于唯一标识一次STUN探测。事务ID由STUN客户端来选择,在一次STUN探测中,STUN服务器收到STUN的捆绑请求消息后,以同样的事务ID返回STUN捆绑响应消息。同时,STUN服务器根据事务ID来唯一标识STUN客户端的不同探测请求。

消息属性采用TLV格式,Type和Length字段的长度均为16比特,Value字段的长度可变。

  • CHANGE-REQUEST:捆绑请求中携带的消息属性,STUN客户端使用此属性来请求STUN服务器使用不同的IP地址或端口号来发送捆绑响应。

  • MAPPED-ADDRESS:捆绑响应中携带的消息属性,表示经过地址转换后的STUN客户端的IP地址和端口。

  • XOR-MAPPED-ADDRESS:捆绑响应中携带的消息属性,表示经过地址转换后的STUN客户端的IP地址和端口。与MAPPED-ADDRESS不同的是,XOR-MAPPED-ADDRESS属性中携带的IP地址经过了异或(XOR)处理。

  • RESPONSE-ORIGIN:捆绑响应中携带的消息属性,表示STUN服务器发送数据的IP地址和端口。

  • OTHER-ADDRESS:捆绑响应中携带的消息属性,表示STUN服务器的另一个IP地址和端口号。假设STUN服务器的IP地址为Y1,替代IP地址为Y2,端口号为YP1,替代端口号为YP2。Da表示STUN客户端发送捆绑请求的目的IP地址,Dp表示STUN客户端发送捆绑请求的目的端口号。如果Da为Y1,那么OTHER-ADDRESS中的IP地址为Y2;如果Da为Y2,那么OTHER-ADDRESS中的IP地址为Y1。如果Dp为YP1,那么OTHER-ADDRESS中的端口号为YP2;如果Dp为YP2,那么OTHER-ADDRESS中的端口号为YP1。

当STUN客户端要求STUN服务器使用不同的IP地址发送捆绑响应时,如果Da为Y1,则捆绑响应报文OTHER-ADDRESS中的IP地址为Y2;如果Da为Y2,则OTHER-ADDRESS中的IP地址为Y1。类似地,当STUN客户端要求STUN服务器使用不同的端口号发送捆绑响应时,如果Dp为YP1,那么OTHER-ADDRESS中的端口号为YP2;如果Dp为YP2,那么OTHER-ADDRESS中的端口号为YP1。

如果STUN服务器未指定替代IP地址,则捆绑响应报文中不会携带OTHER-ADDRESS属性,这种情况下,STUN客户端无法判断NAT类型。

探测NAT映射类型

先探测NAT映射类型,以图中Client_A为例 image.png

(1)     STUN客户端以Endpoint(X_A,P_A)为源地址和源端口向STUN服务器的外网Endpoint(Y_1,P_1)发送捆绑请求。STUN服务器使用Endpoint(Y_1,P_1)给STUN客户端发送捆绑响应,响应内容包括:STUN客户端经过NAT映射后的外网Endpoint(X_A1,P_A1),以及STUN服务器的另一个外网Endpoint(Y_2,P_2)。

(2)     STUN客户端收到STUN服务器发送的捆绑响应报文后,判断NAT映射后的Endpoint(X_A1,P_A1)是否与内网Endpoint(X_A,P_A)相同:

  • 如果Endpoint(X_A1,P_A1)与Endpoint(X_A,P_A)相同,则SUTN客户端认为不存在NAT映射。
  • 如果Endpoint(X_A1,P_A1)与Endpoint(X_A,P_A)不同,则STUN客户端使用第(3)步继续进行探测。

image.png

(3)     STUN客户端以Endpoint(X_A,P_A)给STUN服务器的外网Endpoint(Y_2,P_1)发送捆绑请求。STUN服务器使用Endpoint(Y_2,P_1)给STUN客户端发送捆绑响应,响应内容包括:STUN客户端经过NAT映射后的外网Endpoint(X_A2,P_A2)。

(4)     STUN客户端收到STUN服务器发送的捆绑响应报文后,判断NAT映射后的Endpoint(X_A2,P_A2)是否与第(1)步中NAT映射后的Endpoint(X_A1,P_A1)相同:

  • 如果Endpoint(X_A2,P_A2)与Endpoint(X_A1,P_A1)相同,则STUN客户端认为NAT映射类型为EIM。
  • 如果Endpoint(X_A2,P_A2)与Endpoint(X_A1,P_A1)不同,则STUN客户端使用第(5)步进行探测。

image.png

(5)     STUN客户端以Endpoint(X_A,P_A)给STUN服务器的外网Endpoint(Y_2,P_2)发送捆绑请求。STUN服务器使用Endpoint(Y_2,P_2)给STUN客户端发送捆绑响应,响应内容包括:STUN客户端经过NAT映射后的外网Endpoint(X_A3,P_A3)。

(6)     STUN客户端收到STUN服务器发送的捆绑响应报文后,判断NAT映射后的Endpoint(X_A3,P_A3)是否与第(3)步中NAT映射后的Endpoint(X_A2,P_A2)相同:

  • 如果Endpoint(X_A3,P_A3)与Endpoint(X_A2,P_A2)相同,则STUN客户端认为NAT映射类型为ADM。
  • 如果Endpoint(X_A3,P_A3)与Endpoint(X_A2,P_A2)不同,则STUN客户端认为NAT映射类型为APDM。

探测NAT过滤类型

(1)     STUN客户端以Endpoint(X,XP)为源地址和源端口向STUN服务器的外网Endpoint(Y1,YP1)发送捆绑请求,请求报文中携带CHANGE-REQUEST属性,即要求STUN服务器改变IP地址和端口号来发送捆绑响应。STUN服务器发送给STUN客户端的捆绑响应中,OTHER-ADDRESS为(Y2,YP2),捆绑响应的源地址和源端口为(Y2,YP2)。

(2)     STUN客户端根据是否能收到响应报文进行如下判断:

  • 如果STUN客户端收到了捆绑响应报文,则STUN客户端认为NAT过滤类型为EIF。

  • 如果STUN客户端未收到捆绑响应报文,则STUN客户端使用第(3)步进行探测。

(3)     STUN客户端以Endpoint(X,XP)给STUN服务器的外网Endpoint(Y1,YP1)发送捆绑请求,请求报文中携带CHANGE-REQUEST属性,即要求STUN服务器改变端口号来发送捆绑响应。STUN服务器发送给STUN客户端的捆绑响应中,OTHER-ADDRESS为(Y2,YP2),捆绑响应的源地址和源端口为(Y1,YP2)。

(4)     STUN客户端根据是否能收到响应报文进行如下判断:

  • 如果STUN客户端收到了捆绑响应报文,则STUN客户端认为NAT过滤类型为ADF。

  • 如果STUN客户端未收到捆绑响应报文,则STUN客户端认为NAT过滤类型为APDF。

打洞过程

  1. STUN客户端通过BGP从路由反射器处获得其他STUN客户端的接口信息(包括NAT前后的IP地址和端口信息)。当Client1需要与Client2进行通信时,Client1会通过BGP通知Client2,它们之间需要通过打洞建立数据通道。
  2. Client1与Client2互相发送STUN绑定请求进行打洞。Client1使用本端NAT前的IP地址和端口分别与Client2 NAT前和NAT后的IP地址和端口构建STUN绑定请求报文A和B发送给Client2。同时,Client2也同样进行相应的操作。
  3. Client2收到报文A和B后,处理流程如下,Client1也类似:
    1. 对于报文A,若Client1与Client2在同一个私网中,也就是同一个NAT设备后侧,则报文A可以成功发送至Client2,否则报文A被丢弃。
    2. 对于Client1发出的报文B,经Client1前面的NAT设备1时会生成表项,记录Client1到Client2的会话,但是由于Client2前的NAT设备2上没有相关表项,报文B将会被丢弃。
    3. 同样的,对于Client2发出的报文B,经Client2前面的NAT设备2上将会生成表项,记录Client2到Client1的会话,但是由于Client1前的NAT设备1上没有相关表项,报文B也会被丢弃。
    4. Client1和Client2持续向对方发送绑定请求报文,当NAT设备1与NAT设备2上的会话表项都生成后,绑定请求报文就可以成功发送至对端Client。
  4. Client2收到STUN绑定请求报文后,向Client1发送STUN绑定响应报文,Client1也同样进行相应的操作。

以上打洞过程适用于完全锥形、IP限制锥型和端口限制锥型NAT,对于对称型NAT无法实现。

1
思考:对称型NAT限制如此严格,除了中转服务器,不能实现P2P打洞了嘛?

参考文章

https://www.h3c.com/cn/d_202305/1847789_30005_0.htm#_Toc134613458

https://info.support.huawei.com/info-finder/encyclopedia/zh/STUN.html