注意:这种机制只适用于RFC 3489[21]中定义的经典STUN,RFC 5389引入后,这个机制已经过时。这个机制不是设计用于RFC 5389中定义的STUN。IPv6部署要么不使用NAT,要么以不同的方式使用它。
G.1介绍
CWMP可以用来对通过网关连接的局域网下的CPE设备进行远程管理。当设备部在NAT网关之后,并被分配了私网IP后,CWMP依然可以对其进行管理,但有了限制,通过Connection Request触发CWMP会话的机制不可用。
本附录定义了一种方式,允许ACS初始化位于NAT网关后的设备的CWMP会话,它提供了与Connection Request相同的功能,但使用的是不同的机制,以适应这个场景。
此机制不要求网关支持CWMP协议,仅需要ACS和CPE做出支持。
G.2过程
为满足此特性,CPE和ACS需要满足如下要求:
l CPE必须能够发现它到ACS的连接是穿过了一个NAT网关,并且这个NAT网关为CPE分配了一个私网IP地址。
l CPE必须能够维护一个NAT绑定通道,ACS通过它可以随时向CPE发送数据包,而不是仅在收到CPE的请求后,以响应此请求的方式发送数据包。
l CPE必须能够确定与NAT绑定通道相关联的公网IP地址和端口,并将此信息发送给ACS。
为适应上述各项功能,本附录定义了一些STUN协议的特别用法,即基于UDP的Connection Request机制,做为基于TCP的Connection Request的补充。
借助于STUN,发送UDP Connection Request到CPE,过程总结如下:
l ACS开启CPE的STUN功能(如果出厂默认配置下尚未启用的话),并告知CPE相应的STUN Server地址。
l CPE通过STUN,确定CPE是否位于NAT网关后面,并且被分配了私网地址。
l 如果CPE位于NAT网关后面,并且被分配了私网地址,则CPE使用STUN中定义的过程,探测绑定通道的超时时间。
l CPE以一定的频率周期性发送的STUN绑定请求,以维持NAT绑定通道的畅通,侦听UDP连接请求。
l CPE探测穿越NAT后的公网IP和端口,及其变化,将这些信息发送给ACS。
l ACS有两种方式获取这些信息,一是通过STUN绑定请求消息本身;二是通过TR069中的UDPConnectionRequestAddress参数。
l 当ACS要建立与CPE的连接时,向CPE发送UDP Connection Request。为了适应最广泛的NAT网关,它将从与STUN服务器相同的源地址和端口发送(否则无法穿越“对称型NAT网关”)。
G.2.1对CPE的要求
CPE的TR069参数,根据设备情况,要符合TR098或TR181参数模型。
如果TR069中STUNEnable参数的值为true,CPE必须判断与STUN Server之间是否发生了ip/port转换,如果发生了转换,CPE必须:
l 判断穿过NAT后的公网IP和端口。
l 探知NAT绑定通道的超时时间,并以保持绑定通道所需的速率,周期性发送绑定请求。
l 通过STUN可选属性,指出CPE正在监听哪个绑定通道上的UDP Connection Request,以及绑定通道是否发生了更改。另外,更新TR069中的UDPConnectionRequestAddress参数,以指出与绑定通道关联的公共IP地址和端口。
l 侦听UDP Connection Request消息,并在这些消息到达时,根据其做出响应。
如上各条目的细节,会在下面的章节中详述。
G.2.1.1 探知绑定通道
当通过TR069中ManagementServer对象的STUNEnable参数启用STUN后,CPE必须向指定的STUN服务器(TR069的STUNServerAddress和STUNServerPort参数中指定的)发送绑定请求消息,如[21]中定义的那样。如果TR069的STUNServerAddress参数没有值,则必须使用ACS URL的host部分作为STUN服务器地址。
如果发生了IP/PORT转换,则为了探知绑定通道,发送绑定请求的IP/PORT必须是监听UDP ConnectionRequest的IP/PORT(探知绑定通道的超时时间时,将从不同的端口发送)。
CPE通过基本绑定请求消息,探知CPE和STUN服务器之间,是否发生了地址和端口转换。方法是:比较请求发送的源IP/PORT和STUN服务器返回的MAPPED-ADDRESS属性,如果IP或PORT不同,则说明发生了转换。
如果探知到发生了IP/PORT转换,则CPE必须记录最新收到的MAPPED-ADDRESS属性的值(一对IP/PORT),UDP ConnectionRequest将发送至其表示的IP/PORT。
后续,为了维持绑定通道畅通,CPE定期发送绑定请求,此时CPE必须再次确定是否发生IP/PORT转换,如果发生了转换,CPE必须记录成功响应的MAPPED-ADDRESS属性值。
如果CPE被预分配了STUNUsername/STUNPassword(TR069参数),并且CPE收到了Bainding Error Response,错误码为401(未授权),那么CPE必须重新发送Binding Request,并且携带USERNAME和MESSAGE-INTEGRITY属性。
当发送携带MESSAGEINTEGRITY属性的绑定请求时,如果绑定响应中的MESSAGE-INTEGRITY属性无效或不存在,CPE必须丢弃相应的绑定响应。
如果CPE的本地IP变更,CPE必须重新探测绑定通道,这种情况下,TR069中STUNMinimumKeepAlivePeriod参数定义的绑定请求周期的最小限制不适用。
除了STUN服务器响应中明确的使用了401(未授权)错误码,CPE不能在任何Binding Request中包含MESSAGE-INTEGRITY属性。
CPE中的STUN客户端,不需要支持STUN绑定请求的CHANGE-REQUEST属性,也不需要识别绑定响应中出现的属性的CHANGED-ADDRESS、SOURCE-ADDRESS和REFLECTED-FROM属性。
CPE中的STUN客户端,不需要支持交互共享秘钥的消息,本附录定义的过程中,没有使用这些消息。
G.2.1.2 维持绑定通道
为了维持绑定通道,CPE必须周期性的发送Binding Request消息,发送消息时,使用监听UDP ConnectionRequest消息的IP/PORT作为源IP/PORT。
CPE发送这些绑定请求的频率不能超过TR069中ManagementServer对象的STUNMinimumKeepAlivePeriod参数所指定的频率。
CPE必须至少以TR069的STUNMaximumKeepAlivePeriod参数指定的频率,发送这些绑定请求(如果这个参数有值的话)。
如果TR069中STUNMinimumKeepAlivePeriod和STUNMaximumKeepAlivePeriod参数的值不相等,那么CPE必须主动发现NAT绑定通道所能维持的最长时间。为此,CPE必须使用在[21]中描述的过程来探知绑定通道的超时时间。具体地说,CPE必须能够通过辅助源端口(与主源端口不同)发送绑定请求,来测试绑定是否超时,并使用绑定请求中的RESPONSEADDRESS属性,指示将STUN绑定响应发送到主源端口(CPE侦听UDP Connection Request消息的端口)。
CPE使用辅助源端口发出的绑定请求,来确定绑定超时的具体过程,由CPE厂商自行决定。 一般由两个阶段组成:一个是发现阶段,一个是监控阶段。在发现阶段,CPE试图探知绑定超时的时间,并将测试不同的超时时间值,来确定实际的超时值(例如,使用二进制搜索)。在监控阶段,CPE将在刷新绑定通道之前,定期测试绑定通道,以确定绑定通道是否仍然存在。如果绑定通道不存在了,那么CPE可以返回到发现阶段,以探知新的绑定通道。
TR069中STUNMinimumKeepAlivePeriod参数定义的绑定请求周期,不适用于从辅助源端口发送的绑定请求。
G.2.1.3 将绑定通道的信息发送给ACS
有两种方法可以将绑定通道信息告知ACS。这两种方法,CPE都必须支持。第一种方法,发送Binding Request时,通过STUN的可选属性告知ACS。第二个方法是,CPE在绑定信息更改时,更新TR069中UDPConnectionRequestAddress参数的值。
Table 103列出了一组STUN属性。它们使用大于0x7FFF的属性类型值,STUN规范将其定义为可选的。不识别可选属性的STUN服务器需要忽略它们。
Table 103 用于Binding Request消息中的STUN可选属性。
Attribute Type | Name | Description |
0xC001 | CONNECTION-REQUEST-BINDING | 指出CPE监听UDP Connection Request的绑定通道信息。 Value元素必须是如下内容: 0x64 0x73 0x6C 0x66 0x6F 0x72 0x75 0x6D 0x2E 0x6F 0x72 0x67 0x2F 0x54 0x52 0x2D 0x31 0x31 0x31 0x20 这相当于字符串:“dslforum.org/TR-111” 最后一个字符是空格,目的是使长度为4个字符的整数倍。 它的Length元素必须是0x0014,也就是十进制的20。 |
0xC002 | BINDING-CHANGE | 表示绑定信息已经变化了。 这个属性不包含值,它的Length元素必须是0。 这个属性只能在包含CONNECTION-REQUEST-BINDING的情况下使用。 |
CPE使用监听UDP Connection Request的IP/PORT(即主源IP/PORT)发送的Binding Request,必须包含CONNECTION-REQUEST-BINDING属性。其他的所有Binding Request消息,必须不包含这个属性。
如果TR069中的STUNUsername参数不为空,包含CONNECTION-REQUEST-BINDING属性的Binding Request消息必须包含USERNAME属性,且值为TR069 STUNUsername参数的值,如果有必要,需要在后面补充空格,以保证长度为4字节的整数倍(STUN协议规定)。
每当CPE探测到NAT绑定通道变更(也包含第一次探测到绑定通道),必须立即发送一个Binding Request消息,从主源端口,也就是监听UDP Connection Request消息的端口,并且包含BINDING-CHANGE属性。这次Binding Request必须不包含RESPONSE-ADDRESS或者CHANGE-REQUEST属性。在其他Binding Request消息中,CPE必须不包含BINDING-CHANGE属性。TR069中STUNMinimumKeepAlivePeriod定义的Binding Request的最小周期限制,对于包含BINDING-CHANGE属性的Binding Request消息不适用。
对于包含BINDING-CHANGE属性的Binding Request消息,CPE必须遵从[21]定义的重传过程,以确保此消息被成功的接收。如果应用了重传过程,CPE确定Binding Request仍然失败,则它不能发送包含BINDING-CHANGE的Binding Request(直到绑定随后再次更改)。
如果IP/PORT发生了转换,当CPE确定绑定更改时(以及第一次CPE确定绑定时),CPE必须更新TR069中ManagementServer对象中的UDPConnectionRequestAddress参数的值。特别的:
l TR069中UDPConnectionRequestAddress的主机部分,必须设置为与UDP连接请求关联的绑定通道的公网IP地址。
l TR069中UDPConnectionRequestAddress的端口部分,必须设置为与UDP连接请求关联的绑定通道的公网PORT。
如果CPE确定IP/PORT发生了转换,CPE必须把TR069中ManagementServer对象的NATDetected参数设置为true。
如果ACS将TR069中UDPConnectionRequestAddress参数上的通知属性,设置为Active Notification,那么每当绑定通道信息发生变化,CPE必须建立一个到ACS的连接,并且包含UDPConnectionRequestAddress参数在Inform消息中。
当TR069中UDPConnectionRequestAddress参数变更时,如果上次发送Notification的时间距现在小于TR069 UDPConnectionRequestAddressNotificationLimit参数,那么本次Notification必须推迟,直到达到指定的最小时间间隔。
注意:除了指定的最小通知周期外,CPE也可以根据自己的判断来延迟通知,以避免通知消息过多。这样的延迟仅用在CPE认为绑定通道会在一个较短的时间内再次变更时。例如,在主动发现绑定超时的过程中,可以合理地预期频繁的绑定更改。类似地,CPE检测到安全攻击导致频繁的绑定更改,并限制通知的数量,直到攻击停止。
如果CPE判断出IP/PORT都没有发生转换,那么也必须通知ACS,通知的方法是,将TR069中NATDetected参数设置为false,并且,将UDPConnectionRequestAddress设置为本地IP/PORT,这个本地IP/PORT也就是CPE监听UDP Connection Request消息的地址。
G.2.1.4 UDP Connection Requests
符合本附录规定的CPE,必须在指定的端口上的临听UDP Connection Request。无论CPE是否检测到IP/PORT转换,以及是否启用了STUN,都必须如此。
注意:CPE必须继续监听基于TCP的Connection Request,定义在3.2.1.2。
UDP Connection Request消息的格式定义在Section G.2.2.3。当CPE接收到一个UDP Connection Request消息时,必须进行鉴权和验证。
当且仅当如下条件满足时,一个UDP Connection Request消息是有效的:
l 不得违反[6]对HTTP 1.1请求消息的要求。
l Request Line中给出的方法必须是GET。
n ts查询参数的值,时间戳,必须严格大于最新收到的、有效的、鉴权通过的UDP Connection Request消息。
n 为了保证上述的比较可以执行,CPE必须维护一个持久化记录,保存最新成功验证和鉴权的UDP Connection Request时间戳(除了CPE发生重启)。验证或鉴权失败的UDP Connection Request消息的时间戳不得保存。CPE可以在重启过程中保留这个值,如果没有保留,在重启之后应立即使用0值。
n CPE对时间戳的要求可以比上面所述的更严格。例如,CPE可以另外验证时间戳是否在一个时间窗口内(相对于CPE的当前时间)。如果CPE选择这样做,它应该避免时间窗口过窄,以便在CPE和ACS中都允许一个合理的误差范围。
l id参数,即Message ID,必须与最近收到的、有效的、鉴权成功的UDP Connection Request消息不同。
l un参数,即Username,值必须与TR069中ManagementServer对象的ConnectionRequestUsername参数一致。
当且仅当如下条件满足时,一个UDP Connection Request消息是鉴权通过的:
l sig参数,即Signature,必须与CPE根据Section G.2.2.3使用TR069中ManagementServer对象的ConnectionRequestPassword参数计算出的签名一致。
每当CPE接收并成功地验证和鉴权UDP Connection Request时,它必须遵循与3.2.1.2节中定义的基于tcp的连接请求相同的要求。
CPE必须忽略验证或鉴权不成功的UDP Connection Request。
CPE必须忽略UDP Connection Request中可能出现的,任何非空消息体的内容(这些消息体是为协议的未来版本预留的)。
因为STUN响应和UDP Connection Request将在同一个UDP端口上接收,CPE必须使用消息本身的内容区分STUN消息和UDP Connection Request。
因为[21]中定义的所有STUN消息的第一个字节都是0或1,而UDP Connection Request第一个字节始终是ASCII编码的字母,所以CPE可以使用这种方式来区分消息类型。
端口7547已经被IANA分配给CWMP(见[17]),CPE可以使用这个端口来处理UDP连接请求。
G.2.2对ACS的要求
ACS必须与一个符合此附录要求的STUN服务器关联起来。
G.2.2.1对STUN服务器的要求
STUN服务器必须符合[21]中定义的所有要求,但以下要求除外,STUN服务器可以选择不实现这些要求:
l STUN服务器不需要支持在[21]中定义的共享秘密交换机制。如果使用消息完整性,则必须静态地提供共享秘密,并与CPE TR069参数中的STUNUsername和STUNPassword参数对应。
l STUN服务器不需要支持用于发送绑定响应(A2/P2)的辅助源IP地址或端口。如果没有,使用主地址和端口(A1/P1)填充CHANGE-ADDRESS属性即可,如果在绑定请求中收到CHANGE-REQUEST属性,则STUN服务器可以忽略该属性。
通过使用错误代码401(未经授权)的Binding Error Response来响应请求,STUN服务器可以对任何接收到的Binding Request要求消息完整性。
G.2.2.2 判断绑定通道信息
ACS可以通过两种方式来判定绑定通道信息。
G.2.2.2.1 基于STUN消息的方式
如果ACS选择使用这种方式,那么它应该在每个CPE的ManagementServer对象中设置一个非空的STUNUsername和STUNPassword。在ACS所管理的所有CPE中,STUNUsername必须是唯一的,以确保可以此唯一关联CPE。在ACS所管理的所有CPE中,STUNPassword应该是唯一的,并且应该符合[21]规定的密码强度规则。
每当STUN服务器收到一个Binding Request,并且消息中同时包含BINDING-CHANGE和CONNECTION-REQUEST-BINDING属性:
l STUN服务器应该响应回401错误,强制CPE重发附带消息完整性的Binding Request。
l 当STUN服务器接收到重发的具有消息完整性的Binding Request时,应该对请求者进行身份验证。如果ACS和STUN服务器不是整合在一起的,这可能涉及到STUN服务器和ACS之间的通信。
l 如果身份验证失败,则STUN服务器必须响应[21]中定义的Binding Request Error,并且不再进行后续的操作。
l 如果身份验证成功,STUN服务器应该从Binding Request消息中提取出源IP/PORT,并且将其记录下来,用于发送UDP Connection Request消息。根据实现的不同,这可能涉及STUN服务器将IP/PORT与TR069参数STUNUsername的对应关系发送给ACS,ACS将根据CPE对应的STUNUsername保存这些关系。即ACS可据此得知,可用于向特定CPE发送UDP Connection Request消息的IP/PORT。
l 对于一个Binding Request消息中包含的Transaction ID,STUN服务器仅执行一次上述操作。应该忽略具有相同事务ID的绑定请求的冗余副本(为保障消息一定能被ACS接收,CPE可能发送多次)。
使用这种方法,STUN服务器也可以选择不要求消息完整性或对绑定请求进行身份验证,除非它遵循上述过程来确定绑定信息。
ACS可以在任何时间判定当前绑定通道,即使没有携带CONNECTION-REQUEST-BINDING属性的Binding Request来通知变更(这句翻译的可能有问题,原句是The ACS MAY determine the current binding at any time even if no change was notified by following the above procedure on any received Binding Request for which the CONNECTION-REQUEST-BINDING attribute is present )。在这些Binding Request中的USERNAME属性,可在后续的身份验证之前,供ACS暂时的判定CPE的身份。这允许ACS定期验证绑定信息,以确保在绑定通道更改的消息未到达ACS时,该信息是最新的。
如果ACS确定CPE不再位于正在进行IP/PORT转换的NAT之后,那么ACS可以使用3.2.1.2节中定义的基于TCP的连接请求。
G.2.2.2.2 基于TR069 Notification的方式
如果ACS选择在TR069的UDPConnectionRequestAddress参数上使用Active Notification,它应该执行以下操作:
l 设置UDPConnectionRequestAddress参数的Notification属性,以激活通知功能。
l 每当Inform参数中包含UDPConnectionRequestAddress参数时,记录其变更,并且使用最近记录的地址,作为发送UDP Connection Request消息的目标。特别的,目标的IP地址由此参数的host部分得来,PORT由此参数的port部分得来。如果,host部分给出的是一个域名,ACS必须使用DNS判定对应的IP地址。如果端口没有在UDPConnectionRequestAddress参数中明确指明,则默认使用80端口。
l 观察TR069中NATDetected参数的值(可以在UDPConnectionRequestAddress发生变化时读取它,也可以在该参数上启用通知功能)。当该参数为false时,ACS可以使用3.2.1.2节中定义的基于TCP的Connection Request。
使用这种方法,ACS可以选择不要求消息完整性或验证STUN绑定请求,因为这些请求不用于向ACS传递信息。在这种情况下,ACS不需要在CPE中设置STUNUsername或STUNPassword。
G.2.2.3 UDP Connection Request
ACS必须从与STUN服务器相同的源IP地址和端口发送UDP连接请求消息。
一个UDP Connection Request必须在单个数据包中传输。
ACS应该对同一个UDP Connection Request应该发送多次,以避免丢包。当ACS发送相同UDP Connection Request时,消息的内容(包括Message ID、Timestamp和cnonce)必须相同。
UDP Connection Request没有对应的响应消息。
UDP Connection Request消息的格式派生自HTTP 1.1 [6] GET消息的格式,尽管不使用HTTP 1.1协议本身。
特别的,UDP Connection Request消息必须满足下列要求:
l 必须是一个有效的HTTP 1.1 GET消息。
l 必须不包含消息体。
l 如果包含Content-Length Header,值必须为0。
l Request Line中的Method必须为GET。
l Request Line中给出的Request-URI必须是Absolute-URI。URI必须满足如下格式:
n Scheme部分必须是http或者HTTP。
n Authority部分必须如[12]中定义的一样。ACS可以将这个值设为TR069的UDPConnectionRequestAddress(如果这个参数有值的话)。否则,ACS必须从实际的目的IP/PORT中派生此字符串。port部分必须存在,除非目标port是80(默认值)。
n URI的Path部分必须为空。
n URI的Query部分,必须包含一个查询字符串,按照[23]中关于“application/x-www-form-urlencoded”的方式进行编码。查询字符串必须包含如下的键值对:
Name | Value |
ts | Timestamp。从Unix纪元到创建消息时的秒数(标准Unix时间戳)。 |
id | Message ID。一个无符号整数,消息重传时必须相同,后续发送的不同的UDP Connection Request消息必须不同。 |
un | Username。TR069 ManagementServer.ConnectionRequestUsername参数的值,此参数的值是从CPE读取的。 |
cn | Cnonce。一个随机的字符串,由ACS决定。 |
sig | Signature。由HMAC-SHA1 (Key, Text) [19]的40个字符十六进制表示(不区分大小写)组成,满足如下要求: l key的值是TR069 ManagementServer.ConnectionRequestPassword参数的值。 l Text是一个字符串,它由以下元素连接而成,按照如下列出的顺序,且各项之间没有空格: n ts的值 n id的值 n un的值 n cn的值 |
如下是一个URI示例:
http://10.1.1.1:8080?ts=1120673700&id=1234&un=CPE57689&cn=XTGRWIPC6D3IPXS3&sig=3545F7B5820D76A3DF45A3A509DA8D8C38F13512
G.2.3 消息流程
Figure 12 Binding discovery / maintenance from the primary source port
Figure 12是一个消息流示例。
在所有的示例中,所有的ip/port显示为(A,P)符号,A表示IP,P表示PORT。在示例中,(A1,P1)为CPE的主端口,用于监听UDP Connection Request消息,(A1,P2)为CPE的辅助端口,用于探测绑定超时时间。穿过NAT后,地址分别转换成了(A1',P1')和(A2',P2')。在所有的示例中,都假设STUN服务器没有辅助的IP/PORT,所以Binding Response中的CHANGED-ADDRESS属性(CPE不需要使用)内容是STUN服务器的主IP/PORT,也就是(A3,P3)。
Figure 12展示了周期性的探知绑定通道、维持绑定通道流程,即CPE发送Binding Request消息(使用主IP/PORT)携带CONNECTION-REQUEST-BINDING属性和USERNAME属性(如果Username有值的话)。在这个示例中,假定STUN服务器不对请求进行身份验证。
Figure 13 Binding Request from secondary source port for binding timeout discovery
Figure 13展示了CPE从辅端口发送Binding Request消息,用于发现主IP/PORT的绑定是否超时了。在此示例中,Binding Request消息中没有包含CONNECTION-REQUEST-BINDING属性,因为这个消息不是从主端口发出的。如果主IP/PORT绑定未超时最后一步的消息(灰色箭头)将不会出现。(CPE没有实现这个流程)
Figure 14 – Binding change notification authenticated by the ACS
Figure 14展示了当STUN服务器选择使用基于STUN的通知方式时,Binding Change的通知流程。这种情况下,STUN服务器在存储绑定信息前,要先对Binding Request进行身份验证。
Figure 15 – Binding change notification not authenticated by the ACS
Figure 15展示了当STUN选择使用基于TR069 Notification的通知方式时,Binding Change的通知流程。这种情况下,不需要对Binding Request消息进行身份验证,因为ACS使用CWMP TR069通知去更新绑定信息。
Figure 16 – UDP Connection Request
Figure 16展示了ACS向CPE发送一个UDP Connection Request,来触发一个CWMP TR069会话的流程。此示例中,STUN服务器发送了多次相同的UDP Connection Request,以保障消息能被CPE成功接收。
G.3 安全方面
- STUN协议描述了几种使用STUN机制进行攻击的可能性。相关详述,请参考Section 12 of RFC 3489 [21]。
- 因为绑定变更,会触发ACS对CPE进行身份验证,数据库更新,还可能需要建立CMWP TR069会话从而接收Inform消息,攻击者可以使NAT绑定频繁变更,从而导致ACS负荷加大。当使用TR069 Notification方式的通知方式时,ACS可以设置一个最小通知周期来避免过于频繁的变更通知。但是,要权衡好最大通知速率,和绑定信息过期时间,否则可能导致ACS因绑定信息过期,而无法向CPE发送Connection Request消息。