HF_Cherish

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1. TCP与TCP/IP协议族

TCP是TCP/IP协议族中运输层的一个协议。TCP/IP,即传输控制协议/网间协议,是一个工业标准的协议集,包含了运输层、网络层和链路层的协议,其结构如下图所示:其中socket是API接口,它将TCP/IP协议族包装了起来,应用层通过socket抽象层在网络中传输数据。

2. TCP特点

  1. 面向连接的运输层协议。即在传输数据之前,都要通过三次握手建立连接;关闭连接时,通过四次挥手关闭连接。这也是TCP协议区别于UDP协议的地方,是TCP提供可靠运输的基本原理,是TCP最最基本和重要的特性。而UDP因为不用连接和确认,所以效率高很多,但是质量就不保证。
  2. 每一条TCP连接唯一地被通信两端的两个端点(套接字)所确定。这也是TCP面向连接这一基本特性的体现,即它需要标识每一条连接的两个端点。这个端点叫做套接字(socket),用IP地址和端口号合起来表示一个socket:
    1. 套接字socket = (IP地址:端口号)
    2. TCP连接 = {socket1, socket2} = { (IP1: port1), (IP2: port2) }
  3. 提供可靠交付。即通过TCP连接传送的数据:无差错、不丢失、不重复、按序到达。相对的,UDP就是不可靠交付。这是以面向连接这个特性作为基础,辅以下述措施实现:
    1. 停止等待协议:发送完一个分组就停止发送,等待对方确认,需要处理超时重传
    2. 连续ARQ协议:ARQ(automatic repeat request)是自动重传请求,指使用超时重传及确认丢失和确认迟到机制的协议,其重传请求自动进行的,不需要接收方请求。而连续ARP协议指:维护发送窗口,连续发送窗口内的m个分组,不需要发一个等一次确认,接收方一般采用累积确认(对按序到达的最后一个分组确认),这样可以提高信道利用率。连续ARQ协议阐述了滑动窗口协议的基本概念。
    3. 滑动窗口协议:TCP协议的精髓所在,由此也可以加速传输,并实现流量控制。连续ARQ中也讲了,一次把滑动窗口内的数据都发送出去,接收方对按序到达的最大序号给出确认,如果收到确认(可以累积确认),窗口前移(未收到确认时,要保留已发送的数据,以便超时重传)。而窗口的大小是实现流量控制的关键所在,它是由接收方根据自己的接受情况确定的。可以参照这篇文章的分析。
      • 如下图四中所示,由接受者通告窗口大小为4~9,即6个字节的大小;而在当前窗口中,字节4~6已经发送,未被确认;字节7~9可以发送但未被发送;如果字节4~6被全部或部分按序确认了,例如序号4被确认了,然后窗口大小又没变,则窗口滑动,变为5~10;如果窗口大小变小了(接收方通知的),那么可能窗口就不会前移;但是窗口一般不赞成向后收缩,因为收缩时可能有些数据已经发送了。
      • 再如图5-22,其中发生了三次窗口调节,初始窗口大小为400字节,B确认前200字节时,将窗口重设为300字节,确认201~500字节时,窗口重设为100字节,确认501~600字节时,窗口重设为0。零窗口可能导致死锁:如果B的接收缓存有空余了,发送了新的窗口大小报文段,但是该报文段传送时丢失,而A一直等B的新窗口大小,B一直等A的数据,就出现死锁。解决方法:为每个连接设置持续计时器,如果A接收到零窗口通知,就启动计时器,到时间A就发送一个零窗口探测报文段,如果B给的窗口值还是0,计时器重启,如果不是0,死锁僵局就被打破。
  4. 面向字节流。TCP把程序的数据看作无结构的字节流,例如发送方可能发送了10个数据块,而TCP可能只用4个数据库就发送给接收方。它不在乎数据结构,只要把数据的每个字节都按序发过去就ok了。
  5. 全双工通信。TCP连接两端都设有发送缓存和接收缓存,发送方把数据发送给TCP后就可以干自己的事了,TCP看情况发出去(滑动窗口限制);接收时,TCP把数据放到接收缓存,应用进程合适的时候去读缓存就可以了(当接收缓存满了,TCP主动向上交付,但在PSH=1时,则会立即交付,下边会讲)。所以这给发送方和接收方很大的自由,只要TCP的发送缓存还有空间,他们都可以在任一时间发送数据。

 

3. TCP报文

上边讲的TCP的很多特点:面向连接、可靠传输、窗口等,都是通过其报文的字段实现的。

TCP报文段分两部分:首部(20+4N字节)和数据部分。首部前20字节是固定的,后4N(N是整数)字节是根据需要可以增加的。对其中的某些字段做解释:

  1. 序号:指该TCP连接当前发送的报文段的第一个字节的字节序号,标识当前发送的数据块。每个字节都有序号,序号连续增加,当序号增加到232-1之后,就又变为0.
  2. 确认号:指接收方对发送方发送数据的确认,是期望收到的下一个字节序号。如A向B发送200字节数据,发送序号为301(即发送了301~500的数据),则B向A确认时,确认号为501。若确认号=n,说明到n-1为止的数据都已确认收到了
  3. 数据偏移:数据起点距TCP报文起始点的距离,即首部长度(因为有后4N不确定选项)
  4. URG:从这开始的六个字节,是控制位,上边的特点主要通过控制位实现。URG=1:表示当前报文有紧急数据要传送,相当于高优先级的,发送方TCP就把紧急数据插到该报文段最前面优先发送。注意,即使窗口为0也可以发送紧急数据。需要和下边的 紧急指针 结合使用。例如ctrl+c撤销就可能是一个紧急数据。
  5. ACK:ACK=1,确认号才有效,就是说这才是一个带有确认功能的报文。在连接建立以后,所有传送的报文段都必须把ACK置1.
  6. PSH:PSH=1,表示发送方希望能尽快收到接收方的响应,此时,数据到达TCP的接收缓存时,无论接收缓存是否填满,都立即向上交付给应用进程。(该操作很少用)
  7. RST:RST=1,复位,表示当前连接存在很大问题,需要重新建立连接,有时也用来拒绝非法报文段或拒绝打开一个连接。当发送RST包关闭连接时,无需通过四次挥手,可以直接关闭。而由于这并不是TCP连接中必须的一部分,因此不需要将ACK置1(对应上边连接建立后,ACK必须置1),但可以置1。 这是个很危险的字段,可能被用来实现RST攻击:假设有一个合法用户(1.1.1.1)已经同服务器建立了正常的连接,攻击者构造攻击的TCP数据,伪装自己的IP为1.1.1.1,并向服务器发送一个带有RST位的TCP数据段。服务器接收到这样的数据后,认为从1.1.1.1发送的连接有错误,就会清空缓冲区中建立好的连接。这时,如果合法用户1.1.1.1再发送合法数据,服务器就已经没有这样的连接了,该用户就必须重新开始建立连接。 因此在面试中经常会问产生RST包的各种原因
    1. 服务器端口未打开而客户端来连接。很常见,特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。但是某些os的原因,可能不会出现这种状况,如向一台win7主机发送一个连接不存在的端口的请求,这台主机就不会响应。
    2. 连接超时。例如89、27两台主机,89主机用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间,然后89向27发送SYN包请求连接,27回应了一个SYN表示可以连接,但是回应太慢,超过了那个recv时间限制,所以89就直接又发了个RST包,又拒绝连接了。
    3. 提前关闭。服务器就是想要尽快关闭连接,就可以发送一个RST。
    4. 收到一个不存在的连接上的报文。如TCP收到一个报文,但是根据它的端点套接字,找不到一个符合要求的套接字对(表示一条连接,前文讲的),那说明此连接有错了,就发送一个RST包。
  8. SYN:用于连接建立时同步序号。SYN=1就表示是一个连接请求或连接接收报文,是在三次握手的前两次握手中使用
  9. FIN:用于释放连接,所以不能和SYN同时使用。所有SYN/FIN的包都是非法包。此外由于连接还没有关闭,所以还要打上ACK标记,即是FIN/ACK包,仅由FIN标记的包是不合法的。FIN报文段即使不携带数据,也要占一个序号
  10. 窗口:这就算上边接收方通知发送方的窗口大小,即接收方接收缓存大小。

根据上边的解释,就可以总结一些常见的非法包:SYN/FIN包、FIN包、NULL包(没有任何标记的包)

4. TCP建立连接---三次握手

 

1. (A) --> [SYN] --> (B)

假如服务器B和客户机A通讯. 当B要和A通信时,A首先向B发一个SYN (Synchronize) 标记的包,告诉B请求建立连接.

注意: 一个 SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources). 认识到这点很重要,只有当B受到A发来的SYN包,才可建立连接,除此之外别无他法。因此,如果你的防火墙丢弃所有的发往外网接口的SYN包,那么你将不 能让外部任何主机主动建立连接。

2. (A) <-- [SYN/ACK] <--(B)

接着,B收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作.

注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.

3. (A) --> [ACK] --> (B)

A收到SYN/ACK 包,A发一个确认包(ACK),通知B连接已建立。至此,三次握手完成,一个TCP连接完成

Note: ACK包就是仅ACK 标记设为1的TCP包. 需要注意的是当三此握手完成、连接建立以后,TCP连接的每个包都会设置ACK位

这就是为何连接跟踪很重要的原因了. 没有连接跟踪,防火墙将无法判断收到的ACK包是否属于一个已经建立的连接.一般的包过滤(IpchBins)收到ACK包时,会让它通过(这绝对不是个 好主意). 而当状态型防火墙收到此种包时,它会先在连接表中查找是否属于哪个已建连接,否则丢弃该包

5. TCP释放连接(四次挥手)

 

posted on 2015-08-17 23:05  HF_Cherish  阅读(590)  评论(0编辑  收藏  举报