一种基于SYN注入式的TCP打洞技术SYNI

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

一种基于SYN注入式的TCP打洞技术—SYNI编译:HyoSoft原文:SYNI–TCPHolePunchingBasedonSYNInjection作者:SebastianHolzapfel,Matth¨ausWander,ArnoWacker,TorbenWeis/UniversityofDuisburg-Essen,DistributedSystemsGroup/Bismarckstraße90,47057Duisburg,Germany前言:互联网IP地址的短缺,IPv4过渡至IPv6进度缓慢,导致目前大多数仍然是通过NAT(网络地址转换)路由器上网。通常位于NAT路由器之后的上网设备无法从外网连接,然而,有很多网上应用需要接受外来连接,例如基于点对点技术的IP电话服务。有一些特别的技术可以绕过这种限制,叫做“NAT穿越”,而“打洞”则是NAT穿越的其中一种形式。本文分析对比一些已有的TCP打洞技术原理,和提出一种新的TCP打洞方案,通过从内网向本地路由器注入一个SYN包以达到打洞的目的。一个基于TCP打洞的远程办公软件已成功开发出来:Rdesk远程办公通道。1.0版本使用了本文中介绍的较为简单的TCP打洞方法,但亦能适用于大多数家用NAT路由器。该软件支持使用微软远程桌面进行远程办公,您可从下载使用。文本的目的除了介绍打洞的新方法,亦让读者对TCP打洞原理能有透彻的理解,可以在实践中实施自己的思路和方法。本文假设读者已熟悉Socket编程,对三次握手建立连接的过程有一定的了解,如果之前已了解过UDP打洞的基本原理,则更有助于理解本文的内容。1、介绍网络地址转换(NetWorkAddressTranslation,NAT)是解决互联网IP短缺的一种有效方案。目前世界上超过70%的上网电脑都是位于NAT路由器之后。如果互联网能够普及使用IPv6,那当然有充足的IP地址提供给世界上几乎每一台上网终端,但目前来看遥遥无期,NAT在相当长时间内仍将是访问互联网的主要方式。使用NAT路由器,多台电脑能够共享一个公网IP访问互联网,路由器后面的电脑只配置为私网IP。普通的路由不会对IP报文进行修改,只会根据路由表直接转发。而NAT路由器则把来自私网的数据包源IP地址/端口转换成公网IP地址/端口,发送至互联网,同时将来自互联网的相应的数据包的目的IP地址/端口转换为私网目的地址在内网发送,内网主机能透明地访问互联网。路由器的公网IP相对外网是可见的,但不能从外网直接访问位于路由器之后的内网主机。因此导致了一个问题,一些服务例如IP电话等,需要接受由外网发起的连接,但被路由器阻隔,不能正常工作。因此,一种叫做“NAT穿越”的技术方案被提了出来。在路由器设置端口映射(Mapping)是NAT穿越有效办法,有一种NAT穿越技术叫UPnP,一般NAT路由器都内置了此功能,它能实现内网主机向路由器主动请求端口映射,其使用简单,但由于一些原因,几乎所有路由器出厂设置都是禁用UPnP的。在一些场合,使用者无法自行启用UPnP,则打洞技术就非常必要了。打洞过程只需由内网主机向目的外网主机发送一个数据包,NAT路由器就会建立一条映射,允许目的外网主机反向进入和连接相应的内网主机。由于UDP协议的无连接性,UDP打洞比TCP打洞更容易实现。然而,很多应用要求可靠数据传输,而UDP为不可靠传输协议。尽管一种叫RUDP的协议能够提供基于UDP的可靠通讯,但大多数场合,使用成熟的TCP通讯方式无疑是更好的选择。我们的目标在于实现一种高成功率的基于TCP的打洞机制。为达目的,我们分析了各种路由器的特性,尽量让TCP打洞具有通用性。同时这种方法在实践中证明是非常壮健的,例如无需苛刻的时序约束等,否则在编程中难以实现。在本文中我们介绍了一种新的NAT穿越技术:SYN注入式TCP打洞。我们简称为SYNI(SYNInject)。该技术能使一个位于内网主机对位于另一个内网的主机实现TCP连接,基本原理是:从一个内网的主机向另外一个内网的路由器发送一个SYN包(TCP连接请求包),另一个内网主机也进行同样的操作。但这两个SYN包是不能到达对方内网的,因为双方都有NAT路由器阻隔。2、系统模型我们定义了一个固定系统模型,这个模型将会适用于下文中所有穿越方式。我们总假设通讯双方主机(Host)都是通过NAT路由器(Router)上网,可能是位于一个甚至多级NAT路由器之后。而且总假设这些主机已知道对方主机的路由器公网IP及发送数据包所分配的端口(Endpoint)。大多数NAT路由器(除SymmetricNAT),当内网主机在本机绑定某个TCP端口向外连接,路由器转换数据包时会保持该端口值作为EndPoint源端口。打洞连接过程双方主机需要交换一些信息,需要建立一个公共通道。例如可以在公网放置一个双方都可以直接访问的第三方服务器。有些系统直接使用了第三方公网服务器来中转通讯数据,而无需打洞,例如TeamViewer软件所使用的连接方式,但这种通讯方式相比直接连接会慢很多,因此一般第三方服务器只用来于协助打洞连接。此外第三方服务器还可以用来获取双方路由器的公网IP等信息。3、基础知识我们先来讨论位于NAT路由器之后的两个主机尝试与对方建立TCP连接时,会发生什么。一个已经建立的TCP连接,路由器的动态映射表会有一个相应的映射记录,如目标主机公网IP:1234本地NAT路由器端口5678本地私网主机IP:5678,路由器会转发符合每条记录中相应的数据包。如果内网需要与外网建立TCP连接,首先需要发送一个SYN包请求连接,例如源为“本机私网IP:5678”,目的为“公网IP:1234”,路由器是允许此连接初始包通过,并进行源转换和发至公网的,此时路由器就会建立一个与上面类似的映射,即是在本地路由器打了一个洞。但当这个SYN包到达对方路由器时,由于对方路由器不存在相应的映射,则对方路由器可能会直接丢弃,或回应一个标记为“目标不可到达”的ICMP包,又或者会回应一个拒绝TCP包(RST)。相比Socket超时错误,返回一个拒绝连接错误,对于Socket通常是致命的,而且这个错误会导致本地路由器删除当前已建立的映射记录。因此,大多数的TCP打洞方法,都需要保证在发送某些数据包时,既可以通过本地路由器而又不到达对方的路由器。为了达到这样的要求,需要修改减少IP报文的TTL值(TimeToLive),使报文在到达目的地之前就被丢弃。TTL值的选择一定要小于本地主机与目标主机之间的路由跳数。一般来说,当主机只位于一层路由器之后,则TTL固定为2就能保证达到这样的效果。如果是多级路由器,则在打洞之前主机需要确定合适的TTL值,保证IP包能通过所有本地路由器到达公网,并且不能返回“不可到达错误”或RST,即在所有本地路由器都打一个洞。这个可以通过递增TTL值,重复发送TCP或UDP包,直至检测到“目标不可到达”ICMP错误或RST错误,则上一个TTL值就是可用最大值。当数据包不能达到目的地,会返回一个ICMP超时包(TimeExceed),对于一般的操作系统和路由器,这个信息通常不会认作是一个错误。当主机发送了一个Low_TTL值的SYN包,就在路由器打了一个洞,使路由器生成了一个映射记录。我们期望有了这个洞,路由器就能允许外网主机发送SYN包进来,与内网主机开始建立TCP连接。的确有些路由器是这样,虽然支持这种简单打洞的路由器类型不多,但大多数人家用的路由器其实都是支持这样的方式。如果只希望实现单向连接功能,使用这种方式已经对大多数路由器都是合适的。Rdesk1.0就是使用这种方式,能实现从实现办公电脑对家庭内网电脑进行单向连接。但在相当多类型的NAT路由器,这个映射是有别于已建立连接后的映射的。我们知道,一个标准的TCP连接需要三次握手过程:1、连接:SYN(a/0)|2、回应:SYN/ACK(b/a+1)|3、确认:ACK(a+1/b+1)。其中a为从A端发送的初始序列号,b为从B端发送的初始序列号。如果路由器严格安装此标准建立连接,则在内网主机发送一个SYN后,路由器可能会只等待从外网返回的是SYN/ACK包,而不是我们期望的允许SYN包进入,如果从外网返回的是一个SYN包,路由器有可能会当作是非法包而丢弃,甚至向对方回应ICMP错误或RST。在内网方向,路由器允许一个SYN包通过后,亦可能只会等待下一个来自内网主机的包是ACK包,其他包则认为是非法。同时,标准的TCP握手过程是要求序列号一致的。4、SYNI方式我们上一节已描述了TCP打洞原理,它是依靠从内网向本地NAT路由器注入一个SYN包来实现。现在我们假设一个位于路由器Ra后面的内网主机HostA,试图与另一个位于路由器Rb后面的内网主机HostB建立连接。图一:SYNI--虚线表示双方之间的公共消息通道如图一所示,我们的SYNI方法包括四个步骤。它需要符合一些与HostA、HostB的操作系统有关的先决条件,同样Ra、Rb亦有需符合一定的条件。这里我们标记这些条件为P1,P2...P(x)等,因为在第六节将SYNI与其他打洞方式比较时我们会使用这些条件。第一步,我们会在主机HostA建立一个TCP套接字(SocketA),设置其为上一节中已找到的Low_TTL值,然后对HostB的外网IP及已知的端口号进行连接(Connect)。与此同时,HostA需要创建能够检测及发送RawPacket的RawSocket,和开始检测对发向外网的IP包(P1,条件一:操作系统可以实现RawSocket检测和发送IP包)。通过IP包检测,可以分析TCP初始连接时发送的SYN包中ISN字段信息(InitialSequenceNumber,初始序列码),即上一节介绍三次握手协议中的小写a。这里需要路由器Ra支持,即路由器不会对发送的SYN包中的ISN信息进行修改(P2,条件二:路由器不会修改SYN包的ISN)。一些路由器会用一个偏移量修改ISN,以防止IP欺骗。当然一般的NAT路由器是不会这样做的,在我们的测试中也没有遇到过这种路由器。当这个SYN包到达路由器Ra,Ra会建立一个映射,和将这个SYN包向目的路由器Rb包发送。由于使用了Low_TTL,SYN包不会到达Rb,会在互联网中途某个路由器被丢弃,而不会返回ICMP错误或RST。SYN所经过的每一个互联网路由器可能都会返回一个ICMP超时信息,Ra可能会丢弃这些信息,或会把这些信息返回给HostA。无论如何,一般来说Ra仍然可以保持之前的映射,和SocketA不会终止连接,会继续等待返回一个SYN/ACK包(P3,条件三:内网主机及路由器忽略ICMP超时信息)。HostA通过第三方服务器通知HostB已开始连接,和告知所发送的SYN包中的ISN信息。第二步,HostB获知A已开始连接后,同样启动一个RawSocket,构建一个目的为Ra的模拟SYN包,设置一个随机的ISN值c,和同样设置为Low_TTL进行对外发送。同理,此时Rb亦会建立一条映射记录。第三步,HostB建立一个SocketB,不需要修改TTL,立即进行侦听(Listen)。B使参考A发送的SYN包,用RawSocket构建一个模拟SYN(a/0)包进行发送,发送后即可关闭RawSocket。SocketB接收到该包,会以为是从A发送过来的的SYN包,则会立即以Ra为目的地对外发送一个SYN/ACK(b/a+1)包。由于这个SYN/ACK包拥有正常的TTL值,可以通过互联网传送至Ra。第四步,由于之前Ra已建立了映射,并在等待第二次握手,从B发送过来的SYN/ACK包则可以通过Ra送至HostA。HostA接受到该包后,会执行第三次握手,SocketA随即会发送一个ACK包(a+1/b+1),此时HostA三次握手完成并返回连接成功。但由于之前SocketA已设置为LowTTL,这个ACK包可以通过Ra发送至互联网,但不能到达Rb和HostB。而且在SocketA开始

1 / 8
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功