目录
[TCP/IP 通信传输流](#TCP/IP 通信传输流)
[SYN攻击(SYN Flood Attack)](#SYN攻击(SYN Flood Attack))
[基于 TCP 协议实现通信](#基于 TCP 协议实现通信)
[TCP 协议的通信过程](#TCP 协议的通信过程)
Web通信的简单结构
Web 使用一种名为 HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器端等一系列运作流程。举个例子,我们使用浏览器访问百度:<www.baidu.com>(Ip:220.181.38.150)。
-
DNS域名解析:
DNS(Domain Name System)服务是和HTTP协议一样位于应用层的协议。它提供域名到IP之间的解析服务。
-
http访问web
网络通信基础TCP/IP
通常使用的网络(包括互联网)是在TCP/IP协议族的基础上运作的。TCP/IP协议族四层结构分为:应用层、传输层、网络层和数据链路层。
-
应用层:决定了向用户提供应用服务时通信的活动。
-
传输层:提供处于网络连接中的两台计算机之间的数据传输。常见的是TCP和UDP两种性质不同的协议。
-
TCP(Transmission Control Protocol)
-
UDP(User Data Protocol)
-
-
网络层:用来处理在网络上流动的数据包。
-
链路层(数据链路层、网络接口层):用来处理连接网络的硬件部分。
当然也存在OSI七层机构和TCP/IP五层结构的划分方式。
TCP/IP 通信传输流
发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。
HTTP中的三剑客
在TCP/IP协议族中与HTTP密不可分的3个协议:IP协议、TCP协议和DNS协议
负责传输的IP协议
IP 协议的作用是把各种数据包传送给对方。其中两个重要的条件是 IP 地址和 MAC 地址(Media Access Control Address)。IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC 地址基本上不会更改。
使用ARP协议凭借MAC地址进行通信,这个过程像快递公司的送货过程。寄件人将货物送到集散中心,快递公司根据收件地址就能确定下一站该送往哪个区域的集散中心。这种机制也叫路由选择、
*
确保可靠性的TCP协议
为了准确无误地将数据送达目的地,TCP协议采用了三次握手(three-way handshaking)策略。握手过程中使用了TCP的标志(flag)-SYN(synchronize)和ACK(acknowledgement)。只有三次握手,Client和Server才能相互确认双相连接,实现双工数据传输。
-
第一次握手(SYN=1,seq=x):客户端发送一个TCP的SYN标志位置1的包,指明要连接的服务器端口以及初始序号x,保存在包头的序列号(Sequence-Number)字段中,发送完毕后,客户端进入SYN-SEND状态。
-
第二次握手(SYN=1,ACK=1,seq=y,ack=x+1):服务器发回确认包(ACK)应答,即SYN和ACK标志位均为1。服务器将自己ISN(初始序列号)放入Seq中,同时将ack设置为客户端的ISN+1即x+1.发送完毕后,服务器进入SYN-RCVD状态。
-
第三次握手(ACK=1,seq=x+1,ack=y+1):客户端再次发送确认包(ACK),SYN为0,ACK为1,并且把ack设为服务器的ISN+1即y+1发送给对方,数据发送完毕,客户端进入ESTABLISHED状态,当服务器接收到这个包时,也进入ESTABLISHED状态,TCP握手结束。
SYN攻击(SYN Flood Attack)
是一种网络攻击,通常针对TCP协议的三次握手过程中的漏洞进行攻击。SYN攻击旨在使目标服务器耗尽资源,导致其无法正常处理新的连接请求,从而使服务不可用。以下是SYN攻击的工作原理和防御方法:
工作原理:
-
攻击者发送大量伪造的TCP连接请求(SYN请求)到目标服务器。
-
目标服务器收到这些伪造的连接请求后,会为每个请求分配一些资源,如内存和连接表项,然后回复一个SYN-ACK响应,等待客户端的确认。
-
攻击者不回复服务器的SYN-ACK响应,或者回复得很慢,从而使服务器一直等待确认。
-
由于服务器需要等待确认,它不断累积未完成的连接请求,消耗了系统资源,最终可能无法再接受新的合法连接请求,导致拒绝服务(DoS)。
防御方法:
-
SYN Cookies:一种常见的防御方法是使用SYN Cookies。在使用SYN Cookies的情况下,服务器不会为每个连接请求分配资源,而是根据客户端的请求生成一个特殊的标识符(SYN Cookie)。只有在客户端回复ACK时,服务器才会分配资源。这可以减轻攻击对服务器资源的影响。
-
调整连接资源限制:可以调整服务器的TCP连接资源限制,限制每个IP地址的并发连接数,以减轻攻击的影响。这可以通过操作系统的设置来实现。
-
使用防火墙和入侵检测系统(IDS/IPS):防火墙和IDS/IPS可以用于检测和过滤恶意的SYN请求流量。它们可以识别和拦截大规模的SYN攻击尝试。
-
网络流量分析:监控和分析网络流量,及时检测异常流量模式,可以帮助发现SYN攻击。
-
升级硬件和网络带宽:增加服务器的硬件资源和网络带宽可以增加其抵御SYN攻击的能力,但这并不是解决问题的根本方法。
-
使用CDN:使用内容分发网络(CDN)可以分担攻击流量,减轻服务器的负担,提高服务的可用性。
四次挥手
四次挥手的目的是关闭一个连接,连接存在时,客户端和服务器均可主动发起挥手动作(TCP是一个全双工协议),在socket编程中,任何一方执行close()操作即可产生挥手操作。
-
第一次挥手(FIN=1,seq=u):假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为 1 的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,客户端进入 FIN_WAIT_1 状态。
-
第二次挥手(ACK=1,ack=u+1):服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求, 但还没有准备好关闭连接。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。
-
第三次挥手(FIN=1,seq=w):服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为 1。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
-
第四次挥手(ACK=1,ACKnum=w+1):客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT 状态,等待 可能出现的要求重传的 ACK 包。 服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。 客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime) 之后,没有收到服务器端的 ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接, 进入 CLOSED 状态。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
三次握手是因为因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。
但是关闭连接时, 当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET(因为可能还有消息没处理 完),所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了"。只有等到 我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步握手。
*
负责域名解析的DNS服务
DNS(Domain Name System)服务是和 HTTP 协议一样位于应用层的协议。它提供域名到 IP 地址之间的解析服务。
基于 TCP 协议实现通信
TCP是一个全双工协议,数据通信允许数据同时在两个方向上传输,因此全双工是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。通过Socket简单地模拟下双工通信。
-
server端实现:
javapublic class ServerSocketDemo { public static void main(String[] args) throws IOException { try { ServerSocket server = null; // 创建一个serverSocket在端口8080监听客户端请求 server = new ServerSocket(8080); Socket socket = null; try { socket = server.accept(); // 使用accept()阻塞等待客户请求 } catch (IOException e) { e.printStackTrace(); } String line; // 由Socket对象得到输入流,并构造响应的BufferedReader对象 BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 由Socket对象得到输出流,并构造PrintWriter对象 PrintWriter os = new PrintWriter(socket.getOutputStream()); // 由系统标准输入设备构造BufferedReader对象 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); // 在标准输出上打印从客户端读入的字符串 System.out.println("Client:" + is.readLine()); // 从标准输入读入字符串 line = sin.readLine(); // 读到"bye"停止循环 while (!line.equals("bye")) { // 向客户端输出该字符串 os.println(line); // 刷新输出流,使Client马上收到该字符串 os.flush(); // 在系统标准输出上打印读入的字符串 System.out.println("Server:" + line); // 从Client读入字符串,并打印到标准输出上 System.out.println("Client:" + is.readLine()); // 从系统标准输入读入字符串 line = sin.readLine(); } os.close(); is.close(); socket.close(); server.close(); } catch (IOException e) { System.out.println("Error:" + e); } } }
-
client端实现:
javapublic class ClientSocketDemo { public static void main(String[] args) { try { // 找到目标serverSocket的地址和端口 Socket socket = new Socket("localhost", 8080); // 控制台的输入流 BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); // 在当前连接上写入数据 PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // 拿到输入流 BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String readline = sin.readLine(); while (!readline.equals("bye")) { out.println(readline); out.flush(); System.out.println("Client:"+readline); System.out.println("Server:"+in.readLine()); readline = sin.readLine(); // 重新获取 } out.close(); in.close(); socket.close(); } catch (IOException e) { System.out.println("Error" + e); } } }
TCP 协议的通信过程
首先,对于 TCP 通信来说,每个 TCP Socket 的内核中都有一个发送缓冲区和一个接收缓冲 区,TCP 的全双工的工作模式及 TCP 的滑动窗口就是依赖于这两个独立的 Buffer 和该 Buffer 的填充状态。
缓冲区
接收缓冲区把数据缓存到内核,若应用进程一直没有调用 Socket 的 read 方法进行读取,那么该数据会一直被缓存在接收缓冲区内。不管进程是否读取 Socket,对端发来的数据都会经 过内核接收并缓存到 Socket 的内核接收缓冲区。 read 所要做的工作,就是把内核接收缓冲区中的数据复制到应用层用户的 Buffer 里。 进程调用 Socket 的 send 发送数据的时候,一般情况下是将数据从应用层用户的 Buffer 里复 制到 Socket 的内核发送缓冲区,然后 send 就会在上层返回。换句话说,send 返回时,数据不一定会被发送到对端。
Socket 的接收缓冲区被 TCP 用来缓存网络上收到的数据,一直保存到应用进 程读走为止。如果应用进程一直没有读取,那么 Buffer 满了以后,出现的情况是:通知对端 TCP 协议中的窗口关闭,保证 TCP 接收缓冲区不会移除,保证了 TCP 是可靠传输的。如果对方无视窗口大小发出了超过窗口大小的数据,那么接收方会把这些数据丢弃。
滑动窗口协议
这个过程中涉及到了 TCP 的滑动窗口协议,滑动窗口(Sliding window)是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道 网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题;发送和接受方都会维护一个数据帧的序列,这个序列被称作窗口。
发送窗口
就是发送端允许连续发送的帧的序号表。 发送端可以不等待应答而连续发送的最大帧数称为发送窗口的尺寸。
接收窗口
接收方允许接收的帧的序号表,凡落在接收窗口内的帧,接收方都必须处理,落在接收窗口外的帧被丢弃。 接收方每次允许接收的帧数称为接收窗口的尺寸。
接收窗口 接收方允许接收的帧的序号表,凡落在接收窗口内的幀,接收方都必须处理,落在接收窗口外的帧被丢弃。 接收方每次允许接收的帧数称为接收窗口的尺寸。