我们知道使用WebRTC进行端对端进行通话时,最便捷的方式就是通话的双方通过ip直连,摆脱原始的直播服务器中转的方式。

但是在现实的应用场景中,我们的客户端都是出于各大局域网内部的,比如局域网A中的192.168.2.231和局域网B中的192.168.2.162之间是不能直接连接通讯的,那么我们能不能通过某种方式让这两个处于不同局域网内的ip能够直连互相进行通讯呢?这是这NAT穿墙打洞就出场了。

NAT是什么

NAT(Network Address Translation),网络地址转换协议。NAT是1994年提出的,当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信时,就可以使用NAT技术。

比如说内网ip地址192.168.1.155与外网ip地址150.158.106.96是无法直接通信,如果想要让这两个ip能够直接通信,就需要用到NAT技术将ip地址192.168.1.155先转换成公网ip地址和端口之后就可以进行通信了。

NAT的出现主要是因为IP4地址耗尽,理论上当全球IP6全面普及使用之后,NAT是可以退出历史舞台的。可见NAT的本质就是让一群机器公用同一个IP,这样就暂时解决了IP短缺的问题。

NAT的出现还有一个出于网络安全的原因,外网的主机要想攻击内网的主机,必须要经过防火墙,经过NAT转换才能找到内网的主机。

NAT是如何工作的

我们前面了解到NAT的作用是把内网的私有地址,转化成外网的公有地址。使得内部网络上的(被设置为私有IP地址的)主机可以与外部的Internet进行网络通信。
那么NAT是如何工作的呢?

NAT设备有个NAT转换表,这个表记录了NAT设备收到的回包,接下来应该转发给哪台内部主机。

当内网通过NAT设备访问外网时会随机产生一个不同于其他内网机器的端口号,当NAT收到回包的时候,回包同样也会携带这个端口号,然后NAT设备就可以通过这个端口号映射出内网ip来判断这个回包应该交给哪个内部主机处理。

比如说172.16.10.6这台内部主机,在访问服务器100.100.100.69的时候,会随机产生一个不同于其他内网机器的端口号,比如说产生的的端口号是47690。

那么当NAT收到端口号为47690的回包的时候就会交给172.16.10.6这台内部主机进行处理。利用这种端口映射的方式就可以实现一个公网ip可以同时给数千台私有终端提供网络服务。

NAT的四种模式

为什么需要讲解NAT的四种模式呢?
因为在后面的讲解NAT打洞穿透的时候需要用到这些知识点。

NAT有4种不同的类型:

  • Full Cone(完全锥形)

这种模式NAT内部的机器A连接过外网机器C后,NAT会打开一个端口。然后外网的任何发到这个打开的端口的UDP数据报都可以到达A。不管是不是C发过来的。

例如:

A:192.168.8.100
NAT:202.100.100.100
C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000),
任何发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

  • Address Restricted Cone(地址受限制锥形)

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口。然后C可以用任何端口和A通信,其他的外网机器不行。

例如:

A:192.168.8.100
NAT:202.100.100.100
C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000),
任何从C发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

  • Port Restricted Cone(端口受限制锥形)

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口。然后C可以用原来的端口和A通信,其他的外网机器不行。

例如:

A:192.168.8.100
NAT:202.100.100.100
C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)
C(202.88.88.88:2000)发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)

  • Symmetric(对称式)

对称式NAT与端口限制性克隆类似,唯一不同的是当同一内部主机使用相同的端口与不同IP地址或端口的外部主机进行通信时,
NAT对该内部主机的端口映射会有所不同,这种情况下NAT会针对不同IP地址或端口的外部主机为内部主机的相同端口分配新的外部端口号。
对称式NAT不保证所有会话中的私有地址端口和公开地址端口之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。
这种情况下内部主机的“内网IP地址和端口”与“NAT IP地址和端口”之间会形成一对多关系。

NAT类型检测

通过使用STUN服务器检测设备所处网络的NAT类型,STUN服务器需要两个公网IP。

我们假定client是要检测的设备,server是STUN服务器,并假设server的两公网SOCKET的IP地址和端口号分别是IP1:port和IP2:port。

步骤1:

client向server IP1:port发送请求,server使用IP1:port将收到请求的源IP和port(即设备的公网IP地址和端口号)回复给client,如果得到的公网IP和设备自身的IP一样,则判定设备自身处在公网,无NAT,检测结束,否则进行下一步。

步骤2:

client向server IP1:port发送请求,server使用IP2:port来回复,如果设备能收到回复,则判定client的NAT为完全锥形(Full Cone NAT),检测结束,否则进行下一步。

步骤3:

client向server IP2:port发送请求,server使用IP2:port将收到的源IP和port回复给client,client判断此port和步骤1得到的port是否一样,如果不一样,则为对称型(Symmetric NAT),检测结束;

如果一样,则为限制型(Restricted Cone NAT),这时候需要进一步检查是地址限制型NAT还是端口限制型NAT。

步骤4:

client向server IP2:port发送请求,要求server使用该IP的另一个端口来回复,server使用IP2:port2回复请求,如果client能收到回复,则判断为地址限制型(Address Restricted Cone) NAT,否则为端口限制型(Port Restricted Cone) NAT

如何实现NAT打洞

在了解如何打洞之前我们来说一说为什么需要打洞?
NAT设备允许私网内主机主动向公网内主机发送数据,但却禁止反方向的主动传递,但在一些特殊的场合需要不同私网内的主机进行互联(例如P2P软件、WebRTC等),打洞穿越NAT的问题必须解决。

在这里需要强调的一点打洞并不是P2P所特有的,当我们打开电脑,连上网络,打开几个不同网站的时候,打洞和穿越时时刻刻都在发生着。
比如你打开腾讯的时候,你就在自己的NAT上打了一个洞,这个洞只允许腾讯特定的端口的数据穿越回来,在这里如果没有你先打的洞,腾讯官网是不可能成功给你发消息的。

既然说打洞无时无刻不在,那么为什么我们在平时的开发中很少提到打洞,而到了P2P或者WebRTC时却要一而再再而三地提起打洞呢?

这是因为在传统的cs模型的网络编程中,服务器都架设在公网,服务器端不用打洞(服务端不用为客户端打洞,客户端的数据也能过来),客户端就能向服务器发送请求。
其次,client向服务器发送请求时,client的打洞和服务器响应的穿越是自动实现的。还有一点就是在传统的cs模型中,打洞是单方向的,即只需客户端打洞。而在P2P或者WebRTC等一些应用中打洞是双向的。
当两个在不同内网机器A和机器B想要进行直接通信时,就需要A在自己的NAT上为B打一个洞,让B的数据能过来;B在自己的NAT上为A打一个洞,让A的数据能过来,而AB双方的打洞的操作得由我们自己完成,
所以不得不提及穿越打洞的概念。

假设现在有两个处于不同内网的设备A和B需要进行点对点通信,那么它们的打洞流程大概是怎么样的呢?

首先我们知道A和B目前并不能直接进行链接,因为它们互不知道对方的ip地址以及端口。如果需要在A和B之间进行打洞就需要借助一个公网的中介服务器S。
我们通过中介服务器S拿到A和B背后的NAT-A和NAT-B所在公网地址和端口即可完成打洞。

大致的打洞流程是:

1、 建立起设备A和设备B与中介服务器S的长连接关系;

2、 A向S发起请求,申请与B建立直连关系;

3、 S收到A的申请后,保存好A所在的公网NAT-A的ip和端口,并发送给B,要求B向A发送一条信息;

4、 B收到S的指令后向NAT-A发送一条信息,绝大数情况下这条信息是没有回复的,因为NAT-A中并没有关于B的映射规则。既然知道没有回复那么为什么还要发送这么一条无谓的信息呢?
其实这就是打洞,B向A发送消息并不是为了让A回复什么,而是为了让NAT-B给NAT-A打开一个端口,让后面NAT-A的消息能够进来给B接收得到。至此虽然B还是连接不上A,设备B的穿透洞是打好了,A是可以通过NAT-B连接B设备了。

5、 B在向NAT-A发送消息完成后,告诉中介服务器S:“我已经准备好了,来吧。。。”,S收到B准备好的消息之后就通知A,让A发送消息给B。

6、 A收到S的指令后向NAT-B发送消息,因为NAT-B在第4步中已经给A打开了端口,所以是可以连接上的。同时在A给B发送消息的同时,NAT-A也打开了一个端口,用于接收B的回应。至此A和B的打洞就完成了,A与B直接就可以利用NAT-A和NAT-B进行点对点通信了。

注意: 路由器和防火墙的UDP打洞的端口有个时间限制的,在一定时间内如果没有数据通讯会自动关闭。

笔者整理了一个两个终端的NAT类型能否打洞成功的对照表:

| A客户端NAT类型 | B客户端NAT类型 | 能否穿透 |
| ------ | ----- |
| 全锥 | 全锥/地址受限制/端口受限制/对称型 | 能打通 |
| 地址受限制 | 地址受限制/端口受限制/对称型 | 能打通 |
| 端口受限制 | 端口受限制 | 能打通 |
| 端口限制 | 对称型 | 不能打通 |
| 对称型 | 对称型 | 不能打通 |

通过这个对照表我们可以看到当两端都是对称型或者一端是对称型,另外一段是端口限制型的时候NAT打洞是无法成功的,那么这种情况下,如何进行端对端的通话呢?
这个问题我们后面再探讨。

好了关于NAT的学习先到此结束了,关注我,一起进步,人生不止coding!!!

WebRTC之NAT穿墙相关推荐

  1. WebRTC音视频原理

    一.什么是WebRTC WebRTC,网页即时通讯(Web Real-Time Communication),是直接在 Web 浏览器内驱动实时通信(语音.视频和任意数据)方法的API.它于2011年 ...

  2. Game as a Service —— 开源云游戏搭载WebRTC

    软件即服务,基础架构即服务,平台即服务,通信平台即服务,视频会议即服务,那么,游戏即服务(Game as a Service)如何呢?已经有不少科技公司试水云游戏,最著名的要数Google的Stadi ...

  3. WebRTC通话原理(六)

    WebRTC通话原理-基本流程 基本流程 WebRTC通话最典型的应用场景就是一对一音视频通话,如微信或QQ音视频聊天.通话的过程是比较复杂的,这里我们简化这个流程,把最主要的步骤提取出来,如图所示. ...

  4. WebRTC通话原理-网络协商-NAT-ICE-STUN-TURN

    作者: 亢少军 彼此要了解对方的网络情况,这样才有可能找到一条相互通讯的链路.需要做以下两个处理. 获取外网IP地址映射. 通过信令服务器(signal server)交换"网络信息&quo ...

  5. WebRTC,P2P技术,IPv6的一些思考

    本文涵盖计算机网络,软件等多方面的知识. 不过放心,这篇文章不会只告诉你p2p"是什么",也不会仅仅告诉你"为什么",而要深刻探讨它的设计"是否合理& ...

  6. 【流媒体】WebRTC基础入门

    WebRTC基础入门 WebRTC概述 WebRTC架构 WebRTC重要类 MediaStream RTCPeerConnection 基本格式 方法分类 媒体协商 Stream/Track 重要事 ...

  7. IPFS星际文件系统(中文白皮书)

    IPFS - 可快速索引的版本化的点对点文件系统 作者: Juan Benet (juan@benet.ai) 译者: 郭光华(gavin@8btc.com) 摘要 星际文件系统是一种点对点的分布式文 ...

  8. IPFS - 可快速索引的版本化的点对点文件系统(草稿3)

    摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的,而IPFS是一个单一的Bittorrent 群集 ...

  9. IPFS白皮书中文版

    IPFS - 可快速索引的版本化的点对点文件系统 摘要 星际文件系统是一种点对点的分布式文件系统, 旨在连接所有有相同的文件系统的计算机设备.在某些方面, IPFS类似于web, 但web 是中心化的 ...

最新文章

  1. 架构设计中服务层的简单理解
  2. TCL脚本语言基础介绍
  3. NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证
  4. LeetCode 329. 矩阵中的最长递增路径(记忆化递归)
  5. 物联网通信技术,那些你不知道的事
  6. Java Swing Mysql学生成绩管理系统
  7. arcgis的numpy模块_数据分析之numpy模块
  8. 【面试题】444- 55 道常见CSS面试题
  9. 惯导系统误差分析(一) 惯性导航系统的误差与误差源
  10. Python进行UDP编程
  11. 实验高中计算机,仿真物理实验室高中完整版
  12. 下载:HD AUDIO For XP SP3修正补丁
  13. Android内存优化:Reckon(二)
  14. Gym-101173K Key Knocking 思维+贪心
  15. linux 用户 组区别吗,Linux用户组之主组和附加组
  16. IOS微信浏览器input输入账号键盘闪烁
  17. FastJson的JSON.isValid()出现BUG!
  18. buck电路 dac stm32_嵌入式设计-基于STM32F334的BUCK同步降压数字电源设计-电路城论坛 - 电子工程师学习交流园地...
  19. 系统吞吐量、QPS、并发数、响应时间,以及提高吞吐量的思路
  20. 在DW中制作网页中的表格

热门文章

  1. R 语言载入包时不显示包的信息
  2. 驶入脱贫“高速路”-国稻种芯-通榆县:稻谷农特产品推送进城
  3. java menuitem,Java AWT MenuItem和菜单
  4. 《口袋妖怪》大战:通过数据分析,一次性揭示最强王者,谁能成为最后的胜者?
  5. android 铃声设置失败,Android设置铃声失败
  6. 设计模式——窗口模式
  7. 笔记本电脑一般能用几年?
  8. android 4.4 webview加载部分https网页白屏
  9. ABBYY FineReader16最新PDF图片文字识别软件
  10. 【ARMv8 编程】ARMv8 指令集介绍