You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用tcpdump过滤6379/5432端口含数据TCP数据包的技术咨询

关于tcpdump过滤带数据的6379/5432端口数据包的分析与优化

嘿,我来帮你捋捋这条tcpdump命令的细节和你遇到的问题~

你写的这条命令目标很明确:抓eth0网卡上6379(Redis)和5432(PostgreSQL)端口里带实际数据的TCP数据包,先把你用的完整命令贴出来方便参考:

sudo tcpdump -i eth0 -n -tt 'tcp port 6379 or port 5432 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

核心过滤逻辑拆解

那个看起来复杂的长表达式,其实是手动计算TCP数据包的有效载荷(payload)长度,判断它不为0就意味着包带了数据:

  • ip[2:2]:获取整个IP包的总字节数
  • ((ip[0]&0xf)<<2):计算IP头部的长度(IP头的IHL字段是前4位,乘以4才是实际字节数)
  • 两者相减得到TCP段的总长度(IP总长度减去IP头长度)
  • ((tcp[12]&0xf0)>>2):计算TCP头部的长度(TCP头的Data Offset字段是第13字节的高4位,同样乘以4得字节数)
  • 最后用TCP段总长度减去TCP头长度,结果就是payload的长度,不等于0就说明包有实际数据。

关于你遇到的截断输出

你提到的输出1521257077.232079 IP 10.240.0.40.37978 > 10.240.明显是被截断了,大概率是这两个原因:

  • 终端窗口宽度不够,导致长输出被截断换行或者显示不全,你可以拉大终端窗口后重新执行,或者加-v/-vv参数让输出更详尽,也可以把抓包结果存到文件再分析:
    sudo tcpdump -i eth0 -n -tt 'tcp port 6379 or port 5432 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' -w redis_pg_capture.pcap
    
    之后用tcpdump -r redis_pg_capture.pcap或者Wireshark打开文件,就能看到完整的数据包内容了。
  • 极少数情况是抓包时没捕获到完整数据包,但这种概率很低,先优先排查终端显示问题。

命令优化建议

其实tcpdump本身有更简洁的方式过滤带payload的包,而且你要注意逻辑优先级的问题:

  1. 修正逻辑优先级:你的原始命令里and的优先级比or高,所以实际逻辑是「捕获6379端口的所有TCP包,或者5432端口带数据的TCP包」,如果想让两个端口都应用“带数据”的过滤,必须加括号:
    sudo tcpdump -i eth0 -n -tt 'tcp (port 6379 or port 5432) and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
    
  2. 简化过滤条件:不用手动计算头长度,直接用tcpdump支持的tcp payload(部分版本支持),或者用更直观的方式判断:
    sudo tcpdump -i eth0 -n -tt 'tcp (port 6379 or port 5432) and tcp payload'
    
    如果你的tcpdump版本不支持tcp payload,也可以用这个等价的简化表达式:
    sudo tcpdump -i eth0 -n -tt 'tcp (port 6379 or port 5432) and not tcp[12:1] = 0x50'
    
    这里0x50对应TCP头长度为20字节(Data Offset字段值为5,乘以4就是20),如果TCP头长度等于20且没有选项,同时IP包长度减去IP头和TCP头长度为0的话,就是空包,所以排除这种情况就能抓到带数据的包。

内容的提问来源于stack exchange,提问作者Ratatouille

火山引擎 最新活动