大家好,我是轩辕。 前几天,我在读者群里提了一个问题: 这一下,大家总算停止了灌水(这群人都不用上班的,天天划水摸鱼),开始讨论起这个问题来。 有的说通过User-Agent可以看,我直接给了一个狗头。 然后发现不对劲,改口说可以通过HTTP响应的Server字段看,比如看到像这种的,那肯定Windows无疑了。 HTTP/1.1 200 OK 还有的说可以通过URL路径来判断,如果大小写敏感就是Linux,不敏感就是Windows。 于是我进一步提高了难度,如果连Web服务也没有,只有一个TCP Server呢? 这时又有人说:可以通过ping这个IP,查看ICMP报文中的TTL值,如果是xxx就是xx系统,如果是yyy就是yy系统···(不过有些情况下也不是太准确) 从TCP重传说起今天想跟大家探讨的是另外一种方法,这个方法的思路来源于前几天被删掉的那篇文章。就是日本网络环境下访问不了极客时间的问题,当时抓包看到的情况是这个图的样子: 看到了服务器后面在不断的尝试重发了吗?当时我就想到了一个问题: 服务器到底会重传好多次呢? 众所周知,TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。 其中,可靠性的一个重要体现就是它的超时重传机制。 TCP的通信中有一个确认机制,我发给你了数据,你得告诉我你收到没,这样双方才能继续通信下去,这个确认机制是通过序列号SEQ和确认号ACK来实现的。 简单来说,当发送方给接收方发送了一个报文,而接收方在规定的时间里没有给出应答,那发送方将认为有必要重发。 那具体最多重发多少次呢?关于这一点,RFC中关于TCP的文档并未明确规定出来,只是给了一些在总超时时间上的参考,这就导致不同的操作系统在实现这一机制的时候可能会有一些差异。于是我进一步想到了另一个问题: 会不会不同操作系统重传次数不一样,这样就能通过这一点来判断操作系统了呢? 然后我翻看了《TCP/IP详解·卷1》,试图在里面寻找答案,果然,这本神书从来没有让我失望过: 这一段说了个什么事情呢?大意是说RFC标准中建议有两个参数R1和R2来控制重传的次数,Linux中,这俩参数可以这样看:
但需要特别注意的是,并不是最多重传3次或者15次,Linux内部有一套算法,这两个值是算法中非常重要的参数,而不是重传次数本身。具体的重传次数还与 总体来说,在Linux上重传的次数不是一个固定值,而是不同的连接根据 而在Windows上,也有一个变量来控制重传次数,可以在注册表中设定它: 键值路径: 我手里有一份Windows XP的源码,在实现协议栈的驱动 不过就目前的信息来看,由于Linux的重传次数是不固定的,还没法用这个重传次数来判断操作系统。 TCP之SYN+ACK的重传就在我想要放弃的时候,我再一次品读《TCP/IP详解·卷1》中的那段话,发现另一个信息:TCP的重传在建立连接阶段和数据传输阶段是不一样的! 上面说到的重传次数限制,是针对的是TCP连接已经建立完成,在数据传输过程中发生超时重传后的重传次数情况描述。 而在TCP建立连接的过程中,也就是三次握手的过程中,发生超时重传,它的次数限定是有另外一套约定的。 Linux: 在Linux中,另外还有两个参数来限定建立连接阶段的重传次数:
重点来关注这个 我们知道正常情况下,TCP的三次握手是这个样子的: 但如果客户端不给服务端发起第三个包,那服务端就会重发它的第二次握手包,情况就会变成下面这样: 所以,这个 为了进一步验证,我使用Python写了一段代码,用来手动发送TCP报文,里面使用的发包库是scapy,这个我之前写过一篇文章介绍它:面向监狱编程,就靠它了!。 下面的这段代码,我向目标IP的指定端口只发送了一个SYN包,: def tcp_syn_test(ip, port): 用上面这段代码,向一台Linux的服务器发送,抓包来看一下: 实际验证,服务器确实重传了5次SYN+ACK报文。 一台服务器说明不了问题,我又多找了几个,结果都是5次。 再来看一下Linux的源码中关于这个次数的定义: 接下来看一下Windows上的情况。 Windows前面说过,在注册表 根据 而且有趣的是,和Linux上的默认值不一样,Windows上的默认值是2。 这就有意思了,通过这一点,就能把Windows和Linux区分开来。 我赶紧用虚拟机中的XP上跑了一个nginx,测试了一下: 果然是2次,随后我又换了一个Windows Server 2008,依旧是2次。 为了进一步验证,我通过注册表把这个值设定成了4: 再来试一下: 重传次数果然变成了4次了。 接下来在手中的Windows XP源码中去印证这个信息: 果然,不管是从实验还是从源码中都得到了同一个结论:
总结如果一个IP开启了基于TCP的服务,不管是不是HTTP服务,都可以通过向其发送SYN包,观察其回应来判断对方是一个Linux操作系统还是一个Windows操作系统。 当然,这种方法的局限性还是挺大的。 首先,本文只介绍了一些默认的情况,但TCP的重传次数是可以更改的,如果网络管理员更改了这个数值,判断的结果就不准确了。 其次,对于有些网络服务器开启了防DDoS功能,测试发现,其根本不会重传SYN+ACK包,比如我用百度的IP测试就得到了这样的结果。 最后,没有测试其他操作系统上的情况,比如Unix和MAC OSX,为什么呢? 因此,文中介绍的这种方法只能作为一种辅助手段,仅供参考,大家能顺便了解一些关于TCP重传的知识也是很有意义的。 好了,以上就是今天的分享了,写作不易,大家看完给个三连支持呀~ |
|
来自: 新用户0118F7lQ > 《微信文章》