stun协议深入解剖STUN协议的全称是Simple Traversal of User Datagram Protocol Through Network Address Translators,主要功能是检测是否位于NAT后面,如果位于NAT后面,经过NAT 转换后的地址和端口是什么,另外可以检测NAT的类型1.NAT类型NAT的类型:全锥形NAT:所有从同一个内网IP和端口号发送过来的请求都会被映射成同一个外网IP地址和端口号而且任何一个外网主机都可以通过这个映射的外网IP和端口号向这台内网主机发关怉受限制锥形NAT:它也是所有从同一个内网IP和端口号发送过来的请求都会被映射成同一个外网IP和端口号和Full-Cone NAT不同的是,一个拥有IP地址X的外网主机如果想要给内网主机发送数据包,必须是这台内网主机之前给IP地址X发送过数据包才可以端口受限制锥形NAT:它和Restricted Cone很相似,只不过它包括端口号,也就是,一台IP地址X 和端口P的外网主机想给内网主机发送数据包,必须是这台内网主机之前给这个IP地址X和端口P发送过数据包才可以对称NAT:对称NAT就是,所有从同一个内网IP和端口发送到一个特定的目的IP和端口的请求,都会被映射到同一个IP和端口。
如果同一台主机用相同的源地址和端口号发送数据包,但是发往不同的目的地,NAT将会使用不同的映射进一步说,只有当外网主机收到内网主机发送来的数据包之后才能向内网主机往回发送数据包2.STUN服务器STUN Binding Request使用UDP协议发送到STUN服务器,当Binding Request 消息到达服务器的时候它可能经过了一个或者多个NAT结果是STUN服务器收到的request消息的源IP地址被映射成最靠近STUN服务器的NAT的IP地址,STUN服务器把这个源IP地址和端口号复制到一个Bind Response消息中,通过发送回拥有这个IP地址和端口号的客户端,对于上面提到的所有类型的NAT,这个消息都会到达客户端3.如何区分不同的NAT(1)是否处于NAT后面当STUN客户端收到STUN Binding Response消息之后,它会将自己发送Request时bind的本地IP地址和端口号同Response消息中的IP地址端口号进行比较,如果不匹配,就表示客户端正处于一个或者多个NAT的前面在Full-Cone NAT的情况下,在STUN Response消息中的IP地址和端口是属于公网的,公网上的任何主机都可以使用这个IP地址和端口号向这个应用程序发送数据包,应用程序只需要在刚才发送STUN Binding Request的IP地址和端口上监听即可。
2)是否在对称NAT后面当然,主机可能并不在一个full-core NAT的前面,实际上,它并不知道自己在一个什么类型的NAT的前面为了确定NAT的类型,客户端使用附加的STUN Binding Request.具体过程是很灵活的,但一般都会像下面这样工作客户端再发送一个STUN Binding Request,这次发往另一个IP地址,但是使用的是跟上一次同一个源IP地址和源端口号,如果返回的数据包里面的IP地址和端口号和第一次返回的数据包中的不同,客户端就会知道它是在一个对称NAT的后面3)客户端如何确定自己是否在一个完全锥形NAT的后面在客户端发送的消息中,有一个标志包含了Server的另一个IP,客户端发给Server消息,Server解析消息,取出这个IP,然后Server用这个IP向客户端发送消息如能通过,则是完全锥形如不能通过,则是受限制或端口受限4)客户端如何确定自己是在受限锥形NAT还是端口受限NAT在客户端发送的消息中,有一个标志包含了Server的另一个端口,客户端发给Server消息,Server解析消息,取出这个端口,然后Server用这个原IP和端口向客户端发送消息。
如能通过,则是仅仅IP受限锥形如不能通过,则是端口受限型4.STUN消息一览STUN消息是使用大端字节流编码的TLV(type-length-value).所有的STUN消息都以一个STUN头开始,紧跟着STUN的载核数据(Payload)Payload 是一系列的STUN属性集合,它们取决于STUN消息的类型STUN的消息头包含了STUN message type,transation ID,and length.STUN message type 可以是Binding Request,Binding Response,Binding ERROR Response, Shared Secret Request,Shared Secrect Response或Shared Secret Error Response.Transaction ID的作用是将请求(Request)和响应(Response)联系起来长度字段代表STUN Payload数据的整个长度Shared SecretRequests一直都是承载于TCP之上发送的(实际上,是使用了承载于TCP 这上的TLS发送的)STUN协议也定义了很多的STUN属性。
第一个是MAPPED-ADDRESS属性,它是一个IP地址和端口对,Binding Response里面一直都有它,它代表了服务器在Binding Request中看到的源IP 地址和源端口号还有一个RESPONSE-ADDRESS属性,包含一个IP地址和端口RESPONSE-ADDRESS可以被放到Binding Request中,它告诉服务器Binding Request将会被发送到哪里它是可选的,当不填写的时候,Binding Response 会被卧发送到Binding Request的源IP地址和源端口号当填写的时候,Binding Response会发送到填写的IP地址和端口)该属性使用客户端发送给其他客户端,或者客户端同服务端通信第三个属性是CHANGE-REQUEST属性,它包含了两个flag,这两个flag控制用来发送Response的IP地址和端口号这两个标志被称为“change IP”和“change port”标志,CHANGE-REQUEST标志只允许在Binding Request中出现,在确定客户端是在Restricted Cone NAT之前还是Port Restricted Cone NAT 之前的时候,这两个标志是很有用的。
它们指示Server从不同的源地址和源端口发送Binding Response在Binding Request中CHANGE-REQUEST属性是可选的第四个属性是CHANGED-ADDRESS属性,它出现在Binding Response中如果客户端请求使用”change IP”和”change port”行为,它会通知客户端将会使用的源IP地址和源端口号第五个属性是SOURCE-ADDRESS属性,它只出现在Binding Response中,它指示发送Response的源IP地址和源端口号,它在检测两个NAT配置的时候是很有用的第六个是USERNAME,它只在Shared Secret Response中出现,忽略了…第七个属性是ERROR-CODE属性,它出现在Binding Error Response和Shared Secret Error Response中,它指出发生的错误忽略了三四个属性…..消息头:所有的STUN消息都包含20个字节的消息头:012301234567890123456789012345678901+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|STUN Message Type|Message Length|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Transaction ID+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Message Type可以取下面这些值:00001:Binding Request00101:Binding Response00111:Binding Error Response00002:Shared Secret Request00102:Shared Secret Response00112:Shared Secret Error ResponseMessage Length是载核数据的字节长度,不包含消息头的长度。
Transaction ID是一个128位的标识符,可以随机生成消息属性STUN消息头后面跟着0个或多个属性,所有的属性都是TLV形式的,包含16位的类型,16位的长度,和变长的值012301234567890123456789012345678901+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Type|Length|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Value….+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+下面是类型的定义:00001:MAPPED-ADDRESS00002:RESPONSE-ADDRESS00003:CHANGE-REQUEST00004:SOURCE-ADDRESS00005:CHANGED-ADDRESS00006:USERNAME00007:PASSWORD00008:MESSAGE-INTEGRITY00009:ERROR-CODE0000a:UNKNOWN-ATTRIBUTES0000b:REFLECTED-FROMMAPPED-ADDRESS这个属性表示映射的IP地址和端口。
012301234567890123456789012345678901+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|x x x x x x x x|Family|Port|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Address|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Family一般都是001,表示IPV4RESPONSE-ADDRESS这个属性的数据包形式跟MAPPED-A。