wireshark网络分析的艺术

1、Linux服务器在收到 SSH 访问请求时,会先查询该客户端 IP 所对应的 PTR 记录( IP 反向解析,由 IP 地址 获得对应的DNS,常用在垃圾邮件过滤)。假如经过5秒钟还没有收到回复,就再发一次查询。如果第二次查询还是等了5秒还没回复,就彻底放弃查询。

解决方式: cat /etc/ssh/sshd_config | grep -i usedns ,如果显示 usedns yes ,将其设置成 no即可。

其中 grep是文本处理工具,同 sedawk被称为文本处理三剑客。-i 代表忽略大小写的区别(ignore)。

2、启用 TCP SACK( selective acknowledgement) 功能,在大量丢包时,不需要每个重传包都确认一次。可以在 ack 数据包中,告知对方哪些包我已经收到了,比如说,当前 ack = 100 ,包中的 sack 字段等于 107--120,那么可以一次性完成 100--106 号包的重传,节约时间。

3、延迟确认

当要发送一个 ack 数据包的时候,因为纯粹的ack数据包只是单纯的确认,不含有其他有用信息。启用延迟确认,当收到一个 seq时,不立即发送 ack,而是稍等一会,当本地有数据要发送时,将信息加在 ack数据包里,就一起带过去了,节省带宽。

4、数据接收方可以积累一些包才对发送方 ack 一次。

5、愚笨窗口综合症(silly window syndrome)—“小包问题“

1
2
3
4
5
6
7
8
9
10
11
12
纳格(Nagle)算法:
if 有新数据要发送
if 数据量超过 MSS (即一个 TCP 包所能携带的最大数据量,通常为 1500-20tcp头-20ip头)
立即发送
else
if 之前发出去的数据尚未确认
把新数据缓存起来,凑够 MSS 或等确认到达再发送
else
立即发送
end if
end if
end if

6、延迟确认和 nagle 算法不能一起用,容易造成网络延迟大的要命

7、虽然说是 TCP 的三次握手,四次挥手,但是有时候,四次挥手,并不一定就是4个数据包,有可能是3个,即中间的 2号包的 ACK 和3号包的 FIN 结合在一起,形成一个数据包。

8、NTLM( NT LAN Manager),一种身份认证协议

  • 客户端向服务器发送一个 NTLM 协商请求,然后服务器立即回复一个随机字符串作为 challenge。
  • 客户端收到 challenge 之后,向服务器回复 用户名,以及两个 response(用hash过的用户密码对 challenge加密得到的)
  • 服务器不知道如何验证真假,所以将 challenge 和 两个response 都转发给 域控Domain Controller ,让域控去帮忙验证真假。
  • 域控收到后,也用 hash过的用户密码对 challenge进行加密。如果加密结果和 reponse一样,说明密码正确,身份验证通过。

由于从数据包里就能看到 challengeresponse ,算法也是固定的,所以并不安全。

9、Kerberos(安全认证协议)

认证过程如下图,kerberos 认证是个双向的过程,即client可以验证serverserver 也可以认证 client

$\blacksquare$ 相关名词解释

  • KDC ( key distributed center ): 整个安全认证过程的票据生成管理服务,包括 AS 和 TGS 服务。
  • AS ( authentication service ): 为 client 生成TGT的服务。
  • TGS( ticket granting service ): 为 client 生成某个服务器的 ticket。
  • TGT ( ticket-granting ticket ): 用于获取 ticket 的票据。

$\blacksquare$ 认证过程

(1) client 向 KDC 中的 AS 发送数据,表明自己的身份,AS对client的身份进行验证,验证通过后返给 client一个 TGT.

(2) client 拿着这个 TGT,给TGS发送数据,说我想访问某个 server。然后TGS会将会话密钥$K_{client-server}$用 client master key加密后传送给client;与此同时,TGS也会将会话密钥$K_{client-server}$连同client的基本信息打包用server master key加密也发client,并经client转发给server,至此client与KDC的交互完成。

(3) client用自己的 master key 解密 TGS 传过来的第一个包,解密后获得会话密钥$K_{client-server}$,并用这个密钥加密自己的的信息和时间戳打包后传送给server。

(4) server会收到两个数据包,一个用会话密钥加密,一个用自己的master key加密,server先用自己的master
key解密获取会话密钥和一份关于client的信息,然后server拿到解密后获取到的会话密钥再解开另外一个数据包,获得另一份关于client的信息和时间戳,对比一下这两份数据,一样即可验证通过。

详细过程请参照:https://blog.csdn.net/yangyang19920306/article/details/51673460

10、TCP Fast Retransmission ,当发送方收到3个及以上 [TCP Dup ACK] 时,就立刻重传它。

[TCP window Full][TCP zerowindow] ,前者表示这个包的发送方暂时没办法再发送数据了(比如说接收方之前告诉我,接收窗口是100,我把100个数据发送过去了,但是都没有收到回复,可能在去的途中,所以为了保险起见,我不能再接着发送了)。后者表示这个包的发送方没办法再接收数据了(告诉对方,我的接收窗口满了,别再发了)。

11、LSO( large segment offload)

传统的网络工作方式是这样的:应用层把产生的数据交给TCP层,TCP层再根据MSS大小进行分段(有CPU负责),然后再交给网卡。而启用LSO之后,TCP层就可以把大于MSS的数据块直接传给网卡,让网卡来负责分段的工作。其实在数据量较大时,数据分段计算校验和等简单操作也挺浪费CPU资源的。在计算机的网卡,高级设置里可以启用这一功能,如下图:

详细说明:https://www.cnblogs.com/tcicy/p/8442225.html

12、TCP中的拥塞控制机制

了解其中的 慢开始、拥塞避免、快重传、快恢复机制。

详细说明:https://blog.csdn.net/jtracydy/article/details/52366461

13、有一种 拥塞窗口的计算方式: $ cwnd = cwnd + MSS*\frac{n \times MSS}{cwnd} $ . n 代表当前接收到的 ack 的个数,当每个数据片返回一个 ack的时候,这个算法是没问题的,即 $\frac{n \times MSS}{cwnd} = 1$ , 每次拥塞窗口增大一个,如上图中的“拥塞避免”状态。但是,我们之前说过,并不是每个数据片都会返回一个 ack 的,有可能攒了好几个才 ack 一次,所以,这种计算方法存在问题,解决方法是关掉网卡中的 Large Receive Offload

14、前面逼逼了辣么多,真实环境抓几个包说道说道。

就拿上面截图的数据包说事吧,数据包下载链接

185.199.109.153 为服务器端,192.168.199.160 为 客户端。

(1) 通信过程详解

首先,1203号包服务器端发送了seq = 939400,len = 1460。

紧接着客户端回复 1204号包,说我已经收到了 ack = 939400+1460 = 940860号包。

正常情况下,服务器接着应该发送 seq = 940860的包给客户端,但是,在 1205号包中,客户端却收到了 seq = 942320 , len = 1460 的数据包,wireshark显示 [ TCP Previous segment not captured ],说明前一个包(seq = 940860的数据包)可能丢了。

既然数据包丢了,客户端就得发送 ack 接着请求,所以,在1206号包中,客户端第二次要求服务器端发送 seq = 940860 的数据,wireshark显示 [ TCP Dup ACK 1204#1 ],代表这是1204号包的再一次请求。

接着,1207号包,客户端收到了 seq = 943780,len = 1460 的数据包( 942320 + 1460 = 943780) 。

1208号包,还没收到 seq = 940860 的数据包,客户端那个气啊,妹的,我再一次重复要求服务器重发 ack = 940860,出现了[ TCP Dup ACK 1204#2 ].

1209号包中,客户端收到了 seq = 946700 , len = 1460 的数据包,现在问题比较大了,两个应该收到的数据包却没有收到,分别是 seq = 940860, seq = 945240 (1207中:943780+1460 = 945240)。同样的,wireshark显示 [ TCP Previous segment not captured ]。

接着,问题得到了改善,在1210号包中,客户端收到了本应该早收到的 seq = 945240, len = 1460 的数据包。wireshark显示 [ TCP Out-Of-Order ],这也说明了,在真实的网络环境中,数据包并不一定是按序到达的。

客户端收到了 seq = 945240 ,seq = 946700(945240+1460) 的数据包,应该发送确认,直到此时,那个 seq = 940860 的包还是没给我发来,丫丫的,在1211号包 和 1212号包中客户端再一次发送 ack = 940860,要求服务器发送 seq = 940860号包给我,wireshark显示[ TCP Dup ACK 1204#3 ],[TCP Dup ACK 1204#4 ]。

在下面的1213 ( seq = 946700+1460 = 948160 )、12141215 (seq = 948160+1460 = 949620 )、12161217 ( seq = 949620+1460 = 951080 )、1218号,6个数据包还是重演之前的画面,客户端收到的是后面的数据包,每收到一个包,就重复确认一次 ack = 940860, 于是出现了图中的 [ TCP Dup ACK 1204#5 ] 、 [ TCP Dup ACK 1204#6 ]、 [ TCP Dup ACK 1204#7 ] 。

最终,好现象终于出现,1219号包,服务器终于发来了盼望已久的 seq = 940860, len = 1460 。一起顺利,所有问题已经解决。由于是乱序到达的,wireshark显示 [ TCP Out-Of-Order ]。

1220号包中,客户端发送对 seq = 940860 的确认,因为之前已经接收到了 seq = 951080+1460 = 952540,所以此时就显示的 ack = 952540 。

接下来,一切正常。

(2) SACK字段展示

拿 1211 号数据包详细说一下之前提到的 SACK 字段。1211数据包是 ack 1209号数据包的吧。有个事实是:我本应该收到 seq = 940860 的,但是,从1205和1207号包中,我收到的是 seq = 942320, seq = 943780 ,所以此时,1211的TCP头部可选字段的 sack : 942320---945240 (943780+1460 = 955240)。从1209号数据包中我收到的是 seq = 946700,所以 1211数据包的TCP头部字段记录第二个 sack : 946700---948160 (946700+1460 = 948160) 。

在TCP的头部可选字段记录这个两个字段值,花掉了 20 字节,所以TCP的头部长度变成了 20 + 20 = 40 Bytes.

同样的,当客户端收到了 1210 号数据包的时候,是不是就把这两个字段中间空缺的那 1460 ( 946700-945240 = 1460 ) 字节给补上了。所以,在 1212号 ack 数据包中,sack : 942320---948160 ,如上图所示。

那么当之前没收到的 seq = 940860 也收到的时候,这个 sack字段就没啥意义了,直接没有了,如 1220号ack包展示的那样。到此,一切那么的完美。

sack字段在变化,同样的,ack 数据包的头部长度也在变化,如上图中: 74 >> 66 >> 54。每次 ack 都会 浪费 一定的带宽,所以,出现了下面的收到多个 seq ,客户端才 ack 一次。

(3) 之前说过,真实的环境中,并不会每个数据包都 ack 一次,如下图,在这里是每收到 2 个数据包才发送一个 ack。

15、TCP在三次握手的时候,客户端与服务器之间会协商 MSS 的大小,防止应用层发送的数据在 IP 层被分片。虽然,分片有时候是不可控的,比如数据包中间经过路由器时,也有可能被路由器分片。

协商过程如下图:

客户端说我的 MSS = 1460, 但是服务器说他的 MSS = 1370,所以,在接下来的数据包中,应用层的数据按照 MSS= 1370 的大小来传输。

16、通过如下命令构造分片的包

1
ping <ip> -l 9000 -n 4

其中的 -l 参数指定发送的 ping 包的大小,9000 Bytes,所以会被分片处理,如下图所示。 -n指定发送的包的个数,还可以使用 -f 参数,指定发送的包不允许分片,即 DF = 1

可以看到,分片数据包的 off 偏移字段,客户端可以根据 ID 字段,识别这是属于哪一个数据的分片包。那么,客户端如何确定什么时候开始重组这些分片的数据包?可以根据分片数据包的 MF 字段,最后一个分片包的 MF = 0 ,代表这是最后一个数据包了,后面没有数据了,这时,客户端就可以重组这些分片的数据包了。

有一种网络的攻击方式: 往客户端持续发送 MF = 1 的数据包,导致客户端一直缓存分片,导致内存耗尽。

17、TCP中避免拥塞的方式有: 接收端通过接收窗口的大小来通知发送端,告知其数据接收能力。同时,发送端

通过拥塞控制算法来动态调整自己的数据发送量。其中:

1
当前数据发送量 = min( 接收窗口大小, 拥塞控制值大小 )

18、因为TCP头中只给接收窗口预留了16个比特(因为当时设计的时候,全世界的带宽都很小),这就意味着它最大只能表示$2^{16} - 1 = 65535$ 字节,网络发展到今天明显不够用啊。后来,想到了一个解决方案,在TCP三次握手的时候,在可选字段中告知对方一个叫 window scale 的值,对方将这个值当做 2 的指数,算出来的值再作为接收窗口的系数。有了这个系数,就可以把接收窗口扩展好多倍了。

从上图中可以看出,客户端告诉服务器,自己的 Win = 65535,放大倍数为 2 倍;接着服务器告诉客户端,自己的 Win = 13600, 放大倍数为 WS = 128 倍。

数据包详情如下图:

19、思考:一个服务器是如何使用 80 端口同时为多个客户端提供服务的?根据连接建立时创建的五元组区分。详细点可以看 多路 I/O复用 epoll

20、在网络层,也就是IP层头部,有那么几个字段:identificationflagsoffset 。因为IP层是无连接的,每产生一个数据报,identification就加 1 ,如果中途的路由器将其分片后,接收端可以根据 flags 中的 MFDF字段以及片偏移字段,将同一个 identification 的数据报重新组装起来。

21、一种流量劫持的手段如下图所示:

实线代表真实的流量,虚线代表劫持的流量。实现的原理就是,我假的服务比你真的服务先响应客户端,这样,等到真的数据来的时候,就会被用户无情的丢弃掉了。

可以通过查看数据包中的 TTL 值,分析流量是否存在被劫持的可能性。

22、HTTP >> HTTP1.1 >> SPDY >> HTTP2.0 QUIC(基于UDP)

23、[ TCP zerowindow ] 表示这个包的发送方已经没有办法再接收数据了,对应包中显示 win = 0

[ TCP window Full ] 表示这个包的发送方暂时没有办法再发送数据了,已经把对方声称的接收窗口已经发满了确没收到ack,只能先暂停。计算在途字节数

24、书上午看完了,总得来说,作业没有在刻意的讲述知识点,通过一个个案例,真实的说明网络知识是如何应用到现实生活的,内容比较基础,对初学者来说不错的书!

屁股后面跟着一堆作业,就这样吧。找个时间,读一下 tshark 的官方文档,感觉功能很强,用得好的话可以省很多事。https://www.wireshark.org/docs/man-pages/tshark.html

之前当当搞活动,加上双十一,买了好多书,下一本:《python黑帽子 黑客与渗透测试编程之道》。

-------------本文结束感谢您的阅读-------------
您的鼓励就是我创作的动力,求打赏买面包~~
0%