网络协议之NAT穿透
NAT
IPv4地址只有32位,最多只能提供大致42.9亿个唯一IP地址,当设备越来越多时,IP地址变得越来越稀缺,不能为每个设备都分配一个IP地址。于是,作为NAT规范就出现了。NAT(Network Address Translation,网络地址转换)是1994年提出的,其当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。每个NAT设备负责维护一个包含本地IP、端口和外网IP、端口的映射表。所有使用本地地址的主机在和外界通信时,都要在NAT路由器上将其本地地址转换成全球IP地址,才能和因特网连接。其大致过程如下:
NAT的实现方式有如下三种,即:
- 静态转换(Static NAT):将内部网络的私有IP地址转换为公有IP地址,IP地址对是一对一的,是一成不变的,某个私有IP地址只转换为某个公有IP地址;
- 动态转换(Dynamic NAT):将内部网络的私有IP地址转换为公用IP地址时,IP地址是不确定的,是随机的,所有被授权访问上Internet的私有IP地址可随机转换为任何指定的合法IP地址,当ISP提供的合法IP地址略少于网络内部的计算机数量时。可以采用动态转换的方式;
- 端口多路复用(Port NAT):改变外出数据包的源端口并进行端口转换,即端口地址转换。采用端口多路复用方式,内部网络的所有主机均可共享一个合法外部IP地址实现对Internet的访问,从而可以最大限度地节约IP地址资源。同时,又可隐藏网络内部的所有主机,有效避免来自internet的攻击。因此,目前网络中应用最多的就是端口多路复用方式。
UDP连接状态超时
目前,很多网络都使用了NAT技术,而NAT需要保存数据传输的路由表才能完成工作。每个TCP连接有一个明确的协议状态机,开始三次握手,跟着开始数据传输,最后关闭连接,有一个完整的流程。基于这种流程,NAT可以观察到每个连接状态,并可以根据需要创建和删除的路由条目。
然而,UDP是面向无连接的,仅仅只往外发送一个带有载荷的数据报就不再关心其他额外的事情了,但路由响应却需要能从转换表找到本地主机IP和端口,只有如此才能完成数据的传输。UDP既没有握手,也没有连接终止,同时没有任何状态机来监控连接状态。转换器需要保存每个UDP流的状态,进而维护转换表,然而UDP实际上却是无状态的,仅仅只是一个数据报而已,没有提前协商报文,也没有结束状态。由于UDP没有连接终止通告,任何时候,两端都可以停止发送数据包,不带任何通知,就对为维护转换表带来了极大的挑战,因为转换表大多数时候都是动态更新的。为了解决这个问题,UDP路由记录会设置一个定时器进行定时过期,这个时间的设置取决于设备提供商,版本,配置等。因此,有一个事实上的最佳做是引入双向 keepalive报文,周期性的重置路由上所有的NAT设备转换记录计时器。
NAT穿透
不可预知的连接状态管理是NAT的一个严重问题,但对于许多应用程序的一个更大的问题是根本无法建立UDP连接。这对很多应用譬如P2P,如VoIP、游戏、文件共享等,这些应用往往通信双方的角色需要转换,以实现双向通信。
NAT带来的第一个问题是,内部客户端不知道它的外网IP,只知道它的内部IP,NAT设备负责对UDP数据报进行重写,修改UDP包的源端口和地址,以及IP分组中的源IP地址。如果客户端使用内网IP地址与外网主机进行通信,那么连接将不可避免地失败。因此,NAT这种“透明”的转换就有问题了,如果它需要与外网中的主机进行通信,应用程序必须先知道自己的外网IP地址。
然而,仅仅知道的自己的外网IP依然是无法保证UDP传输成功的。任何数据包到达拥有外网IP的NAT设备后,还需要有一个目的端口,才能从NAT转换表中找到对应的内网IP和端口,这样数据才能真正达到目的地址。如果不能在转换表中找到对应的映射,那么数据报就被直接丢弃。也就是说NAT作为一个简单的包过滤器,只有在转换表中找到对应的路由,才能完成信息传递,否则就会不能成功传输数据。
如果隔着NAT设备,那种客户端(内网主机作为服务器)处理来自P2P应用(如VoIP,游戏终端,文件共享等)的入站连接时,就需要面对NAT穿透问题。为了解决这种UDP穿透问题,很多穿越技术(STUN,TURN,ICE)被提出了,用于在UDP主机之间建立端至端的连接。
STUN
STUN(Simple Traversal Utilities for NAT)协议允许让位于内网的客户端发现网络中的地址转换器,进而找到NAT为自己配置的外网IP和端口。要想实现这种功能,还需要一个已知的第三方STUN服务器支持,示意图如下:
假设STUN服务器的IP地址是可知的(通过DNS或手动指定),客户端首先发送绑定请求到STUN服务器。相应的,STUN服务器回复一个响应,其中包含为客户端分配的外网IP和端口。这个简单的流程解决我们了我们前面讨论中遇到的几个问题:
- 客户端可以知道自己的外网IP和端口,使用这些信息就能够与对端进行通信;
- 向STUN服务器发送的请求,也同时在NAT上建立了路由映射记录,这确保了外部主机的请求可以发送到内部网络中的客户端;
- STUN协议定义了一个简单keep-alive探测机制来保证NAT上的路由不超时。
有了这个机制,两端需要通过UDP进行通信时,它们会先发送绑定请求到各自的STUN服务器,收到各自STUN服务器的响应,然后分别使用各自的外网IP和端口进行通信。然而,在实际应用中,STUN是不足以处理所有的NAT的拓扑结构和网络配置。在某些情况下,UDP可能会被防火墙或其他一些网络设备完全阻止 ,为了解决这个问题,我们还可以使用TURN协议作为备用方案,它可以运行在UDP上,在最坏的情况下还可以将UDP转换成TCP。
TURN
TURN(Traversal Using Relays around NAT)通过Relay方式穿越NAT,TURN应用模型通过分配TURNServer的地址和端口作为客户端对外的接受地址和端口,即私网用户发出的报文都要经过TURNServer进行Relay转发,在报文负载中所描述的地址信息直接填写TURNServer地址的方式进行通信。示意图如下所示:
当然,这种通信方式的最明显的缺点就是它不再是P2P的通信。他需要依赖于TURN服务器来保证可靠的传输,TURN服务器就成为了一个瓶颈,维护TURN的成本将很高,至少TURN服务器需要足够的带宽来保证所有的数据流。因此,TURN方案最好作为最后的备用方案,只有在其他方案都失效的情况下才能使用。
在现实场景中,NAT设备很多,相当一部分用户不能通过STUN直接建立p2p连接,如果想提供可靠的UDP服务,还需要同时支持STUN与TURN。
ICE
建立一个有效的NAT穿越解决方案,不是一件简单容易的事情。值得庆幸的是,我们可以借助ICE协议来帮助我们完成这一任务。ICE是一个协议,和一组方法,用来寻求最有效的端与端之间隧道建立方法:如果可能则直接连接,如果不行则通过STUN进行协商,如果都失败了则采取TURN。示意图如下:
UDP相比于TCP最大的特征正是它忽略了的功能:连接状态、握手、重发、重组、重排、拥塞控制、拥塞预防、流量控制,甚至可选的错误检查。任何事情都是有利有弊的,在忽略了这么多特性之后,这个面向消息的传输层能提供了很大的灵活性,当然也为实现者带来了一些麻烦。客户端的应用程序可能从头开始重新实现部分或者大部分缺失的特性,而且每项功能的实现都得保证与网络中其他主机与协议和谐共生。
与TCP不同,内置了流量和拥塞控制、拥塞避免机制,UDP应用程序必须自己实现这些机制。拥塞不敏感的UDP应用程序可以很容易的拥塞网络,可能会导致网络性能降低,在严重的情况下,会导致网络拥塞崩溃。如果想在自己的应用程序中使用UDP,一定要认真研究和学习当下的最佳实践和建议。RFEC5405对设计单播UDP应用程序给了很多建议,简述如下:
- 应用必须忍受变化的互联网路径;
- 应用应控制传输速率;
- 应用应当实现所有流量拥塞控制;
- 应用应该使用和TCP同等的带宽;
- 应用当丢包时应该回退重传计数器;
- 应用不应该发送超过MTU的数据报;
- 应用应该处理数据报的丢失,重复,重新排序;
- 应用应该是确保可以支持两分钟的延迟;
- 应用应该启用IPv4 UDP校验,必须启用IPv6校验;
- 应用可能在需要的时候使用保活(最小间隔15秒)。
随着WebRTC规范的提出,WebRTC为浏览器提供了新的能力,相信UDP会变得越来越重要!
相关文章
网络协议之NAT穿透的更多相关文章
- 使用TCP协议的NAT穿透技术
一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基本上没有人会告诉你如何使用TCP协议去穿透(甚至有的人会直接告诉你TCP协议是无法实现穿透的).但是,众所周知的是,UDP是一个无连 ...
- 使用TCP协议的NAT穿透技术(转)
其实很早我就已经实现了使用TCP协议穿透NAT了,但是苦于一直没有时间,所以没有写出来,现在终于放假有一点空闲,于是写出来共享之. 一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基 ...
- 使用TCP协议的NAT穿透技术 (转载)
其实很早我就已经实现了使用TCP协议穿透NAT了,但是苦于一直没有时间,所以没有写出来,现在终于放假有一点空闲,于是写出来共享之. 一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基 ...
- p2p网络中的NAT穿透技术----常见NAT穿越解决方案
转:http://blog.csdn.net/cllzw/article/details/46438257 常见NA丁穿越解决方案 NAT技术在缓解IPv4地址紧缺问题.构建防火墙.保证网络安全等方面 ...
- 网络协议之TLS
前言 由于在TCP.UDP等方式传输数据时,数据包有可能被其他人截获,并解析出信息,这就给信息安全带来了很大的挑战.最初的SSL协议被网景公司提出,它不会影响上层协议(如HTTP.电子邮件等),但可以 ...
- 网络协议之UDP
前言 TCP协议在不可靠的网络环境上提供了可靠的通信通道,隐藏了大量的底层细节,使应用程序更加简洁.但有些应用并不需要这么高的可靠性,并不需要按序交付,而且TCP为了提高可靠性也增加了延时,在某些对延 ...
- 网络协议之TCP
前言 近年来,随着信息技术的不断发展,各行各业也掀起了信息化浪潮,为了留住用户和吸引用户,各个企业力求为用户提供更好的信息服务,这也导致WEB性能优化成为了一个热点.据分析,网站速度越快,用户的黏性. ...
- 《c# 实现p2p文件分享与传输系统》 二、 设计 - 续(NAT穿透)
c#实现P2P文件分享与传输系统 二.设计 - 续(NAT穿透) 首先要抱歉,因为这些日子较忙,没有写文章,这个系列拖了很久,现在开始继续. 上一篇文章介绍了p2p系统Tracker Server和 ...
- NAT穿透解决方案介绍
最近公司要实现在各种网络环境下面的多屏互动(机顶盒.android phone.iphone及PC端)的需求:由于IP地址资源有限的原因,目前我们使用的各种终端设备都位于局域网后面也就是多台设备共享同 ...
随机推荐
- NOIWC2017&&THUWC2017 滚粗记
因为NOI WC的时候一直在生病,浑浑噩噩就过去了7天,基本没什么记忆了,所以就压到一篇里好了. day -1 第一次发现高铁的椅子原来还可以转过来,于是我们四个小伙伴面对面愉快的打了一路宣红A. 在 ...
- chromedriver 代理设置(账号密码)
在使用selenium时遇到的一个问题 如何为chromedriver设置有密码的代理 在借鉴了stackoverflow上的答案 background.js var config = { mode: ...
- 【位运算】判断一个数是否为2的n次方
import java.util.Scanner; /** * 功能:用位运算,判断一个数是否为2的n次方. * 思路:用1做移位操作,然后判断移位后的值是否与给定的数相同. */ public cl ...
- UnityShader 序列帧动画效果
实现原理:主要思想是设置显示uv纹理的大小,并逐帧修改图片的uv坐标. 实现步骤 1.我们首先用_Time.y和速度属性_Speed相乘得到模拟的时间. 2.然后我们用time除以_Horizonta ...
- vue2.0实战记录
1. 初始化项目vue init webpack caseone cd caseonecnpm installcnpm install less less-loader -Dcnpm install ...
- python---基础知识回顾(五)(python2.7和python3.5中的编码)
Unicode 和 UTF-8 有何区别? python基础之字符编码 以上两篇看懂即可,那下面的就不需要看了 python标准数据类型 Bytes python--数据类型bytes Python ...
- vue 倒计时返回首页
1. vue页面15分钟无操作时返回首页 2. 基于vue的倒计时demo 3. 在vue2.0项目中一个简单的倒计时功能 4. vue重新发送验证码 5. 表格<td>里面文字垂直显示
- vue-router 实践
1. vue-router2学习实践笔记 2. router.push() 3. 使用vue-router跳转页面
- tips 前端 bootstrap 嵌套行 嵌套列 溢出 宽度不正确 栅格化系统计算
bootstrap 当嵌套列时 有时会出现很奇异的row 的width不对问题出现的情况时 <div class="row" > <!--row a--> ...
- 2008ZJOI树的统计
codevs 2460 树的统计 http://codevs.cn/problem/2460/ 2008年省队选拔赛浙江 题目等级 : 大师 Master 题目描述 Description 一棵 ...