WebRTC网络基础
WebRTC网络基础
1.NAT协议
是将IP数据报头中的IP地址转换为另一个IP地址的过程。
作用:
- 在实际应用中,NAT主要用于实现私有网络访问公共网络的功能。这种通过使用少量的公网IP地址代表较多的私网IP地址的方式,将有助于减缓可用IP地址空间的枯竭。
- 出于安全考虑 外网想要攻击内网就需要经过网关 部分就会被过滤
种类:
-
完全锥型 无限制
内网主机建立一个UDP socket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,任何外部主机只要知道这个(PublicIP:PublicPort)就可以发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包。
其在NAT上建立的内外网的映射表如下:
{
内网:IP,
内网端口,
映射的外网IP,
映射的外网端口
}
- C1,C2向STUN发消息
- 交换公网IP及端口
-
地址限制型
内网主机建立一个UDP socket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,如果任何外部主机想要发送数据给这个内网主机,只要知道这个(PublicIP:PublicPort)并且内网主机之前用这个socket曾向这个外部主机IP发送过数据。只要满足这两个条件,这个外部主机就可以用自己的**(IP,任何端口)**发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包。
其在NAT上建立的内外网的映射表如下:
{
内网:IP,
内网端口,
映射的外网IP,
映射的外网端口,
被访问主机的IP
}
- C1向C2发请求 C2通过C1发的请求返回数据
- 交换公网IP及端口 端口限制型类似
-
端口限制型
内网主机建立一个UDP socket(LocalIP:LocalPort) 第一次使用这个socket给外部主机发送数据时NAT会给其分配一个公网(PublicIP:PublicPort),以后用这个socket向外面任何主机发送数据都将使用这对(PublicIP:PublicPort)。此外,如果任何外部主机想要发送数据给这个内网主机,只要知道这个(PublicIP:PublicPort)并且内网主机之前用这个socket曾向这个外部主机(IP,Port)发送过数据。只要满足这两个条件,这个外部主机就可以用自己的**(IP,Port)**发送数据给(PublicIP:PublicPort),内网的主机就能收到这个数据包
其在NAT上建立的内外网的映射表如下:
{
内网:IP,
内网端口,
映射的外网IP,
映射的外网端口,
被访问主机的IP,
被访问主机的端口
}
-
对称型
内网主机建立一个UDP socket(LocalIP,LocalPort),当用这个socket第一次发数据给外部主机1时,NAT为其映射一个(PublicIP-1,Port-1),以后内网主机发送给外部主机1的所有数据都是用这个(PublicIP-1,Port-1),如果内网主机同时用这个socket给外部主机2发送数据,第一次发送时,NAT会为其分配一个(PublicIP-2,Port-2), 以后内网主机发送给外部主机2的所有数据都是用这个(PublicIP-2,Port-2).如果NAT有多于一个公网IP,则PublicIP-1和PublicIP-2可能不同,如果NAT只有一个公网IP,则Port-1和Port-2肯定不同,也就是说一定不能是PublicIP-1等于 PublicIP-2且Port-1等于Port-2。此外,如果任何外部主机想要发送数据给这个内网主机,那么它首先应该收到内网主机发给他的数据,然后才能往回发送,否则即使他知道内网主机的一个(PublicIP,Port)也不能发送数据给内网主机,这种NAT无法实现UDP-P2P通信。
- 端口猜测
-
穿越组合
- 端口受限 --> 对称
- 对称 --> 对称 二者无法打通
2.STUN服务
(Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs))
STUN(穿越NAT的简单UDP传输)服务器允许所有的NAT客户终端(如防火墙后边的计算机)与位于局区域网以外的VOIP服务商实现电话通话。
其允许应用程序发现自己和公网之间的中间件类型,同时也能允许应用程序发现自己被NAT分配的公网IP。
协议内容
-
STUN header

-
2个字节类型
-
2个字节消息长度,不包括消息头
-
16个字节事务ID(128bit),请求与相应事务ID相同
STUN Message Type:
-
最高的2位必须置零,这可以在当STUN和其他协议复用的时候,用来区分STUN包和其他协议数据包。
-
STUN Message Type 字段定义了消息的类型( 请求/成功响应/失败响应/指示)和消息的主方法。
虽然我们有4个消息类别,但在STUN中只有两种类型的事务,即请求/响应类型和指示类型。响应类型分为成功和出错两种,用来帮助快速处理STUN信息。Message Type字段又可以进一步分解为如下结构:
MessageClass定义:0b00表示request,0b01表示indication,0b10表示success response,0b11表示error response
-
Message Length 字段存储了信息的长度,以字节为单位,不包括20字节的STUN头部。由于所有的STUN属性都是都是4字节对齐(填充)的,因此这个字段最后两位应该恒等于零,这也是辨别STUN包的一个方法之一。
-
Magic Cookie 字段包含固定值0x2112A442,**这是为了前向兼容RFC3489,因为在RFC3489/STUN中,这一区域是事务ID的一部分。另外选择固定数值也是为了服务器判断客户端是否能识别特定的属性。**还有一个作用就是在协议多路复用时候也可以将其作为判断标志之一。(32位)
-
Transaction ID
字段是个96位的标识符,用来区分不同的STUN传输事务。
对于request/response传输,事务ID由客户端选择,服务器收到后以同样的事务ID返回response;对于indication则由发送方自行选择。事务ID的主要功能是把request和response联系起来,同时也在防止攻击方面有一定作用。服务端也把事务ID当作一个Key来识别不同的STUN客户端,因此必须格式化且随机在0~2^(96-1)之间。重发同样的request请求时可以重用相同的事务ID,但是客户端进行新的传输时,必须选择一个新的事务ID。
-
-
-
STUN Message Body
- 通常跟着0个或者多个属性,每个属性必须是TLV编码的(Type-Length-Value)

3.TURN服务
1 | |
整体流程

TURN Allocate

4.NAT类型检测
前提条件
1 | |
为什么使用UDP协议
因为UDP是无连接协议,只要你发送数据给他,他就可以收到,而TCP需要建立连接
步骤
客户端发送ECHO请求给服务端 客户端等待服务端返回数据

5.ICE框架
1 | |
介绍
1. ICE 的角色
分为 controlling和controlled。
offer 一方为controlling角色,answer一方为controlled角色。
2. ICE的模式
分为FULL ICE和Lite ICE:
FULL ICE:是双方都要进行连通性检查,完成的走一遍流程。
Lite ICE: 在FULL ICE和Lite ICE互通时,只需要FULL ICE一方进行连通性检查, Lite一方只需回应response消息。这种模式对于部署在公网的设备比较常用。
3. ICE Candidate
媒体传输的候选地址(包括协议,ip,端口,类型),组成candidate pair做连通性检查,确定传输路径。(ICE主要收集Candidate 对Candidate pair做排序 以及连通性)
- 主机候选者(本机的)
- 映射候选者(NAT映射的)
- 中继候选者(TURN服务器开通的)
4. Componet ID
传输媒体的类型,1代表RTP;2代表 RTCP。
WebRTC采用Rtcp-mux方式,也就是RTP和RTCP在同一通道内传输,减少ICE的协商和通道的保活。
5. Type
(Host/Srvflx/Relay/Prflx)
6. Checklist
由candidate pair生成按优先级排序的链表,用于ICE连通性检查。
7. Validlist
由连通性检查成功的candidate pair按优先级排序的链表,用于ICE提名和选择最终路径。
8. Base
是指候选者的基础地址(Srvflx address 的base 是本地host address。
host address和 relayed address 的base 是自身。)
9. SDP协议
是一种通用的会话描述协议,主要用来描述多媒体会话,用途包括会话声明、会话邀请、会话初始化等。
1 | |
ICE过程
1. Gather candidates
根据Componet ID获取所有候选者 同时生成foundation foundation是用于判断candiadate是否相同
2. 删除重复的候选者
如果两个候选者地址,Base地址一样 则删除
3. 交换candidates
ICE使用offer/answer的方式,双方通过SDP协商交换candidates信息。
Candidate信息包括type,foundation,base,component id,transport。
SDP a行格式如下:
1 | |
表示 foundation为1,媒体是RTP,采用UDP协议,公网映射地址为212.223.223.223:12345,优先级为9654321,type为srflx,base地址为10.216.33.9:54321。
4. 生成candidate pairs
在本端收到远端candidates后,将Component ID和transport protocol相同的candidates组成pair。
修整candidate pair,如果是srvflx地址,则需要用其base地址替换。
对端也是同样的流程。
5. 生成checklist
将candidate pairs按照优先级排序,生成checklist,供连通性检查使用
6. 连通性检查
Ordinary checks 两端都按照各自checklist分别进行检查。
Triggered checks 收到对端的检查时,也在对应的candidate pair上发起连通性检查,以提高效率
如果checklist里有relay candidate,则必须首先为relay candidate创建permission。
7. 发送连通性检查请求
8. 生成validlist
9. 提名candidate pair
10. 选择最终传输地址
网络协议分析 (tcpdump 与 wireshark)
tcpdump
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
其中:
tcp: ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型
-i eth1 : 只抓经过接口eth1的包
-t : 不显示时间戳
-s 0 : 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包
-c 100 : 只抓取100个数据包
dst port ! 22 : 不抓取目标端口是22的数据包
src net 192.168.1.0/24 : 数据包的源网络地址为192.168.1.0/24
-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析
搭建TRUN服务器
1. 下载并安装libevent-2.0
1 | |
2. 下载编译安装coturn
1 | |
3. 配置文件
在/usr/local/etc/目录下有turnserver.conf.default,复制为turnserver.conf
1 | |
使用ifcongig查询网卡名称和内网地址
4. 生成签名证书
1 | |
5. 修改配置信息
1 | |
6. 开启turnserver,执行命令
1 | |
7. 在阿里云后台的安全组规则中添加用到的端口,包括3478端口的tcp/udp
1 | |
8. 在浏览器中打开https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/进行验证
如果返回relay类型的数据且最终为Done则说明测试成功
需要注意的是:在Chrome中测试虽然同样会返回relay数据但会报一些错误
1 | |
但是在firfox中则不会存在这个问题,但无论如何均不影响使用。