iCurry
2023/03/25阅读:32主题:默认主题
计算机网络
6. IP 地址有哪些分类?
IP 地址被分成 5 类 ,分别是 : A 、B 、C 、D 、E 类。
A 类 IP 地址是首位以 0 开头的地址。 从第 1 位 到 第 8 位 是 它的网络标识。用十进制表示 是 0.0.0.0 ~ 127.0.0.0。A 类地址的后24位相当于主机标识。
B 类 IP 地址是首位以 10 开头的地址.从第 1 位 到 第 16 位 是 它的网络标识。用十进制表示是 128.0.0.1~191.255.0.0。A 类地址的后16位相当于主机标识。B类主机一个网段内可容纳的主机地址上线为65534
C 类 IP 地址是首位以 110 开头的地址.从第 1 位 到 第 24位 是 它的网络标识。用十进制表示是 192.168.0.0~239.255.255.0。A 类地址的后8位相当于主机标识。B类主机一个网段内可容纳的主机地址上线为254.
D 类 IP 地址是首位以1110 开头的地址.从第 1 位 到 第 24位 是 它的网络标识。用十进制表示是 244.0.0.0~239.255.255.255。D类地址没有主机标识,常被用于多播。
E 类 地址一直未被使用。
7. 三次握手中每一次没收到报文会发生什么情况?
1、第一次握手数据丢失
当客户端想和服务端建立TCP连接的时候,客户端会向服务端发送一个 SYN 报文 ,然后客户端进入 SYN_SENT 状态。如果该 SYN 报文丢失,服务端收不到客户端发送的消息,自然也就不会向客户端发送 SYN + ACK 报文。客户端收不到 服务端发送的 SYN + ACK 报文,就会触发【超时重传】机制。重传 SYN 报文,且报文序列号与丢失报文的序列号一致。
总结:第一次握手数据丢失,客户端会触发【超时重传】机制,重新发送 SYN 报文。
2、第二次握手数据丢失。
客户端向服务端发送 SYN 报文 ,服务端收到 SYN 报文,就会向客户端 发送 SYN + ACK 报文,之后 服务端进入 SYN_RCVD状态。
如果第二次握手数据丢失。客户端收不到 服务端 发送的 SYN + ACK 报文,就会触发【超时重传】机制,继续向服务端发送 SYN 报文。 由于客户端收不到服务端发送的报文,自然也不会向 服务端 发送 ACK 报文。服务端收不到 ACK报文,也会触发【超时重传】机制。
总结:第二次握手数据丢失,客户端、服务端都会触发【超时重传】机制,客户端重新发送 SYN 报文,服务端重新发送 SYN + ACK 。
3、第三次握手数据丢失。
客户端收到服务端发送的 SYN + ACK 报文,就会向服务端发送 ACK 报文,同时进入 ESTABLISHED 状态。当ACK报文丢失,服务端收不到客户端发送的报文,就会触发【超时重传】机制,重传 SYN + ACK 报文。直到达到最大重传次数或者收到ACK 报文为止。
总结:若第三次握手数据丢失,会触发服务端的【超时重传】机制。
备注 : 在握手的过程中,ACK报文不会重传,如果ACK丢失了,就由对方重传对应的报文。
8. 第二次握手传回了 ACK,为什么还要传回 SYN?
传回的SYN报文,是服务端发起建立TCP连接的报文,只有传回SYN报文,客户端才能知道服务端随机初始化的序列号。如果传回ACK的时候不传回SYN,那么客户端想要直到服务端的序列号就需要服务端发送SYN报文,这样三次握手就变成了四次握手,因此在传回ACK的时候,同时传回SYN,可以减少握手次数,节省网络资源。
9. 说说半连接队列和 SYN Flood 攻击的关系?
半连接队列 :当服务端收到客户端发送的 SYN 报文,会创建一个半连接对象,然后将其加入到内核的【SYN队列】。
半连接队列 是发生在 服务端收到 客户端收到的 SYN 报文,但还未收到 客户端的 ACK 报文 这段时间内。当服务端收到 ACK 报文后,就会从半连接队列里取出一个半连接对象,然后创建一个新的连接对象将其加入到 【Accept队列】
SYN Flood 攻击 就是攻击者伪造不同IP地址的 SYN 报文,服务端收到这些报文后会进入 SYN_RCVD 状态,并发送 SYN + ACK ,但这些IP地址是伪造的,因此服务端是收不到 ACK 确认报文的。久而久之,半连接队列 即【SYN队列】就会被占满,使得服务端不能为正常用户服务。
SYN Flood 攻击的最直接方式就是将 SYN 队列打满,使得服务端不能为正常用户服务。
避免SYN Flood 攻击的几种方法:
1、调大netdev_max_backlog;
2、增大TCP半连接队列;
3、开启 tcp_syncookies;
4、减少 SYN + ACK 重传次数。
备注: 对于避免 SYN Flood 攻击的几种方法还不是很熟悉。
10. 说说 TCP 四次挥手的过程?
假设是客户端想要断开连接。客户端会向服务端发送一个TCP首部FIN位置被置为1的报文,即 FIN 报文。此后客户端将处于 FIN_WAIT_1状态。
服务端在收到 客户端发送的 FIN报文后 ,会向客户端发送 ACK确认报文。接着服务器进入 CLOSE_WAIT状态
客户端在收到服务端发送的ACK报文后,将进入 FIN_WAIT_2 状态。
当服务端处理完数据后,将向客户端发送 FIN 报文,请求关闭连接。此时服务端处于 LAST_ACK状态。
客户端收到服务端发送的 FIN 报文后,将向 服务端发送 ACK 报文,接着 客户端进入 TIME_WAIT状态。
服务端在收到客户端发送的ACK 确认报文后,就进入CLOSE 状态。至此服务端已经完成连接的关闭。
客户端在经过 2MSL 时间后,自动进入 CLOSE 状态,至此客户端也已经完成连接的关闭。
从上述过程可以看出,每个方向上都需要一个 FIN 和 ACK 报文。因此TCP 断开连接,又称为 四次挥手。
11. TCP 挥手为什么需要四次呢?
TCP在断开连接时,需要向对方发送 FIN包。过程如下:
关闭连接,客户端向服务端发送 FIN 包。此时即表示客户端不在发送数据,但次数的客户端还可以收到数据。
服务端在收到客户端发送的 FIN 报文后,会向 客户端发送一个 ACK 报文。但此时 服务端还有可能向客户端发送一些数据。当服务端不需要再向客户端发送数据时,就会向客户端发送FIN报文,表示同一关闭连接。
客户端在收到服务端发送的FIN报文,会向服务端发送 ACK 报文进行确认。
从上面的过程可知,TCP 断开连接时候 FIN 和 ACK 报文会分开发送,因此TCP断开连接时,应该是四次挥手。
总结: TCP 断开连接之所以是四次挥手而不是三次。是因为,对于 服务端收到 客户端发送的 FIN报文后,还要向客户端发送数据的情况。针对这种情况,有必要将 ACK 、FIN 报文分开发送。因此需要四次挥手。
12. TCP 四次挥手过程中,为什么需要等待 2MSL, 才进入 CLOSED 关闭状态?
1、为什么要等待 2MSL ?(或者说问什么要有 TIME_WAIT 这个状态?)
1 : 防止历史连接中的数据,被后面所建立的相同四元组的连接错误接收。
假设 不等待 2MSL ,或者等待的时间 少于 2MSL。
假设 在服务端关闭连接之前,发送了一段报文,但是被网络延迟了。在连接关闭之后,客户端和服务端又建立了一个 TCP连接,且目标、源 IP 地址,端口号等都相同。当前面被延迟的报文抵达了客户端,而且该报文的序列号又刚好在客户端的接收窗口内,此报文就会被客户端接收,这就会产生数据错乱等问题。2 MSL 足以让两个方向上的数据包都被丢弃,使得原来的数据包在网络上都自然消失,再出现的数据包一定都是新建立连接所产生的
2、保证被动连接的一方,能够正确的被关闭。
RFC 793 中就指出,TIME_WAIT的作用就是等待足够的时间已保证最后的ACK能够让被动关闭方接收,从而帮助其正常关闭。
假设 客户端向服务端发送的最后一次 ACK 报文丢失,那么服务端就会 重新向 客户端发送 FIN 报文。如果没有 TIME_WAIT 状态,此时的客户端已经处于关闭状态,收到服务端发送的 FIN 报文,就会回 RST 报文。服务端收到 RST 报文就会将其解释为一个错误。
如果客户端有 TIME_WAIT 状态 且等待足够的时间, 确保服务端能收到 ACK , 如果收不到 服务端就会 重发 FIN 报文,客户端收到FIN 报文,就会重置 等待时间。而一个 ACK 报文 加 FIN 报文刚好是 2MSL.
2、等待的时长为什么是 2MSL,不是更长或者更短?
MSL (Maximum Segment Lifetime) 报文最大生存时间 。它是任何报文在网络上所能存在的最长时间,超过了这个时间 报文就将被丢弃。
2MSL 的时长刚好是 报文在网络中一来一回的时间。2MSL 时长能满足 客户端从收到报文 再向服务端发送报文
进一步说,2MSL 时长 可以允许报文 在传输中丢失一次,比如 客户端向服务端发送的 ACK 报文丢失,服务端会重新发送 FIN 报文。这个一来一回的时间在 2MSL 内。
如果等待的时间进一步加长,会浪费资源。虽然能够允许报文丢失更多次,但报文多次丢失的概率很低,对于这种问题,忽略它比解决它更有价值。
13. TIME_WAIT 状态过多会导致什么问题?怎么解决?
1、占用系统资源,比如 文件描述符 、内存资源 、CPU资源、线程资源。
2、占用端口资源。
客户端和服务端 TIME_WAIT 过多,导致的问题是不同的。
客户端 TIME_WAIT过多, 占满了端口资源。那么接下来就无法再对 目标IP地址 + 目标端口号相同的服务器发起连接。但是客户端上的端口还是可以使用的,可以对其他服务器发起连接
服务端 TIME_WAIT过多,并不会导致端口资源受限。因为服务端只监听一个端口 ,而且由于四元组唯一确定一个TCP 连接,因此理论上服务端可以建立很多连接。但 TCP 连接过多,会占用系统资源。
备注:关于服务端 TIME_WAIT 过多,不会影响端口的解释有些不太明白。
如何优化 TIME_WAIT 过多:
1、打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps选项。
在Linux内核中 开启以上两个参数。 就可以将处于 TIME_WAIT 状态的 socket 为新的连接所用。
tcp_tw_reuse,仅能作用于客户端,而且还要打开TCP 对时间戳的支持(即net.ipv4.tcp_timestamps = 1)。开启了时间戳之后,客户端就无需等待 2MSL 也能保证 新连接不会收取到历史报文。
时间戳: 每一份报文都会被标记上时间。如果后面报文的时间戳小于前面报文的时间戳。就说明该报文是历史报文,就会被丢弃。
2、net.ipv4.tcp_max_tw_buckets
此值默认为 18000 ,当处于 TIME_WAIT 状态的 连接一旦超过 这个值后,系统就会将后面的 TIME_WAIT 连接状态重置。该方法比较暴力。
3、程序中使用 SO_LINGER ,应用强制使用 RST 关闭。
通过设置 socket 选项,来设置调用 Close 关闭连接行为。
备注:这里关于 socket 选项设置的问题 不是很明白。
作者介绍