一、TCP传输控制协议
TCP(Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,在简化的计算机网络 OSI 模型中,它完成第四层传输层所指定的功能,用户数据包协议(UDP)是同一层内另一个重要的传输协议。
TCP 层(传输层)位于应用层与 IP 层(网络层)之间。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是 IP 层不提供这样的流机制,而是提供不可靠的包交换。因此 TCP 协议就是为了提供可靠的传输。
应用层向 TCP 层发送用于网间传输的、用 8 位字节表示的数据流,然后 TCP 把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后 TCP 把结果包传给 IP 层,由它来通过网络将包传送给接收端实体的 TCP 层。TCP 为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP 用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
1. TCP 握手协议
在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送 syn 包 (syn=j) 到服务器,并进入 SYN_SEND 状态,等待服务器确认;
第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK (ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。
2. TCP 半连接攻击(SYN 攻击):
SYN 攻击属于 DOS 攻击的一种,它利用 TCP 协议缺陷,通过发送大量的半连接请求,耗费 CPU 和内存资源。SYN 攻击除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上 SYN 攻击并不管目标是什么系统,只要这些系统打开 TCP 服务就可以实施。
服务器接收到连接请求(syn=j),将此信息加入未连接队列,并发送请求包给客户(syn=k,ack=j+1),此时进入 SYN_RECV 状态。当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。配合 IP 欺骗,SYN 攻击能达到很好的效果,通常,客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 syn 包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。每种操作系统半连接队列大小不一样所以抵御 SYN 攻击的能力也不一样。
检测 SYN 攻击很简单,当你在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。
半连接:在三次握手过程中,服务器发送 SYN-ACK 之后,收到客户端的 ACK 之前的 TCP 连接称为半连接 (half-open connect)。此时服务器处于 Syn_RECV 状态。当收到 ACK 后,服务器转入 ESTABLISHED 状态.
未连接队列(半连接队列):在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的 SYN 包(syn=j)开设一个条目,该条目表明服务器已收到 SYN 包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于 Syn_RECV 状态,当服务器收到客户的确认包时,删除该条目,服务器进入 ESTABLISHED 状态。
backlog 参数:表示未连接队列的最大容纳数目。
SYN-ACK 重传次数:服务器发送完 SYN-ACK 包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。
半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到 SYN 包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为 Timeout 时间、SYN_RECV 存活时间。
二、SYN 攻击防范
主要有两大类,一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固 TCP/IP 协议栈防范。但必须清楚的是,SYN 攻击不能完全被阻止,我们所做的是尽可能的减轻 SYN 攻击的危害,除非将 TCP 协议重新设计。
1. 过滤网关防护
这里,过滤网关主要指明防火墙,当然路由器也能成为过滤网关。防火墙部署在不同网络之间,防范外来非法攻击和防止保密信息外泄,它处于客户端和服务器之间,利用它来防护 SYN 攻击能起到很好的效果。过滤网关防护主要包括超时设置,SYN 网关和 SYN 代理三种。
网关超时设置:防火墙设置 SYN 转发超时参数(状态检测的防火墙可在状态表里面设置),该参数远小于服务器的 timeout 时间。当客户端发送完 SYN 包,服务端发送确认包后(SYN+ACK),防火墙如果在计数器到期时还未收到客户端的确认包(ACK),则往服务器发送 RST 包,以使服务器从队列中删去该半连接。值得注意的是,网关超时参数设置不宜过小也不宜过大,超时参数设置过小会影响正常的通讯,设置太大,又会影响防范 SYN 攻击的效果,必须根据所处的网络应用环境来设置此参数。
SYN 网关:SYN 网关收到客户端的 SYN 包时,直接转发给服务器;SYN 网关收到服务器的 SYN/ACK 包后,将该包转发给客户端,同时以客户端的名义给服务器发 ACK 确认包。此时服务器由半连接状态进入连接状态。当客户端确认包到达时,如果有数据则转发,否则丢弃。事实上,服务器除了维持半连接队列外,还要有一个连接队列,如果发生 SYN 攻击时,将使连接队列数目增加,但一般服务器所能承受的连接数量比半连接数量大得多,所以这种方法能有效地减轻对服务器的攻击。
SYN 代理:当客户端 SYN 包到达过滤网关时,SYN 代理并不转发 SYN 包,而是以服务器的名义主动回复SYN/ACK包给客户,如果收到客户的ACK包,表明这是正常的访问,此时防火墙向服务器发送ACK包并完成三次握手。SYN代理事实上代替了服务器去处理SYN攻击,此时要求过滤网关自身具有很强的防范SYN攻击能力。
2. 加固 TCP/IP 协议栈
防范SYN攻击的另一项主要技术是调整tcp/ip协议栈,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等。tcp/ip协议栈的调整可能会引起某些功能的受限,管理员应该在进行充分了解和测试的前提下进行此项工作。
SynAttackProtect 机制:SynAttackProtect 机制是通过关闭某些 socket 选项,增加额外的连接指示和减少超时时间,使系统能处理更多的 SYN 连接,以达到防范 SYN 攻击的目的。
-
SYN cookies 技术:我们知道,TCP 协议开辟了一个比较大的内存空间 backlog 队列来存储半连接条目,当 SYN 请求不断增加, 致使系统丢弃 SYN 连接。为使半连接队列被塞满的情况下,服务器仍能处理新到的 SYN 请求,SYN cookies技术被设计出来。
SYN cookies 应用于 linux、FreeBSD 等操作系统,当半连接队列满时,SYN cookies 并不丢弃 SYN 请求,而是通过加密技术来标识半连接状态。
在 TCP 实现中,当收到客户端的 SYN 请求时,服务器需要回复 SYN+ACK 包给客户端,客户端也要发送确认包给服务器。通常,服务器的初始序列号由服务器按照一定的规律计算得到或采用随机数,但在 SYN cookies 中,服务器的初始序列号是通过对客户端 IP 地址、客户端端囗、服务器 IP 地址和服务器端囗以及其他一些安全数值等要素进行 hash 运算,加密得到的,称之为 cookie。当服务器遭受 SYN 攻击使得 backlog 队列满时,服务器并不拒绝新的 SYN 请求,而是回复 cookie(回复包的 SYN 序列号)给客户端, 如果收到客户端的 ACK 包,服务器将客户端的ACK序列号减去1得到 cookie 比较值,并将上述要素进行一次 hash 运算,看看是否等于此 cookie。如果相等,直接完成三次握手(注意:此时并不用查看此连接是否属于 backlog 队列)。
增加最大半连接数:大量的 SYN 请求导致未连接队列被塞满,使正常的 TCP 连接无法顺利完成三次握手,通过增大未连接队列空间可以缓解这种压力。当然 backlog 队列需要占用大量的内存资源,不能被无限的扩大。
缩短超时时间:上文提到,通过增大 backlog 队列能防范 SYN 攻击;另外减少超时时间也使系统能处理更多的 SYN 请求。我们知道,timeout 超时时间,也即半连接存活时间,是系统所有重传次数等待的超时时间总和,这个值越大,半连接数占用 backlog 队列的时间就越长,系统能处理的 SYN 请求就越少。为缩短超时时间,可以通过缩短重传超时时间(一般是第一次重传超时时间)和减少重传次数来实现。
三、TCP 与 UDP 协议的区别和适用场景
1. 面向字节流(TCP)
虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序看成是一连串的无结构的字节流。TCP 有一个缓冲,当应用程序传送的数据块太长,TCP 就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP 也可以等待积累有足够多的字节后再构成报文段发送出去。
2. 面向报文(UDP)
面向报文的传输方式是应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则 IP 层需要分片,降低效率。若太短,会是 IP 太小。UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。
3. 面向连接(TCP)
一种网络协议,依赖发送方和接收器之间的显示通信和阻塞以管理双方的数据传输。网络系统需要在两台计算机之间发送数据之前先建立连接的一种特性。面向连接网络类似于电话系统,在开始通信前必须先进行一次呼叫和应答。面向连接的服务(connection-oriented service)就是通信双方在通信时,要事先建立一条通信线路,其过程有建立连接、使用连接和释放连接三个过程。
4. 面向无连接(UDP、IP)
无连接的通信,就不需要预先建立起一个联络两个通信节点的连接来,需要通信的时候,发送节点就可以往“网络”上送出信息,让信息自主地在网络上去传,一般在传输的过程中不再加以监控,让该信息的传递在网上尽力而为地往目的地节点传送。比如写信,你只需填写好收信人的地址信息,然后将信投入邮局,就算完成了任务。此时,邮局会根据收信人的地址信息,将信件送达指定目的地。
在默认的阻塞模式下,TCP 无边界,UDP 有边界。 对于 TCP协议,客户端连续发送数据,只要服务端的这个函数的缓冲区足够大,会一次性接收过来,即客户端是分好几次发过来,是有边界的,而服务端却一次性接收过来,所以证明是无边界的; 而对于 UDP 协议,客户端连续发送数据,即使服务端的这个函数的缓冲区足够大,也只会一次一次的接收,发送多少次接收多少次,即客户端分几次发送过来,服务端就必须按几次接收,从而证明,这种 UDP 的通讯模式是有边界的。
特点、优缺点比较:
可靠性:字节编号,应答 ACK,分段传输、重传
流量控制:滑动窗口机制
全双工:两个进程建立一个连接,并在任何一个方向上发送数据,任一端可发可接。