tcpdump是抓包常用的工具,可以直接从数据链路层抓取网络数据进行分析。tcpdmp提供了很多命令行参数,提供定制的数据捕获功能。
下面首先会介绍其命令行参数,接着以一个使用场景为例说明使用方法。
1.tcpdump使用说明
1.1 命令行参数
- i interface 网络接口,例如lo0, en0, eth0等
- c count 指定抓包的个数,如果没有提供,则一直监听并抓取
- X 以十六进制和ASCII方式打印报头和数据内容
- v 详细显示指令执行过程
- vv 更加详细的显示执行的执行过程
- vvv 更更详细。。。
1.2 类型的关键字
- host(缺省类型): 指明一台主机,如:host 210.27.48.2
- net: 指明一个网络地址,如:net 202.0.0.0
- port: 指明端口号,如:port 23
1.3 方向的关键字
- src: 例如,src 210.27.48.2, IP包源地址是210.27.48.2
- dst: 例如,dst net 202.0.0.0, 目标网络地址是202.0.0.0
1.4 协议的关键字
缺省值是监听所有协议的信息包
- fddi
- ip
- arp
- rarp
- tcp
- udp
更多的参数说明,请参考关于tcpdump的man page。
2. 抓包举例
2.1 server和client端准备
server端功能说明
server端监听8080端口,如果有连接到来,建立连接后,向客户端发送一条数据,然后关闭连接。
实现上使用golang,代码如下:
package main
import (
"net"
"log"
"time"
)
func main() {
addr := "0.0.0.0:8080"
tcpAddr, err := net.ResolveTCPAddr("tcp",addr)
if err != nil {
log.Fatalf("net.ResovleTCPAddr fail:%s", addr)
}
listener, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
log.Fatalf("listen %s fail: %s", addr, err)
} else {
log.Println("rpc listening", addr)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Println("listener.Accept error:", err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
var buffer []byte = []byte("You are welcome. I'm server.")
for {
time.Sleep(3*time.Second)
n, err := conn.Write(buffer)
if err != nil {
log.Println("Write error:", err)
break
}
log.Println("send:", n)
break
}
log.Println("connetion end")
}
client端功能说明
client端与server建立连接后,从server读取数据,如果对端关闭连接,则client也关闭连接。
实现上使用golang,代码如下:
package main
import (
"log"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err != nil {
log.Println("dial failed:", err)
os.Exit(1)
}
defer conn.Close()
buffer := make([]byte, 512)
for {
n, err := conn.Read(buffer)
if err != nil {
log.Println("Read failed:", err)
return
}
log.Println("count:", n, "msg:", string(buffer))
}
}
2.2 抓包步骤
(1) 执行抓包命令
tcpdump -i lo0 port 8080 -n -vvv -X
tcpdump: listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
在接口lo0上抓取发送和接收端口为8080的数据包。
由于是在本地测试,client和server在同一台主机上,因此抓取lo0接口。
另外,执行命令时需要超级权限。
(2) 启动server
./server
2019/04/13 18:40:30 rpc listening 0.0.0.0:8080
2019/04/13 18:41:08 send: 28
2019/04/13 18:41:08 connetion end
(3) 启动client
./client
2019/04/13 18:41:08 count: 28 msg: You are welcome. I'm server.
2019/04/13 18:41:08 Read failed: EOF
(4) 查看抓到的数据包
首先是三次握手。
SYN:
18:41:05.618523 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64, bad cksum 0 (->3cb6)!)
127.0.0.1.61930 > 127.0.0.1.8080: Flags [S], cksum 0xfe34 (incorrect -> 0xdd83), seq 66368567, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 1414333278 ecr 0,sackOK,eol], length 0
0x0000: 4500 0040 0000 4000 4006 0000 7f00 0001 E..@..@.@.......
0x0010: 7f00 0001 f1ea 1f90 03f4 b437 0000 0000 ...........7....
0x0020: b002 ffff fe34 0000 0204 3fd8 0103 0306 .....4....?.....
0x0030: 0101 080a 544d 035e 0000 0000 0402 0000 ....TM.^........
SYN+ACK:
18:41:05.618580 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64, bad cksum 0 (->3cb6)!)
127.0.0.1.8080 > 127.0.0.1.61930: Flags [S.], cksum 0xfe34 (incorrect -> 0x15f3), seq 3395921258, ack 66368568, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 1414333278 ecr 1414333278,sackOK,eol], length 0
0x0000: 4500 0040 0000 4000 4006 0000 7f00 0001 E..@..@.@.......
0x0010: 7f00 0001 1f90 f1ea ca69 a56a 03f4 b438 .........i.j...8
0x0020: b012 ffff fe34 0000 0204 3fd8 0103 0306 .....4....?.....
0x0030: 0101 080a 544d 035e 544d 035e 0402 0000 ....TM.^TM.^....
ACK:
18:41:05.618593 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.61930 > 127.0.0.1.8080: Flags [.], cksum 0xfe28 (incorrect -> 0x76fc), seq 1, ack 1, win 6379, options [nop,nop,TS val 1414333278 ecr 1414333278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 f1ea 1f90 03f4 b438 ca69 a56b ...........8.i.k
0x0020: 8010 18eb fe28 0000 0101 080a 544d 035e .....(......TM.^
0x0030: 544d 035e TM.^
接着,连接建立后,server端向client端发送数据:
18:41:05.618605 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.8080 > 127.0.0.1.61930: Flags [.], cksum 0xfe28 (incorrect -> 0x76fc), seq 1, ack 1, win 6379, options [nop,nop,TS val 1414333278 ecr 1414333278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 1f90 f1ea ca69 a56b 03f4 b438 .........i.k...8
0x0020: 8010 18eb fe28 0000 0101 080a 544d 035e .....(......TM.^
0x0030: 544d 035e TM.^
18:41:08.620640 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 80, bad cksum 0 (->3ca6)!)
127.0.0.1.8080 > 127.0.0.1.61930: Flags [P.], cksum 0xfe44 (incorrect -> 0x6769), seq 1:29, ack 1, win 6379, options [nop,nop,TS val 1414336278 ecr 1414333278], length 28: HTTP
0x0000: 4500 0050 0000 4000 4006 0000 7f00 0001 E..P..@.@.......
0x0010: 7f00 0001 1f90 f1ea ca69 a56b 03f4 b438 .........i.k...8
0x0020: 8018 18eb fe44 0000 0101 080a 544d 0f16 .....D......TM..
0x0030: 544d 035e 596f 7520 6172 6520 7765 6c63 TM.^You.are.welc
0x0040: 6f6d 652e 2049 276d 2073 6572 7665 722e ome..I'm.server.
client接收数据后,发送ACK给server端:
18:41:08.620685 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.61930 > 127.0.0.1.8080: Flags [.], cksum 0xfe28 (incorrect -> 0x5f70), seq 1, ack 29, win 6379, options [nop,nop,TS val 1414336278 ecr 1414336278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 f1ea 1f90 03f4 b438 ca69 a587 ...........8.i..
0x0020: 8010 18eb fe28 0000 0101 080a 544d 0f16 .....(......TM..
0x0030: 544d 0f16 TM..
server关闭到client方向的连接,发送FIN:
18:41:08.620751 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.8080 > 127.0.0.1.61930: Flags [F.], cksum 0xfe28 (incorrect -> 0x5f6f), seq 29, ack 1, win 6379, options [nop,nop,TS val 1414336278 ecr 1414336278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 1f90 f1ea ca69 a587 03f4 b438 .........i.....8
0x0020: 8011 18eb fe28 0000 0101 080a 544d 0f16 .....(......TM..
0x0030: 544d 0f16 TM..
client发送ACK:
18:41:08.620787 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.61930 > 127.0.0.1.8080: Flags [.], cksum 0xfe28 (incorrect -> 0x5f6f), seq 1, ack 30, win 6379, options [nop,nop,TS val 1414336278 ecr 1414336278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 f1ea 1f90 03f4 b438 ca69 a588 ...........8.i..
0x0020: 8010 18eb fe28 0000 0101 080a 544d 0f16 .....(......TM..
0x0030: 544d 0f16 TM..
client 断开到server方向的连接,发送FIN:
18:41:08.621085 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.61930 > 127.0.0.1.8080: Flags [F.], cksum 0xfe28 (incorrect -> 0x5f6e), seq 1, ack 30, win 6379, options [nop,nop,TS val 1414336278 ecr 1414336278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 f1ea 1f90 03f4 b438 ca69 a588 ...........8.i..
0x0020: 8011 18eb fe28 0000 0101 080a 544d 0f16 .....(......TM..
0x0030: 544d 0f16 TM..
server端发送ACK:
18:41:08.621133 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
127.0.0.1.8080 > 127.0.0.1.61930: Flags [.], cksum 0xfe28 (incorrect -> 0x5f6e), seq 30, ack 2, win 6379, options [nop,nop,TS val 1414336278 ecr 1414336278], length 0
0x0000: 4500 0034 0000 4000 4006 0000 7f00 0001 E..4..@.@.......
0x0010: 7f00 0001 1f90 f1ea ca69 a588 03f4 b439 .........i.....9
0x0020: 8010 18eb fe28 0000 0101 080a 544d 0f16 .....(......TM..
0x0030: 544d 0f16 TM..