网络排查案例课
杨胜辉
eBay 资深运维专家,流量系统负责人
22781 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 39 讲
实战三:不用抓包就能做的网络排查篇 (2讲)
网络排查案例课
15
15
1.0x
00:00/00:00
登录|注册

04 | 挥手:Nginx日志报connection reset by peer是怎么回事?

确认挥手过程的正确性
Wireshark显示的局限性
挥手过程中的Piggybacking
事务是否成功的确认
服务端日志记录connection reset by peer
客户端异常发送RST
时间范围过滤
TCP标志位过滤
IP地址过滤
TCP协议的灵活性和设计考量
挥手的常见误区解析
通过抓包分析解决应用层问题的经验分享
Wireshark中搜索挥手阶段RST+ACK报文的过滤器
案例2: TCP挥手的特殊情况
案例1: Nginx日志中的RST
半关闭状态的处理
挥手可以同时发起
挥手的发起方可以是客户端或服务端
应用层数据与网络层数据的对比
迭代式过滤
Wireshark过滤器的使用
抓包工具的使用和日志分析
如何将应用层信息与网络层信息关联
应用层日志与网络层信息的差异
实际案例分析
可能的影响和排查方向
意味着TCP连接被对端重置
TCP状态转移
TCP连接的三次握手和四次挥手
TCP协议的重要性
扩展知识
思考题
案例分析
TCP挥手的误区
抓包分析技巧
应用层与网络层的关系
Nginx日志中的connection reset by peer
TCP连接的基础
TCP连接管理与Nginx日志分析

该思维导图由 AI 生成,仅供参考

你好,我是胜辉。今天这节课,我们要通过实际的案例,来学习下 TCP 挥手的知识,在实战中加深对这些知识的理解。
我们在做一些应用排查的时候,时常会在日志里看到跟 TCP 有关的报错。比如在 Nginx 的日志里面,可能就有 connection reset by peer 这种报错。“连接被对端 reset(重置)”,这个字面上的意思是看明白了。但是,心里不免发毛:
这个 reset 会影响我们的业务吗,这次事务到底有没有成功呢?
这个 reset 发生在具体什么阶段,属于 TCP 的正常断连吗?
我们要怎么做才能避免这种 reset 呢?
要回答这类追问,Nginx 日志可能就不够用了。
事实上,网络分层的好处是在于每一层都专心做好自己的事情就行了。而坏处也不是没有,这种情况就是如此:应用层只知道操作系统告诉它,“喂,你的连接被 reset 了”。但是为什么会被 reset 呢?应用层无法知道,只有操作系统知道,但是操作系统只是把事情处理掉,往内部 reset 计数器里加 1,但也不记录这次 reset 的前后上下文。
所以,为了搞清楚 connection reset by peer 时具体发生了什么,我们需要突破应用层这口井,跳出来看到更大的网络世界

在应用层和网络层之间搭建桥梁

确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文通过实际案例介绍了在Nginx日志中出现的"connection reset by peer"错误的排查过程。作者强调了应用层和网络层信息的差异,以及两者之间的鸿沟。通过Wireshark的过滤器,详细介绍了如何从原始抓包文件中定位与问题相关的报文,以及如何将应用层信息与网络层信息联系起来,解决类似的网络排查问题。文章还介绍了如何排除握手阶段和挥手阶段的RST报文,以及如何使用frame.time过滤器定位特定时间段内的报文。最终,通过对比TCP流里的应用层数据和Nginx日志中的请求和返回,找到了是哪个RST引起了Nginx报错。整体而言,本文通过实际案例生动地展示了解决"connection reset by peer"错误的方法,对读者进行了技术上的指导和启发。文章还通过第二个案例介绍了TCP挥手过程中的一些特殊情况,提醒读者在理解TCP知识点时需要深入理解,而不是生搬硬套。通过抓包分析,作者抽丝剥茧,定位到具体的问题环节不在Nginx,也不在网络本身,而是在客户端代码这里。这样的分析让写代码的同学可以专心做代码修复,而不用一直怀疑问题在其他环节。整体而言,本文内容丰富,案例生动,对读者进行了技术上的指导和启发。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络排查案例课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(37)

  • 最新
  • 精选
  • 那时刻
    请问老师,客户端用 RST 来断开连接并不妥当,需要从代码上找原因。比如客户端在 Receive Buffer 里还有数据未被读取的情况下,就调用了 close()。调用close,是不是应该发fin包呢?什么时候会发rst包?

    作者回复: 这是内核的行为。close()系统调用会走到tcp_close(),在这个函数里,会做判断,如果buffer里还有数据未读,它就直接调用tcp_send_active_reset(),发出RST,并把这个连接直接设置到CLOSED状态,也就是不进入TIME_WAIT。 对于这种情况,为了避免close()时候发出RST,就需要检查业务代码,确保在调用close()之前,把接收缓冲里的数据读取掉。

    2022-01-19
    5
    15
  • kaixiao7
    老师,在客户端握手的第三个RST+ACK报文中,为什么会出现RST呢?有哪些情况会出现呢?

    作者回复: 你好,这个要看具体的场景逻辑,有一种场景就是握手的第三个报文是RST+ACK的,那就是健康检查,也就是对服务端口的可达性的检查。发起端发送SYN,服务端回复SYN+ACK,发起端此时知道这个服务端口是可用的(健康的),此时探测任务已经完成了。而用RST+ACK的话可以明确的让服务端关闭这个连接请求(释放资源),在发起端(客户端)也是可以回收资源,对双方都有利。

    2022-05-03
    11
  • *
    老师,tcp.ack和tcp.flags.ack有什么不同,为什么问题1的答案是tcp.ack==1 and tcp.flags.reset == 1

    作者回复: 答案是tcp.flags.ack == 1 and tcp.flags.reset == 1 tcp.ack是指报文的确认号,是一个数字 tcp.flags.ack和tcp.flags.reset都是报文的TCP标志位,不是0就是1

    2022-01-27
    4
    9
  • 最后一个图 有个疑问的, 为什么客户端在初始化关闭的时候 除了发送一个 FIN ,还有个 ACK呢,是为了回复上一个服务端发送的数据吗?

    作者回复: 是的,就是确认它收到的上一个报文。在TCP里面,基本上除了握手的第一个报文SYN,其他报文都带ACK标志位

    2022-01-25
    3
    5
  • 上杉夏香
    这篇文章的最后一张图,是不是有些瑕疵?进入半连接状态后,服务端继续发送数据,当服务器发送FIN报文的时候,它的seq应该不再是L?

    作者回复: 这个图是Stevens的书中的原图。之前没留意,你这么说,我觉得真是个问题。服务器发送的FIN的seq应该是L加上最后一次data的length。你好仔细!~

    2022-06-27
    4
  • 乌龟爱上金鱼
    老师您好,对端向我发了fin,我这边ack后没有close,进入closewait,对端现在应该是finwait2,按理来说对端现在只是不向我发送数据了,但是能接受数据,但是我继续向对端发送数据后,对端回复的是reset,这是为什么呀?

    作者回复: 您好,这确实是一个有意思的话题。TCP确实可以做“半关闭”行为,但是仅根据对端发出的一个FIN报文是无法确切的判定对端是全关闭(同时关闭读和写)还是半关闭(只关闭写)的。但是对端在FIN报文后的行为倒是可以帮助我们做进一步的判断。 比如你遇到的情况是,收到FIN后,你继续发送数据,对端回复了RST。这大概率说明对端是同时关闭了读和写了。也就是说,对端发出FIN的同时,它这个socket已经既不能写入数据(也就是发给你数据),也不能接受数据(也就是接收你在收到FIN后发送的更多的数据报文)了。由于此时对端这个socket处于这种不可读写的状态,所以当对端的内核收到了你的数据报文时,它就用RST做了回复。 当然,如果对端的FIN是由shutdown(sockfd, SHUT_WR)触发的,那就只是关闭写的方向,也会同样发送FIN给你,而此时你继续发送数据报文,对端还是有可能会接收的。总之还是看具体的代码场景了~ 所以我推测,对端当时是用shutdown(sockfd, SHUT_RDWR)或者close(sockfd)来关闭这个连接的。供你参考。

    2022-09-19归属地:上海
    2
    3
  • lxj
    有一点点小提议,分析一个问题能把如何抓包,在哪端抓包,抓包时间点,过滤条件再交代详细点嘛,感觉分析的粒度太粗了,上下文没有交代清楚

    作者回复: 你好,这次的抓包细节是这样的: “所以,我们就展开了抓包工作。具体做法是:我们需要选择一端做抓包,这次是客户端;检查应用日志,发现没几分钟就出现了 connection reset by peer 的报错;对照报错日志和抓包文件,寻找线索。” 对应你的几个问题: 如何抓包:用tcpdump 在哪端抓包:客户端 抓包时间点:这个没有特别的讲究,因为问题一直在发生,随时可以抓 过滤条件: tcpdump host 服务端IP 抓了几分钟就发现日志里有我们找的报错,此时就可以把抓包停止了。因为很容易复现,所以抓包时间不长,只有3分25秒。具体的抓包示例文件我很快上传:)

    2022-04-04
    3
  • sysho
    这两个月刚好排查了几个抓包问题,觉得老师这节课讲得真好,看得很爽。

    作者回复: 是的,抓包分析入门后会发现越来越多的乐趣:)

    2022-04-20
    2
  • 邓坤坤
    老师,请问应用层如何编码才能在发送数据时带上fin flag?从来没见过这种

    作者回复: 一般来说,应用层是通过系统调用(像connect, socket, bind, send, close, shutdown等)来跟内核网络做交互的。TCP标志位是无法直接操作的,只能通过系统调用来“间接”的达到目的。比如你要发送FIN flag,那就对socket描述符调用close()。 另外就是用raw socket直接构造报文,但未必是你想要的吧 如果要直接操纵报文,还有一种办法是用

    2022-08-01归属地:上海
    1
  • 简迷离
    老师,案例中的抓包文件能提供下吗?这样单独的看文章分析效果还是有限,能提供下案例抓包文件边看边分析数据包效果更佳,还请老师提供下,谢谢您!

    作者回复: 您好,后面从第6讲开始大部分都有抓包示例文件了,供你参考~ 这一讲的文件我整理一下:)

    2022-03-27
    1
收起评论
显示
设置
留言
37
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部