一、NAT穿透
在计算机科学中,NAT穿越(NAT traversal)涉及TCP/IP网络中的一个常见问题,即在处于使用了NAT设备的私有TCP/IP网络中的主机之间建立连接的问题。
会遇到这个问题的通常是那些客户端网络交互应用程序的开发人员,尤其是在对等网络和VoIP领域中。IPsec VPN客户普遍使用NAT-T来达到使ESP包通过NAT的目的。
尽管有许多穿越NAT的技术,但没有一项是完美的,这是因为NAT的行为是非标准化的。这些技术中的大多数都要求有一个公共服务器,而且这个服务器 使用的是一个众所周知的、从全球任何地方都能访问得到的IP地址。一些方法仅在建立连接时需要使用这个服务器,而其它的方法则通过这个服务器中继所有的数 据——这就引入了带宽开销的问题。
两种常用的NAT穿越技术是:UDP打洞和STUN。除此之外,还有TURN, ICE, ALG,以及SBC。
目录
NAT traversal 与 IPsec
为了实现IPsec应用于NAT之上, 下列的协议必须实作于 firewall:
- Internet Key Exchange (IKE) - User Datagram Protocol (UDP) port 500
- Encapsulating Security Payload (ESP) - IP protocol number 50
或者是 NAT-T 之例:
- IPsec NAT-T - UDP port 4500
在家庭路由器上,这通常通过启用"IPsec穿透"来实现。
IETF 文献
- RFC 1579 - Firewall Friendly FTP
- RFC 2663 - IP Network Address Translator (NAT) Terminology and Considerations
- RFC 2709 - Security Model with Tunnel-mode IPsec for NAT Domains
- RFC 2993 - Architectural Implications of NAT
- RFC 3022 - Traditional IP Network Address Translator (Traditional NAT)
- RFC 3027 - Protocol Complications with the IP Network Address Translator (NAT)
- RFC 3235 - Network Address Translator (NAT)-Friendly Application Design Guidelines
- RFC 3715 - IPsec-Network Address Translation (NAT) Compatibility
- RFC 3947 - Negotiation of NAT-Traversal in the IKE
- RFC 5128 - State of Peer-to-Peer (P2P) Communication across Network Address Translators (NATs)
相关技术
NAT 穿透技术与 NAT 行为
- Session Traversal Utilities for NAT (STUN)
- Traversal Using Relay NAT (TURN)
- NAT-T Negotiation of NAT-Traversal in the IKE
- Teredo tunneling uses NAT traversal to provide IPv6 connectivity.
- Session Border Controller (SBC)
- UDP打洞(UDP hole punching)
- TCP打洞(TCP hole punching)
- ICMP打洞(ICMP hole punching)
NAT 穿透基于 NAT 控制
- Realm-Specific IP (RSIP)
- Middlebox Communications (MIDCOM)
- SOCKS
- NAT Port Mapping Protocol (NAT PMP)
- Internet Gateway Device(IGD)协定, 由通用即插即用(UPnP)论坛所定义。
- Application Layer Gateway (ALG)
NAT 穿透整合技术
University research papers
- Cornell University - Characterization and Measurement of TCP Traversal through NATs and Firewalls
- Columbia University - An Analysis of the Skype Peer-to-Peer Internet Telephony
- Peer to peer communication across Network Address Translators (UDP Hole Punching)
- Internet By All Means - An article on how to maximize your chances to get around firewalls
外部链接
二、UDP打洞
在计算机科学中,UDP打洞指的是一种普遍使用的NAT穿越技术。
描述
通过UDP打洞实现NAT穿越是一种在处于使用了NAT的私有网络中的Internet主机之间建立双向UDP连接的方法。由于NAT的行为是非标准化的,因此它并不能应用于所有类型的NAT。
其基本思想是这样的:让位于NAT后的两台主机都与处于公共地址空间的、众所周知的第三台服务器相连,然后,一旦NAT设备建立好UDP状态信息就转为直接通信,并寄希望于NAT设备会在分组其实是从另外一个主机传送过来的情况下仍然保持当前状态。
这项技术需要一个圆锥型NAT设备才能够正常工作。对称型NAT不能使用这项技术。
这项技术在P2P软件和VoIP电话领域被广泛采用。它是Skype用以绕过防火墙和NAT设备的技术之一。
相同的技术有时还被用于TCP连接——尽管远没有UDP成功。
算法
假设有两台分别处于各自的私有网络中的主机:A和B;N1和N2是两个网络的NAT设备,分别拥有IP地址P1和P2;S是一个使用了一个众所周知的、从全球任何地方都能访问得到的IP地址的公共服务器
步骤一:A和B分别和S建立UDP连接;NAT设备N1和N2创建UDP转换状态并分配临时的外部端口号
步骤二:S检查UDP包,看A和B的端口是否是正在被使用的(否则的话N1和N2应该是应用了端口随机分配,这会让打洞变得更麻烦)
步骤三:如果端口不是随机化的,那么A和B各自选择端口X和Y,并告知S。S会让A发送UDP包到P2:Y,让B发送UDP包到P1:X
步骤四:A和B通过转换好的IP地址和端口直接联系到对方的NAT设备;
UDP打洞实验
两台没有外网 IP、在 NAT 后边的主机如何直连?UDP打洞通常可行,但是需要第三方服务器。方法如下:
在服务器 S 上监听一个 UDP 端口,在收到 UDP 数据包后把源地址发回去。代码如下(github):
import sys import time import socket def main(port): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(('', port)) try: while True: data, addr = s.recvfrom(4096) back = 'Your address is %r\n' % (addr,) s.sendto(back.encode(), addr) print(time.strftime('%Y-%m-%d %H:%M:%S'), addr, 'just sent us a message:', data.decode('utf-8', 'replace'), end='') except KeyboardInterrupt: print() if __name__ == '__main__': try: main(int(sys.argv[1])) except (ValueError, IndexError): sys.exit('which port to listen?')
主机 A 发送数据包:
$ socat readline udp:xmpp.vim-cn.com:2727,sourceport=4567 my addr? Your address is ('a.b.c.d', 40060)
输入任意消息并回车,一个 UDP 就从本地的 4567 发送出去了。从上述示例我们可以看到,NAT 设备转发时是从 40060 端口发送出去的。为了让服务器返回的数据能够到达内网主机,在一段时间内,NAT 设备会记住外网来自 40060 端口的 UDP 数据包要发送给主机 a.b.c.d 的 4567 端口。完全圆锥型NAT不会在意外部数据包是从什么地方发回来的。受限圆锥型NAT会忽略掉其它主机的数据包,上例中只认可来自 xmpp.vim-cn.com 的数据包。端口受限圆锥型NAT更进一步地要求源端口(上例中是 2727)必须跟之前发出的数据包的目的端口一致。当然,「之前发出的数据包」不必是最后一个。所以,除了最后一种——对称NAT——之外,其它类型的NAT都是有可能成功穿透的。参见维基百科条目网络地址转换和STUN。
后来通过 pystun 程序,我得知我所处的 NAT 是完全圆锥型的。
在知道 A 的发送地址后,主机 B 就可以向这个地址发送数据了。接下来的操作使用 socat 命令就是:
# host A $ socat readline udp-listen:4567 # host B $ socat readline udp:A:4567
然后 B 先发送数据让 A 知道 B 的地址(socat 会 connect 到这个地址),双方就可以相互通信了。当然,因为是 UDP 协议,所以通信是不可靠的,丢包啊乱序啊都有可能
参考文献:
udp打洞实验 http://lilydjwg.is-programmer.com/2012/8/28/udp-hole-punching-experiment.35350.html
相关推荐
就是非常有名的“UDP打洞技术”,UDP打洞技术依赖于由公共防火墙和cone NAT,允许适当的有计划的端对端应用程序通过NAT“打洞”,即使当双方的主机都处于NAT之后。这种技术在 RFC3027的5.1节[NAT PROT] 中进行了重点...
C# UDP穿越NAT,UDP打洞,UDP Hole Punching源代码
用C# 实现 UDP 穿越NAT UDP打洞 有全部源码和原理阐述
udp 穿透, 传透NAT,打洞。不仅有文档的介绍,将原理介绍清楚,而且有可以直接运行的源码。学习udp打洞的好资料。
使用C#实现udp打洞穿透nat udp打洞源码服务端和客户端C# 实现
C#UDP打洞NAT C#UDP打洞NAT C#UDP打洞NAT
UDP穿越NAT,UDP打洞,UDP Hole Punching 本程序分为客户端和服务端,服务端需要放在一台公用的外网服务器上,客户端运行前需要修改ip.ini文件的外网服务器信息。 Licenses /// <summary> /// 聊天消息 ///...
UDP穿越防火墙的例子,有助于学习UDP打洞原理哦。
UDP 在外网环境中不同网段的NAT穿透,网上很多的 资料,但是基本上都是理论知识,而且java的代码很少。 我光是找资料就花了100多积分,经过这些天的努力, 终于被我解决了这个问题。现将完整项目共享给大家。 在test...
UDP打洞NAT代码,是VC6.0的工程,绝对可以编译成功,服务端在公网IP阿里云的window端,两端客户端在本地电脑和虚拟机中,可以进行点对点进行通信,大家可以参考下!
java 实现内网穿透,udp 打洞,NAT 穿透原理 1,客户端A登陆的时候,发送一个UDP数据包给服务器,然后服务器根据该包获得客户端A的IP和端口并保存到UdpAddressMap(用登录名作为key保存)中。 2,客户端A执行操作的...
UDP打洞相关的资料,包括原理,说明,以后相关的源码,是学习udp打洞的绝好资料。自己用过,感觉不错。
不对称NAT穿透原理与一种简单的NAT穿透解决方案的讲述
使用UDP打洞的p2p聊天程序,程序分为一个服务器和一个客户端,适用于穿越一般情况下的NAT
UDP打洞原理,Delphi演示 对于Cone NAT.要采用UDP打洞.需要一个公网机器C来充当”介绍人”.内网的A,B先分别和C通信.打开各自的NAT端口.C这个时候知道A,B的公网IP: Port. 现在A和B想直接连接.比如A给B发.除非B是Full ...
C# UDP穿越NAT打洞,可在广域网实现仿qq即时通讯,点对点发送消息。
用Java实现的UDP穿透NAT技术,内有详细的注释,完全可以自己看懂的
UDP穿透NAT的原理与实现
C# udp NAT打洞客户端,可以实现不能局域网的通信,亲测,测试请需要设置一个IP地址,这个IP地址为外网的IP地址,如果没有外网的IP地址,请通过路由器设置DMZ主机地址,也可以实现外网的功能,UDP NAT的原理可以在我...
在传输数据时需要进行打洞处理,这样才能进行点对点传输数据,资源文件是通过UDP打洞的源码,使用C++开发,在Windows上验证通过,仅限于学习测试,请勿使用在商业用途上。