面试之计算机网络


什么是754层网络模型?

全局上理解 7层协议,4层,5层的对应关系。

img

OSI 依层次结构来划分:应用层(Application)、表示层(Presentation)、会话层(Session)、传输层(Transport)、网络层(Network)、数据链路层(Data Link)、物理层(Physical)

TCP建立连接过程的三次握手

TCP 有 6 种标识:SYN(建立联机) ACK(确认) PSH(传送) FIN(结束) RST(重置) URG(紧急)

  • 什么是三次握手

image-20220907194538705

为了保证数据能到达目标,TCP采用三次握手策略:

  1. 发送端首先发送一个带SYN(synchronize)标志的数据包给接收方【第一次的 seq 序列号是随机产生的,这样是为了网络安全,如果不是随机产生初始序列号,黑客将会以很容易的方式获取到你与其他主机之间的初始化序列号,并且伪造序列号进行攻击】
  2. 接收端收到后,回传一个带有 SYN/ACK(acknowledgement)标志的数据包以示传达确认信息【SYN 是为了告诉发送端,发送方到接收方的通道没问题;ACK 用来验证接收方到发送方的通道没问题】
  3. 最后,发送端再回传一个带 ACK 标志的数据包,代表握手结束,若在握手某个过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包
  • 为什么要三次握手

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的

  1. 第一次握手,发送端:什么都确认不了;接收端:对方发送正常,自己接受正常
  2. 第二次握手,发送端:对方发送,接受正常,自己发送,接受正常 ;接收端:对方发送正常,自己接受正常
  3. 第三次握手,发送端:对方发送,接受正常,自己发送,接受正常;接收端:对方发送,接受正常,自己发送,接受正常
  • 两次握手不行吗?为什么TCP客户端最后还要发送一次确认呢

主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。经典场景:客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了。

  1. 由于 TCP 的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。
  2. 此时此前滞留的那一次请求连接,网络通畅了到达服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
  3. 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
  • 为什么三次握手,返回时,ack 值是 seq 加 1(ack = x+1)
  1. 假设对方接收到数据,比如sequence number = 1000,TCP Payload = 1000,数据第一个字节编号为1000,最后一个为1999,回应一个确认报文,确认号为2000,意味着编号2000前的字节接收完成,准备接收编号为2000及更多的数据
  2. 确认收到的序列,并且告诉发送端下一次发送的序列号从哪里开始(便于接收方对数据排序,便于选择重传)
  • TCP三次握手中,最后一次回复丢失,会发生什么
  1. 如果最后一次 ACK 在网络中丢失,那么 Server 端(服务端)该 TCP 连接的状态仍为 SYN_RECV,并且根据 TCP 的超时重传机制依次等待3秒、6秒、12秒后重新发送 SYN+ACK 包,以便 Client(客户端)重新发送ACK包
  2. 如果重发指定次数后,仍然未收到 ACK 应答,那么一段时间后,Server(服务端)自动关闭这个连接
  3. 但是 Client(客户端)认为这个连接已经建立,如果 Client(客户端)端向 Server(服务端)发送数据,Server 端(服务端)将以RST 包(Reset,标示复位,用于异常的关闭连接)响应,此时,客户端知道第三次握手失败

SYN 洪泛攻击(SYN Flood,半开放攻击),怎么解决?

  • 什么是SYN洪范泛攻击

SYN Flood 利用 TCP 协议缺陷,发送大量伪造的 TCP 连接请求,常用假冒的 IP 或 IP 号段发来海量的请求连接的第一个握手包(SYN包),被攻击服务器回应第二个握手包(SYN+ACK包),因为对方是假冒IP,对方永远收不到包且不会回应第三个握手包。导致被攻击服务器保持大量 SYN_RECV 状态的“半连接”,并且会重试默认 5 次回应第二个握手包,大量随机的恶意 syn 占满了未完成连接队列,导致正常合法的 syn 排不上队列,让正常的业务请求连接不进来。【服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到 SYN 洪泛攻击】

  • 如何检测 SYN 攻击?

当你在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击【在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击】

  • 怎么解决? SYN 攻击不能完全被阻止,除非将 TCP 协议重新设计。我们所做的是尽可能的减轻 SYN 攻击的危害,
  1. 缩短超时(SYN Timeout)时间
  2. 增加最大半连接数
  3. 过滤网关防护
  4. SYN cookies技术:
    1. 当服务器接受到 SYN 报文段时,不直接为该 TCP 分配资源,而只是打开一个半开的套接字。接着会使用 SYN 报文段的源 Id,目的 Id,端口号以及只有服务器自己知道的一个秘密函数生成一个 cookie,并把 cookie 作为序列号响应给客户端。
    2. 如果客户端是正常建立连接,将会返回一个确认字段为 cookie + 1 的报文段。接下来服务器会根据确认报文的源 Id,目的 Id,端口号以及秘密函数计算出一个结果,如果结果的值 + 1 等于确认字段的值,则证明是刚刚请求连接的客户端,这时候才为该 TCP 分配资源

TCP断开连接过程的四次挥手?

  • 什么是四次挥手

image-20220907200133430

  1. 主动断开方(客户端/服务端)-发送一个 FIN,用来关闭主动断开方(客户端/服务端)到被动断开方(客户端/服务端)的数据传送
  2. 被动断开方(客户端/服务端)-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号
  3. 被动断开方(客户端/服务端)-关闭与主动断开方(客户端/服务端)的连接,发送一个 FIN 给主动断开方(客户端/服务端)
  4. 主动断开方(客户端/服务端)-发回 ACK 报文确认,并将确认序号设置为收到序号加1
  • 为什么连接的时候是三次握手,关闭的时候却是四次握手
  1. 建立连接的时候, 服务器在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。
  2. 关闭连接时,服务器收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以服务器可以立即关闭,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接。因此,服务器 ACK和 FIN 一般都会分开发送,从而导致多了一次。
  • 为什么 TCP 挥手每两次中间有一个 FIN-WAIT2 等待时间

主动关闭的一端调用完 close 以后(即发 FIN 给被动关闭的一端, 并且收到其对 FIN 的确认ACK)则进入 FIN_WAIT_2 状态。如果这个时候因为网络突然断掉、被动关闭的一段宕机等原因,导致主动关闭的一端不能收到被动关闭的一端发来的 FIN(防止对端不发送关闭连接的 FIN 包给本端),这个时候就需要 FIN_WAIT_2 定时器, 如果在该定时器超时的时候,还是没收到被动关闭一端发来的 FIN,那么直接释放这个链接,进入 CLOSE 状态

  • 为什么客户端最后还要等待 2MSL?为什么还有个TIME-WAIT的时间等待
  1. 保证客户端发送的最后一个 ACK 报文能够到达服务器,因为这个 ACK 报文可能丢失,服务器已经发送了 FIN+ACK 报文,请求断开,客户端却没有回应,于是服务器又会重新发送一次,而客户端就能在这个 2MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启 2MSL 计时器。
  2. 防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新的连接中不会出现旧连接的请求报文。
  3. 2MSL,最大报文生存时间,一个MSL 30 秒,2MSL = 60s
  • 客户端 TIME-WAIT 状态过多会产生什么后果?怎样处理
  1. 作为服务器,短时间内关闭了大量的 Client 连接,就会造成服务器上出现大量的TIME_WAIT连接,占据大量的 tuple /tApl/ ,严重消耗着服务器的资源,此时部分客户端就会显示连接不上
  2. 作为客户端,短时间内大量的短连接,会大量消耗的 Client 机器的端口,毕竟端口只有65535个,端口被耗尽了,后续就无法在发起新的连接了
  3. 在高并发短连接的 TCP 服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量 socket 处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上
    1. 高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个0~65535的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了
    2. 短连接表示“业务处理+传输数据的时间 远远小于 TIMEWAIT超时的时间”的连接
  4. 解决方法:
    1. 用负载均衡来抗这些高并发的短请求;
    2. 服务器可以设置 SO_REUSEADDR 套接字选项来避免 TIME_WAIT状态,TIME_WAIT 状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的
    3. 强制关闭,发送 RST 包越过TIMEWAIT状态,直接进入CLOSED状态
  • 服务器出现了大量 CLOSE_WAIT 状态如何解决

大量 CLOSE_WAIT 表示程序出现了问题,对方的 socket 已经关闭连接,而我方忙于读或写没有及时关闭连接,需要检查代码,特别是释放资源的代码,或者是处理请求的线程配置。

  • 服务端会有一个TIME_WAIT状态吗?如果是服务端主动断开连接呢
  1. 发起链接的主动方基本都是客户端,但是断开连接的主动方服务器和客户端都可以充当,也就是说,只要是主动断开连接的,就会有 TIME_WAIT状态
  2. 四次挥手是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发
  3. 由于TCP连接时全双工的,因此,每个方向的数据传输通道都必须要单独进行关闭。

DNS 解析流程?

.com.fi 国际金融域名 DNS 解析的步骤一共分为9步,如果每次解析都要走完9个步骤,大家浏览网站的速度也不会那么快,现在之所以能保持这么快的访问速度,其实一般的解析都是跑完第4步就可以了。除非一个地区完全是第一次访问(在都没有缓存的情况下)才会走完9个步骤,这个情况很少。

  • 本地客户机提出域名解析请求,查找本地 HOST 文件后将该请求发送给本地的域名服务器。
  • 将请求发送给本地的域名服务器。
  • 当本地的域名服务器收到请求后,就先查询本地的缓存。
  • 如果有该纪录项,则本地的域名服务器就直接把查询的结果返回浏览器。
  • 如果本地 DNS 缓存中没有该纪录,则本地域名服务器就直接把请求发给根域名服务器。
  • 然后根域名服务器再返回给本地域名服务器一个所查询域(根的子域)的主域名服务器的地址。
  • 本地服务器再向上一步返回的域名服务器发送请求,然后接受请求的服务器查询自己的缓存,如果没有该纪录,则返回相关的下级的域名服务器的地址。
  • 重复第7步,直到找到正确的纪录。
  • 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时还将结果返回给客户机。

image-20220907202110899

注意事项:

递归查询:在该模式下DNS服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果DNS服务器本地没有存储查询DNS信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机。

迭代查询:DNS所在服务器若没有可以响应的结果,会向客户机提供其他能够解析查询请求的DNS服务器地址,当客户机发送查询请求时,DNS服务器并不直接回复查询结果,而是告诉客户机另一台DNS服务器地址,客户机再向这台DNS服务器提交请求,依次循环直到返回查询的结果为止。

为什么DNS通常基于UDP?

DNS通常是基于UDP的,但当数据长度大于512字节的时候,为了保证传输质量,就会使用基于TCP的实现方式

  • 从数据包的数量以及占有网络资源的层面

使用基于UDP的DNS协议只要一个请求、一个应答就好了; 而使用基于TCP的DNS协议要三次握手、发送数据以及应答、四次挥手; 明显基于TCP协议的DNS更浪费网络资源!

  • 从数据一致性层面

DNS数据包不是那种大数据包,所以使用UDP不需要考虑分包,如果丢包那么就是全部丢包,如果收到了数据,那就是收到了全部数据!所以只需要考虑丢包的情况,那就算是丢包了,重新请求一次就好了。而且DNS的报文允许填入序号字段,对于请求报文和其对应的应答报文,这个字段是相同的,通过它可以区分DNS应答是对应的哪个请求

什么是DNS劫持?

DNS劫持就是通过劫持了DNS服务器,通过某些手段取得某域名的解析记录控制权,进而修改此域名的解析结果,导致对该域名的访问由原IP地址转入到修改后的指定IP,其结果就是对特定的网址不能访问或访问的是假网址,从而实现窃取资料或者破坏原有正常服务的目的。DNS劫持通过篡改DNS服务器上的数据返回给用户一个错误的查询结果来实现的。

  • DNS劫持症状

在某些地区的用户在成功连接宽带后,首次打开任何页面都指向ISP提供的“电信互联星空”、“网通黄页广告”等内容页面。还有就是曾经出现过用户访问Google域名的时候出现了百度的网站。这些都属于DNS劫持。

什么是DNS污染?

DNS污染是一种让一般用户由于得到虚假目标主机IP而不能与其通信的方法,是一种DNS缓存投毒攻击(DNS cache poisoning)。其工作方式是:由于通常的DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是无连接不可靠的协议,因此DNS的查询非常容易被篡改,通过对UDP端口53上的DNS查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者返回虚假结果。

而DNS污染则是发生在用户请求的第一步上,直接从协议上对用户的DNS请求进行干扰。

DNS污染症状

目前一些被禁止访问的网站很多就是通过DNS污染来实现的,例如YouTube、Facebook等网站。

解决方法:

  1. 对于DNS劫持,可以采用使用国外免费公用的DNS服务器解决。例如OpenDNS(208.67.222.222)或GoogleDNS(8.8.8.8)。
  2. 对于DNS污染,可以说,个人用户很难单单靠设置解决,通常可以使用VPN或者域名远程解析的方法解决,但这大多需要购买付费的VPN或SSH等,也可以通过修改Hosts的方法,手动设置域名正确的IP地址。

为什么要DNS流量监控?

预示网络中正出现可疑或恶意代码的 DNS 组合查询或流量特征。例如:

  • 1.来自伪造源地址的 DNS 查询、或未授权使用且无出口过滤地址的 DNS 查询,若同时观察到异常大的 DNS 查询量或使用 TCP 而非 UDP 进行 DNS 查询,这可能表明网络内存在被感染的主机,受到了 DDoS 攻击。
  • 2.异常 DNS 查询可能是针对域名服务器或解析器(根据目标 IP 地址确定)的漏洞攻击的标志。与此同时,这些查询也可能表明网络中有不正常运行的设备。原因可能是恶意软件或未能成功清除恶意软件。
  • 3.在很多情况下,DNS 查询要求解析的域名如果是已知的恶意域名,或具有域名生成算法( DGA )(与非法僵尸网络有关)常见特征的域名,或者向未授权使用的解析器发送的查询,都是证明网络中存在被感染主机的有力证据。
  • 4.DNS 响应也能显露可疑或恶意数据在网络主机间传播的迹象。例如,DNS 响应的长度或组合特征可以暴露恶意或非法行为。例如,响应消息异常巨大(放大攻击),或响应消息的 Answer Section 或 Additional Section 非常可疑(缓存污染,隐蔽通道)。
  • 5.针对自身域名组合的 DNS 响应,如果解析至不同于你发布在授权区域中的 IP 地址,或来自未授权区域主机的域名服务器的响应,或解析为名称错误( NXDOMAIN )的对区域主机名的肯定响应,均表明域名或注册账号可能被劫持或 DNS 响应被篡改。
  • 6.来自可疑 IP 地址的 DNS 响应,例如来自分配给宽带接入网络 IP 段的地址、非标准端口上出现的 DNS 流量,异常大量的解析至短生存时间( TTL )域名的响应消息,或异常大量的包含“ name error ”( NXDOMAIN )的响应消息,往往是主机被僵尸网络控制、运行恶意软件或被感染的表现。

输入URL 到页面加载过程?

  1. 地址栏输入URL
  2. DNS 域名解析IP
  3. 请求和响应数据
    1. 建立TCP连接(3次握手)
    2. 发送HTTP请求
    3. 服务器处理请求
    4. 返回HTTP响应结果
    5. 关闭TCP连接(4次挥手)
  4. 浏览器加载,解析和渲染

下图是在数据传输过程中的工作方式,在发送端是应用层–>链路层这个方向的封包过程,每经过一层都会增加该层的头部。而接收端则是从链路层–>应用层解包的过程,每经过一层则会去掉相应的首部。

image-20220907202308092

如何使用netstat查看服务及监听端口?

netstat -t/-u/-l/-r/-n【显示网络相关信息,-t:TCP协议,-u:UDP协议,-l:监听,-r:路由,-n:显示IP地址和端口号】

  • 查看本机监听的端口
1
2
3
4
5
6
7
8
9
10
[root@pdai-centos ~]# netstat -tlun
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
udp 0 0 172.21.0.14:123 0.0.0.0:*
udp 0 0 127.0.0.1:123 0.0.0.0:*
udp6 0 0 fe80::5054:ff:fe2b::123 :::*
udp6 0 0 ::1:123 :::*

如何使用TCPDump抓包?

tcpdump 是一款强大的网络抓包工具,它使用 libpcap 库来抓取网络数据包,这个库在几乎在所有的 Linux/Unix 中都有。

tcpdump 的常用参数如下:

1
$ tcpdump -i eth0 -nn -s0 -v port 80
  • -i : 选择要捕获的接口,通常是以太网卡或无线网卡,也可以是 vlan 或其他特殊接口。如果该系统上只有一个网络接口,则无需指定。
  • -nn : 单个 n 表示不解析域名,直接显示 IP;两个 n 表示不解析域名和端口。这样不仅方便查看 IP 和端口号,而且在抓取大量数据时非常高效,因为域名解析会降低抓取速度。
  • -s0 : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
  • -v : 使用 -v-vv-vvv 来显示更多的详细信息,通常会显示更多与特定协议相关的信息。
  • port 80 : 这是一个常见的端口过滤器,表示仅抓取 80 端口上的流量,通常是 HTTP。

如何使用Wireshark抓包分析?

Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。

首先看下TCP报文首部,和wireshark捕获到的TCP包中的每个字段如下图所示:


文章作者: Yang Shiyu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yang Shiyu !
  目录