Skip to main content

tcpdump_resp

· 3 min read

最近使用tcpdump 抓包发现居然支持RESP 协议的解析

tcpdump -i lo port 6379

当我在redis-cli 敲 set a a时候,tcpdump返回

seq 1023993873:1023993900, ack 4077734227, win 342, options [nop,nop,TS val 2912390058 ecr 2912384753], length 27: RESP "set" "a" "a"
  • 如何实现?

去githup 上拿下来编译之后,发现是调用resp_print解析RESP协议的,而且是固定端口的,当端口是6379的时候会尝试用redis的协议解析

void
tcp_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2, int fragmented)
{
...
if (ndo->ndo_packettype) {
switch (ndo->ndo_packettype) {
case PT_ZMTP1:
zmtp1_print(ndo, bp, length);
break;
case PT_RESP: // 指定解析类型 -T
resp_print(ndo, bp, length);
break;
}
return;
}
...
else if (IS_SRC_OR_DST_PORT(REDIS_PORT)) //REDIS_PORT=6379
resp_print(ndo, bp, length);
...
}
(gdb) bt
#0 resp_print (ndo=0x7fffffffca40, bp=0x7ffff6e82088 "*3\r\n$3\r\nset\r\n$1\r\na\r\n$1\r\na\r\n", length=27) at ./print-resp.c:214
#1 0x000000000045ae3f in tcp_print (ndo=0x7fffffffca40, bp=0x7ffff6e82088 "*3\r\n$3\r\nset\r\n$1\r\na\r\n$1\r\na\r\n", length=27, bp2=0x7ffff6e82054 "E", fragmented=0) at ./print-tcp.c:723
#2 0x0000000000420f52 in ip_print_demux (ndo=0x7fffffffca40, bp=0x7ffff6e82068 "\242D\030\353=\b\350\021\363\rIS\200\030\001V\376C", length=59, ver=4, fragmented=0, ttl_hl=64, nh=6 '\006',
iph=0x7ffff6e82054 "E") at ./print-ip-demux.c:100
#3 0x0000000000420b1b in ip_print (ndo=0x7fffffffca40, bp=0x7ffff6e82054 "E", length=79) at ./print-ip.c:493
#4 0x000000000041bf64 in ethertype_print (ndo=0x7fffffffca40, ether_type=2048, p=0x7ffff6e82054 "E", length=79, caplen=79, src=0x7fffffffc680, dst=0x7fffffffc690) at ./print-ether.c:490
#5 0x000000000041bb03 in ether_print_common (ndo=0x7fffffffca40, p=0x7ffff6e82054 "E", length=79, caplen=79, print_switch_tag=0x0, switch_tag_len=0, print_encap_header=0x0, encap_header_arg=0x0)
at ./print-ether.c:345
#6 0x000000000041bc44 in ether_print (ndo=0x7fffffffca40, p=0x7ffff6e82046 "", length=93, caplen=93, print_encap_header=0x0, encap_header_arg=0x0) at ./print-ether.c:401
#7 0x000000000041bc94 in ether_if_print (ndo=0x7fffffffca40, h=0x7fffffffc7e0, p=0x7ffff6e82046 "") at ./print-ether.c:416
#8 0x00000000004078fe in pretty_print_packet (ndo=0x7fffffffca40, h=0x7fffffffc7e0, sp=0x7ffff6e82046 "", packets_captured=1) at ./print.c:414
#9 0x0000000000406d84 in print_packet (user=0x7fffffffca40 "", h=0x7fffffffc7e0, sp=0x7ffff6e82046 "") at ./tcpdump.c:2984
#10 0x00007ffff7755ef6 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#11 0x00007ffff775a4a3 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#12 0x00007ffff775f1fd in pcap_loop () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#13 0x00000000004060b1 in main (argc=5, argv=0x7fffffffddd8) at ./tcpdump.c:2438

其他端口解析RESP

如果你的redis-server 不是在6379,只要加上-T RESP 即可在其他端口解析RESP协议

sudo tcpdump -i lo port 7777 -T RESP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
13:07:31.737440 IP localhost.42466 > localhost.7777: Flags [P.], seq 2285148837:2285148864, ack 2982472773, win 342, options [nop,nop,TS val 2913788220 ecr 2913780890], length 27: RESP "set" "a" "a"
13:07:31.737680 IP localhost.7777 > localhost.42466: Flags [P.], seq 1:6, ack 27, win 342, options [nop,nop,TS val 2913788220 ecr 2913788220], length 5: RESP "OK"
13:07:31.737706 IP localhost.42466 > localhost.7777: Flags [.], ack 6, win 342, options [nop,nop,TS val 2913788220 ecr 2913788220], length 0