nat穿透原理

标签: nat 原理 | 发表时间:2015-04-01 02:01 | 作者:vanadiumlin
出处:http://www.iteye.com
一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基本上没有人会告诉你如何使用TCP协议去穿透(甚至有的人会直接告诉你TCP协议是无法实现穿透的)。但是,众所周知的是,UDP是一个无连接的数据报协议,使用它就必须自己维护收发数据包的完整性,这常常会大大增加程序的复杂度,而且一些程序由于某些原因,必须使用TCP协议,这样就常常令一些开发TCP网络程序的人员“谈穿透色变”。那么,使用TCP协议是不是就不能实现穿透呢?答案当然是否定的:TCP协议不仅能实现NAT穿透,而且实现起来比UDP穿透甚至还简单一些。

要了解如何使用TCP穿透NAT,就要首先看看如何使用UDP穿透NAT。

我们假设在两个不同的局域网后面分别有2台客户机A和 B,AB所在的局域网都分别通过一个路由器接入互联网。互联网上有一台服务器S。

现在AB是无法直接和对方发送信息的,AB都不知道对方在互联网上真正的IP和端口, AB所在的局域网的路由器只允许内部向外主动发送的信息通过。对于B直接发送给A的路由器的消息,路由会认为其“不被信任”而直接丢弃。

要实现 AB直接的通讯,就必须进行以下3步:A首先连接互联网上的服务器S并发送一条消息(对于UDP这种无连接的协议其实直接初始会话发送消息即可),这样S就获取了A在互联网上的实际终端(发送消息的IP和端口号)。接着 B也进行同样的步骤,S就知道了AB在互联网上的终端(这就是“打洞”)。接着S分别告诉A和B对方客户端在互联网上的实际终端,也即S告诉A客户B的会话终端,S告诉B客户A的会话终端。这样,在AB都知道了对方的实际终端之后,就可以直接通过实际终端发送消息了(因为先前双方都向外发送过消息,路由上已经有允许数据进出的消息通道)。

用UDP来实现以上3步不存在什么理论上的问题,因为UDP是无连接的协议,它允许socket进行“多对一”的通讯(即几个具有不同IP和端口号的socket向一个接收socket发送消息)。但是使用TCP就出现了问题:在一般情况下,TCP socket不允许在已经建立连接的端口上再进行监听和使用该本地端口。换句话说,当AB连接上服务器S后,S将AB的实际终端告诉对方,下一步本该是AB利用对方的实际终端进行直连,但这时你会发现对方的实际终端已经被占用了(就是各自连接到服务器S的会话占用了终端),无法同时listen和 connect。于是很多人得出结论:TCP无法实现NAT穿透。

于是问题的关键变成了如何复用一个TCP连接的本地终端,这其实不是协议的问题,而是一个API的问题。幸运的是,所有主流操作系统都支持一个特定的TCP套接字选项——SO_REUSEADDR。这个选项允许将多个socket绑定到同一个本地终端。我们建立socket的时候只要加上这么一行:

setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &flag, len) ; //C++就这么做

_Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True) '这是vb.net 更加简单

知道上面的知识就很好办了,下面我来说说TCP协议的穿透流程:

机器布局还是和上面使用UDP的一样。现在假设客户A想和客户B建立TCP连接。

首先还是 AB分别和服务器S分别建立连接,S记录AB的互联网实际终端。然后S分别向AB发送对方的实际终端。接着,从A和B向S连接时使用的端口,AB都异步调用connect函数连接对方的实际终端(就是S告诉的终端),同时,AB双方都在同一个本地端口监听到来的连接(也可以先监听,再connect更好)。由于双方都向对方发送了connect请求(假设各自的SYN封包已经穿过了自己的NAT),因此在对方connect请求到达本地的监听端口时,路由器会认为这个请求是刚刚那个connect会话的一部分,是已经被许可的,本地监听端口就会用SYN-ACK响应,同意连接。这样,TCP穿透NAT的点对点连接就成功了。


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [nat 原理] 推荐:

nat穿透原理

- - 开源软件 - ITeye博客
一直以来,说起NAT穿透,很多人都会被告知使用UDP打孔这个技术,基本上没有人会告诉你如何使用TCP协议去穿透(甚至有的人会直接告诉你TCP协议是无法实现穿透的). 但是,众所周知的是,UDP是一个无连接的数据报协议,使用它就必须自己维护收发数据包的完整性,这常常会大大增加程序的复杂度,而且一些程序由于某些原因,必须使用TCP协议,这样就常常令一些开发TCP网络程序的人员“谈穿透色变”.

iptables NAT 学习

- - BlogJava-首页技术区
为了搞清楚iptables NAT的过程,做了这个实验. 使用了1台双网卡服务器和1台单网卡服务器,2个网段. 1.       为了看到调度服务器上的数据转发过程,首先在调度服务器上分出内核的debug日志:. l 在/etc/rsyslog.conf最后增加:kern.debug /var/log/iptables.log.

[转]iptables防火墙与NAT服务

- - 小鸥的博客
iptables防火墙与NAT服务. (1)设置在不同的网络或网络安全域之间的一系列部件的组合,它能增强机构内部网络的安全性. (2)通过审查经过每一个数据包,判断它是否有相匹配的过滤规则,根据规则先后顺序一一进行比较,直到满足其中的一条规则为止,然后依据控制机制做出相应的动作,若都不能满足,则将数据包丢弃,从而保护网络安全.

Xen 虚拟机的 NAT 网络配置

- - vpsee.com
我们使用 Xen 虚拟机的时候一般都是用桥接(bridging)的方式把虚拟机(domU)直接暴露在网络上,就像网络上单独的一台服务器一样,这种方式简单好用,不用在 dom0 做任何的端口转发也不用任何 iptable 规则. 不过除了 bridging 以外,Xen 还支持 routing 和 NAT 的方式配置虚拟机网络.

NAT穿透解决方案介绍

- - 编程语言 - ITeye博客
Agent B看到的source address就是经过转换后的IP和Port并不知道Agent A的局域网地址;当Agent B的响应到达Agent A的NAT设备后,NAT设备查找内存中保存的和这个外网地址相对应的内网地址,如果找到后就将这个data packet转发到这个地址,这样就实现了通信.

Docker 中 NAT 和 HOST 的区别

- - snoopyxdy的博客
官方说明使用Dokcer容器启动应用可以媲美直接在宿主机上启动的性能,宣称使用Docker启动应用大约可以达到原来性能的90%,如此低的性能损耗应当归功于Docker容器虚拟化的轻量级. 但是事实真的如官方所说,仅有10%的损耗吗. 我们下面将比较原生启动 redis 实例和使用Docker启动的性能对比.

NAT穿透(UDP打洞) - heaventouch - 博客园

- -
1、NAT(Network Address Translator)介绍. NAT有两大类,基本NAT和NAPT. 静态NAT:一个公网IP对应一个内部IP,一对一转换. 动态NAT:N个公网IP对应M个内部IP,不固定的一对一转换关系. 现在基本使用这种,又分为对称和锥型NAT. 锥型NAT,有完全锥型、受限制锥型、端口受限制锥型三种:.

udp打洞穿透nat实现p2p GitHub - pannzh/P2P-Over-MiddleBoxes-Demo: A simple demo of P2P communication over middle boxes such as NAT

- -
一个P2P聊天程序,使用UDP打洞创建链接. ./p2pchat/server <服务器端口号> ./p2pchat/client <服务器IP>:<服务器端口号> >>> help. 该UDP打洞示例仅支持锥形地址转换器(Cone NAT),如果两个客户端都在同一个公网结点下,需要确保出口路由器支持.

TPROXY之殇-NAT设备加代理的恶果

- - CSDN博客推荐文章
无独有偶,过了N多年,又到了这个时候,碰到了同样的事情. xx年的万圣节,由于服务器瘫痪我们被罚了500块钱,最终发现瘫痪的原因是TPROXY造成的,当时每个大服务区有一台LVS负载均衡设备,工作在NAT模式下,下联一台核心交换机,核心交换机分出N条线路去往各小区域服务器群,每一个小区域服务群拥有一台TPROXY实现的登录代理服务器,仅仅对登录数据包做代理,其它的包直接通过.

用TCP穿透NAT(TCP打洞)的实现

- - 操作系统 - ITeye博客
    我们假设在两个不同的局域网后面分别有2台客户机A和 B,AB所在的局域网都分别通过一个路由器接入互联网.     现在AB是无法直接和对方发送信息的,AB都不知道对方在互联网上真正的IP和端口, AB所在的局域网的路由器只允许内部向外主动发送的信息通过. 对于B直接发送给A的路由器的消息,路由会认为其“不被信任”而直接丢弃.