실행을 할 경우 본인이 실행되는 시간 동안 시스템에서 돌아다녔던 packet들에 대한 정보를 전부 분석한다. 이 때 실행되는 동안 특정 조건을 만족하는 packet들에 대해서만 정보를 얻도록 설정하는 것도 가능하다.
저장 기능을 통해 (-w) 나중에 분석을 하는 것도 가능하다.
보통 기본적으로 설치가 되어 있다. Ubuntu의 경우 22.03 기준 기본으롯 설치가 되어 있으며 확인을 하고싶으면 which를 사용해서 어디에 설치되어있는지 보도록 하자.
보통 실행하려면 관리자 권한이 필요하다.
tcpdump로도 이를 파악하는게 가능하다. -D option을 사용하면 된다.$ tcpdump -D
1.eth0 [Up, Running, Connected]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]
4.bluetooth-monitor (Bluetooth Linux Monitor) [Wireless]
5.nflog (Linux netfilter log (NFLOG) interface) [none]
6.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
7.dbus-system (D-Bus system bus) [none]
8.dbus-session (D-Bus session bus) [none]
특정 인터페이스의 packet을 탐지하게 하고 싶으면 --interface를 사용하면 된다. 만약 이게 주어지지 않고 -d가 주어지지 않으면, 저 -D에서 나온 인터페이스들 중 lo가 아닌 가장 상위 인터페이스를 사용한다. 이는 보통 위처럼 eth0이 된다.
모든 인터페이스에 대해 탐지를 할거면 특정 MacOS, Linux, Solaris의 경우 any를 사용하면 된다.
$ sudo tcpdump --interface=any
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
16:51:27.061243 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 3130648948:3130649199, ack 1141574278, win 512, options [nop,nop,TS val 3018721591 ecr 3018721531], length 251
16:51:27.061267 lo In IP localhost.38184 > localhost.34821: Flags [.], ack 251, win 24571, options [nop,nop,TS val 3018721591 ecr 3018721545], length 0
16:51:27.083105 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 251:476, ack 1, win 512, options [nop,nop,TS val 3018721612 ecr 3018721591], length 225
16:51:27.086212 lo In IP localhost.38186 > localhost.34821: Flags [P.], seq 2036841800:2036842060, ack 561355744, win 512, options [nop,nop,TS val 3018721615 ecr 3018721550], length 260
16:51:27.088033 lo In IP localhost.34821 > localhost.38186: Flags [P.], seq 1:39, ack 260, win 24571, options [nop,nop,TS val 3018721617 ecr 3018721615], length 38
...
16:51:28.853172 lo In IP localhost.38184 > localhost.34821: Flags [.], ack 11202, win 24571, options [nop,nop,TS val 3018723382 ecr 3018723382], length 0
^C
59 packets captured
132 packets received by filter
0 packets dropped by kernel
16:51:27.061243 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 3130648948:3130649199, ack 1141574278, win 512, options [nop,nop,TS val 3018721591 ecr 3018721531], length 251
16:51:27.061243 : 해당 packet을 인터페이스에서 받은 시간. 시:분:초 형식이다.lo : 인터페이스 이름IP : IPv4. IPv6인 경우 IP6라고 나온다.localhost.34821 > localhost.38184 : (발신 ip 주소).(발신 port 번호) > (수신 ip 주소).(수신 port 번호)Flags [...] : TCP flag. 보통 다음이 가능하며 밑이 여러개가 섞일 수도 있다.S : SYN type. 연결 시작때 보통 쓰인다.F : FIN type. 연결 종료때 보통 쓰인다.P : PUSH type. 전송된 data가 버퍼에 들어가지 않고 즉시 상위 애플리케이션에게 전달되어야 하는 경우 쓰인다.R : RST type. 연결을 강제로 끊을 때 쓰인다. 자세한 내용은 이 글 참고. : ACK type. acknowledgement를 나타낸다.seq : packet 안의 sequence number. 위와 같은 경우인, tcpdump의 해당 connection의 첫 packet 같은 경우에는 실제값을 출력을 하나, 이후 같은 연결에 대해서 packet이 등장할 경우 그 값을 기준으로 상대적인 sequence number을 출력한다. 예를들어 다음이 seq 251:650인 경우, 위의 실제 값의 시작 부분에 251을 더한거랑 650을 더한것의 byte를 담은 packet이라는 것을 의미한다.win : window size. 수신 측 buffer 크기를 담고 있다.options : TCP에서 설정할 수 있는 option들에 대한 정보다. 여러개가 가능한데 (MSS, Window Scale, Selective ACK permitted, Selective ACK) 위 예시의 경우 TS, 즉 timestamp만 나와 있다. nop는 주로 padding 용도. Timestamp는 처음은 본인이 보낸 시간, 그 다음 ecr는 마지막으로 어딘가에서 packet을 받은 시간이다.length : "payload"의 길이다. packet의 길이가 아니다. sequence number의 두 차이랑 같아야 한다.tcpdump를 종료할지를 정할 때 쓰인다. 밑의 경우 5개의 packet까지만을 탐지하고 tcpdump를 종료했다.$ sudo tcpdump --interface=any -c 5
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
16:56:20.342894 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 3130790748:3130790999, ack 1141595685, win 512, options [nop,nop,TS val 3019014872 ecr 3019014762], length 251
16:56:20.363787 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 251:491, ack 1, win 512, options [nop,nop,TS val 3019014893 ecr 3019014762], length 240
16:56:20.363886 lo In IP localhost.38184 > localhost.34821: Flags [.], ack 491, win 24571, options [nop,nop,TS val 3019014893 ecr 3019014872], length 0
16:56:20.390722 lo In IP localhost.34821 > localhost.38184: Flags [P.], seq 491:630, ack 1, win 512, options [nop,nop,TS val 3019014920 ecr 3019014893], length 139
16:56:20.394793 lo In IP localhost.38186 > localhost.34821: Flags [P.], seq 2036929641:2036929707, ack 561371280, win 512, options [nop,nop,TS val 3019014924 ecr 3019014766], length 66
5 packets captured
16 packets received by filter
0 packets dropped by kernel
$ sudo tcpdump --interface=any -n -nn -c 5
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
16:58:19.202188 lo In IP 127.0.0.1.34821 > 127.0.0.1.38184: Flags [P.], seq 3130905710:3130905961, ack 1141620564, win 512, options [nop,nop,TS val 3019133731 ecr 3019133674], length 251
16:58:19.202227 lo In IP 127.0.0.1.38184 > 127.0.0.1.34821: Flags [.], ack 251, win 24571, options [nop,nop,TS val 3019133731 ecr 3019133731], length 0
16:58:19.223340 lo In IP 127.0.0.1.34821 > 127.0.0.1.38184: Flags [P.], seq 251:650, ack 1, win 512, options [nop,nop,TS val 3019133753 ecr 3019133731], length 399
16:58:19.223365 lo In IP 127.0.0.1.38184 > 127.0.0.1.34821: Flags [.], ack 650, win 24570, options [nop,nop,TS val 3019133753 ecr 3019133753], length 0
16:58:19.243750 lo In IP 127.0.0.1.34821 > 127.0.0.1.38184: Flags [P.], seq 650:789, ack 1, win 512, options [nop,nop,TS val 3019133773 ecr 3019133753], length 139
5 packets captured
26 packets received by filter
0 packets dropped by kernel
tcpdump의 man page를 보면 맨 마지막에 expression이라는 항목이 보일 것이다. 그 부분이 무슨 packet을 덤핑할 것인지에 대해 전부 정해지는 식이다.
특정 조건에 맞는 packet에 보통 관심이 있기 때문에, 이 expression을 어떻게 짜냐가 매우 중요하다. 이에 대해 pcap-filter이라고 따로 man page가 있다.
구조는 여러개의 primitive들이 combinator (and, or)이랑 조합되는 형태로 이루어진다. 이들 중 몇개만 여기서 소개를 한다.
ip proto protocol이다. 이는 transport layer에서 특정 protocol을 쓰는 IP packet들을 filtering하는 것인데, protocol에 탐지하고 싶은 transport layer protocol이 들어간다. (ex tcp) 밑은 icmp를 탐지하는 경우다.$ sudo tcpdump -i any -c 5 icmp
[sudo] password for sycho:
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:20:26.730932 eth0 Out IP 172.31.115.194 > DESKTOP-AKD4OTF.mshome.net: ICMP 172.31.115.194 udp port 46269 unreachable, length 166
20:20:27.000066 eth0 Out IP 172.31.115.194 > 151.101.194.133: ICMP echo request, id 1, seq 21, length 64
20:20:27.007663 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 1, seq 21, length 64
20:20:27.772276 eth0 Out IP 172.31.115.194 > DESKTOP-AKD4OTF.mshome.net: ICMP 172.31.115.194 udp port 58528 unreachable, length 142
20:20:28.789737 eth0 Out IP 172.31.115.194 > DESKTOP-AKD4OTF.mshome.net: ICMP 172.31.115.194 udp port 38239 unreachable, length 166
5 packets captured
8 packets received by filter
0 packets dropped by kernel
pcap-filter man page를 참고하자.host hostaddr의 형태를 가지며, hostaddr에 송신/수신 측 주소를 입력한다. 기본적으로 IPv4랑 IPv6를 전부 탐지해낸다.$ sudo tcpdump -i any -c 5 -nn host 151.101.194.133
[sudo] password for sycho:
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:46:44.284328 eth0 Out IP 172.31.115.194 > 151.101.194.133: ICMP echo request, id 2, seq 37, length 64
20:46:44.292413 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 37, length 64
20:46:45.314569 eth0 Out IP 172.31.115.194 > 151.101.194.133: ICMP echo request, id 2, seq 38, length 64
20:46:45.322961 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 38, length 64
20:46:46.344901 eth0 Out IP 172.31.115.194 > 151.101.194.133: ICMP echo request, id 2, seq 39, length 64
5 packets captured
6 packets received by filter
0 packets dropped by kerne
src나 dst를 사용해 hostaddr이 송신/수신 주소인 경우에 대해서만 탐지해내는 것이 가능하다.$ sudo tcpdump -i any -c 5 -nn src 151.101.194.133
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:51:43.142119 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 327, length 64
20:51:44.180654 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 328, length 64
20:51:45.204586 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 329, length 64
20:51:46.229111 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 330, length 64
20:51:47.252601 eth0 In IP 151.101.194.133 > 172.31.115.194: ICMP echo reply, id 2, seq 331, length 64
5 packets captured
5 packets received by filter
0 packets dropped by kernel
$ sudo tcpdump src net 151.101.194.0/24
port portnamenum의 형태를 가진다. portnamenum에 송신/수신 측 port를 입력한다. 밑은 port 80, 즉 http request/reply에 관한 packet 송수신만 탐지해낸 결과다.$ sudo tcpdump -i any -c 5 -nn port 80
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:49:53.909918 eth0 Out IP 172.31.115.194.38966 > 151.101.194.133.80: Flags [S], seq 2582613412, win 64240, options [mss 1460,sackOK,TS val 3747761997 ecr 0,nop,wscale 7], length 0
20:49:53.918037 eth0 In IP 151.101.194.133.80 > 172.31.115.194.38966: Flags [S.], seq 3178615467, ack 2582613413, win 65535, options [mss 1360,sackOK,TS val 1982683470 ecr 3747761997,nop,wscale 9], length 0
20:49:53.918182 eth0 Out IP 172.31.115.194.38966 > 151.101.194.133.80: Flags [.], ack 1, win 502, options [nop,nop,TS val 3747762006 ecr 1982683470], length 0
20:49:53.918289 eth0 Out IP 172.31.115.194.38966 > 151.101.194.133.80: Flags [P.], seq 1:79, ack 1, win 502, options [nop,nop,TS val 3747762006 ecr 1982683470], length 78: HTTP: GET / HTTP/1.1
20:49:53.926792 eth0 In IP 151.101.194.133.80 > 172.31.115.194.38966: Flags [.], ack 79, win 264, options [nop,nop,TS val 1982683478 ecr 3747762006], length 0
5 packets captured
9 packets received by filter
0 packets dropped by kernel
host와 마찬가지로 src와 dst를 이용해서 송신이나 수신 port가 portnamenum인 경우만을 탐지하는게 가능하다.$ sudo tcpdump -i any -c 5 -nn src port 80
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:53:48.671575 eth0 In IP 151.101.194.133.80 > 172.31.115.194.46844: Flags [S.], seq 1625515983, ack 1127016704, win 65535, options [mss 1360,sackOK,TS val 882656498 ecr 3747996751,nop,wscale 9], length 0
20:53:48.680100 eth0 In IP 151.101.194.133.80 > 172.31.115.194.46844: Flags [.], ack 79, win 264, options [nop,nop,TS val 882656507 ecr 3747996759], length 0
20:53:48.680100 eth0 In IP 151.101.194.133.80 > 172.31.115.194.46844: Flags [P.], seq 1:324, ack 79, win 264, options [nop,nop,TS val 882656507 ecr 3747996759], length 323: HTTP: HTTP/1.1 301 Moved Permanently
20:53:48.680100 eth0 In IP 151.101.194.133.80 > 172.31.115.194.46844: Flags [F.], seq 324, ack 79, win 264, options [nop,nop,TS val 882656507 ecr 3747996759], length 0
20:53:48.688162 eth0 In IP 151.101.194.133.80 > 172.31.115.194.46844: Flags [.], ack 80, win 264, options [nop,nop,TS val 882656515 ecr 3747996768], length 0
5 packets captured
5 packets received by filter
0 packets dropped by kernel
$ sudo tcpdump portrange 20-100
$ tcpdump "len > 32 and len < 64"
$ sudo tcpdump -i any -c 5 -nn src port 80 and src 151.101.194.133
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
20:56:47.923128 eth0 In IP 151.101.194.133.80 > 172.31.115.194.34296: Flags [S.], seq 622690809, ack 3966489657, win 65535, options [mss 1360,sackOK,TS val 2364886915 ecr 3748176001,nop,wscale 9], length 0
20:56:47.932117 eth0 In IP 151.101.194.133.80 > 172.31.115.194.34296: Flags [.], ack 79, win 264, options [nop,nop,TS val 2364886924 ecr 3748176011], length 0
20:56:47.932117 eth0 In IP 151.101.194.133.80 > 172.31.115.194.34296: Flags [P.], seq 1:324, ack 79, win 264, options [nop,nop,TS val 2364886924 ecr 3748176011], length 323: HTTP: HTTP/1.1 301 Moved Permanently
20:56:47.932117 eth0 In IP 151.101.194.133.80 > 172.31.115.194.34296: Flags [F.], seq 324, ack 79, win 264, options [nop,nop,TS val 2364886925 ecr 3748176011], length 0
20:56:47.941347 eth0 In IP 151.101.194.133.80 > 172.31.115.194.34296: Flags [.], ack 80, win 264, options [nop,nop,TS val 2364886934 ecr 3748176020], length 0
5 packets captured
11 packets received by filter
괄호를 써서 우선순위 부여를 통해 더 복잡한 식을 만드는것도 가능은 한데, 이 경우 ""으로 둘러싸야 한다. shell expression이랑 혼동되지 않도록 하기 위해서다.
and, or, not를 가지고 적극적으로 활용해보자. 밑은 icmp가 아닌, dst가 192.168.0.0이고 src가 192.168.0.1인 packet들에 대해서만 감지한다.
$ sudo tcpdump dst 192.168.0.0 and src 192.168.0.1 and not icmp
curl로 간단하게 HTTP request를 한 것에 대한 packet 분석이다.$ sudo tcpdump -i any -c 5 -nn -A src port 80 and src 151.101.194.133
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
21:00:09.613604 eth0 In IP 151.101.194.133.80 > 172.31.115.194.58946: Flags [S.], seq 2940694077, ack 515812285, win 65535, options [mss 1360,sackOK,TS val 2408165261 ecr 3748377692,nop,wscale 9], length 0
E..<..@.8....e....s..P.B.Gn=........-......P...
.....k.\...
21:00:09.621848 eth0 In IP 151.101.194.133.80 > 172.31.115.194.58946: Flags [.], ack 79, win 264, options [nop,nop,TS val 2408165270 ecr 3748377701], length 0
E..4..@.8....e....s..P.B.Gn>........Z......
.....k.e
21:00:09.622331 eth0 In IP 151.101.194.133.80 > 172.31.115.194.58946: Flags [P.], seq 1:324, ack 79, win 264, options [nop,nop,TS val 2408165271 ecr 3748377701], length 323: HTTP: HTTP/1.1 301 Moved Permanently
E..w..@.8....e....s..P.B.Gn>......../......
.....k.eHTTP/1.1 301 Moved Permanently
Connection: close
Content-Length: 0
Server: Varnish
Retry-After: 0
Location: https://opensource.com/
Accept-Ranges: bytes
Date: Sat, 23 Dec 2023 12:00:08 GMT
Via: 1.1 varnish
X-Served-By: cache-icn1450082-ICN
X-Cache: HIT
X-Cache-Hits: 0
Strict-Transport-Security: max-age=300
21:00:09.622331 eth0 In IP 151.101.194.133.80 > 172.31.115.194.58946: Flags [F.], seq 324, ack 79, win 264, options [nop,nop,TS val 2408165271 ecr 3748377701], length 0
E..4..@.8..,.e....s..P.B.Go.........X......
.....k.e
21:00:09.631157 eth0 In IP 151.101.194.133.80 > 172.31.115.194.58946: Flags [.], ack 80, win 264, options [nop,nop,TS val 2408165279 ecr 3748377710], length 0
E..4..@.8..+.e....s..P.B.Go.........X......
.....k.n
5 packets captured
5 packets received by filter
0 packets dropped by kernel
-w로 내용물을 저장하는게 가능하다. 이 경우 출력이 안 나오게 된다. 저장할 파일의 이름을 -w 옆에 지정해야 한다. 보통 pcap확장자를 사용하는데, packet capture의 약자다.$ sudo tcpdump -i any -c 5 -nn -w result.pcap src port 80 and src 151.101.194.133
[sudo] password for sycho:
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
5 packets captured
5 packets received by filter
0 packets dropped by kernel
-r을 사용하면 된다.$ sudo tcpdump -r result.pcap
reading from file result.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144
Warning: interface names might be incorrect
21:05:06.223271 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [S.], seq 60975892, ack 997167500, win 65535, options [mss 1360,sackOK,TS val 3732285903 ecr 3748674302,nop,wscale 9], length 0
21:05:06.232467 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [.], ack 79, win 264, options [nop,nop,TS val 3732285912 ecr 3748674311], length 0
21:05:06.232468 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [P.], seq 1:324, ack 79, win 264, options [nop,nop,TS val 3732285913 ecr 3748674311], length 323: HTTP: HTTP/1.1 301 Moved Permanently
21:05:06.232468 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [F.], seq 324, ack 79, win 264, options [nop,nop,TS val 3732285913 ecr 3748674311], length 0
21:05:06.241466 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [.], ack 80, win 264, options [nop,nop,TS val 3732285922 ecr 3748674320], length 0
pcap-filter의 마지막 부분인 expr1 relop expr2 부분을 읽으면 된다.$ sudo tcpdump -r result.pcap "tcp[tcpflags] & (tcp-syn|tcp-fin) != 0"
reading from file result.pcap, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144
Warning: interface names might be incorrect
21:05:06.223271 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [S.], seq 60975892, ack 997167500, win 65535, options [mss 1360,sackOK,TS val 3732285903 ecr 3748674302,nop,wscale 9], length 0
21:05:06.232468 eth0 In IP 151.101.194.133.http > 172.31.115.194.34840: Flags [F.], seq 324, ack 79, win 264, options [nop,nop,TS val 3732285913 ecr 3748674311], length 0
-v, -vv, -vvv의 3단계로 output의 verbosity를 나타내는 것이 가능하다. 보통 -v 정도만 해도 TTL이나 IP packet에 있는 option, checksum 확인 등의 여러 기능을 사용하는게 가능하다.
-t, -tt, -ttt, -tttt, -ttttt(...) 로 timestamp의 verbosity를 나타내는 것이 가능하다. 기본은 -tttt다. -t는 시간을 출력 안한다.
user, pass, login이라는 정보가 들어있는 경우 비밀번호가 돌아다니고 있다고 볼 수 있다. 이런 경우는 방지해야 하기 때문에 해당 경우가 일단 일어나는지를 밑의 command로 판단, 있는 경우 누가 일으키는지를 추적할 필요가 있다.sudo tcpdump -A -i eth0 "port http or port ftp or port telnet" | grep -i 'user\|pass\|login'
sudo tcpdump "tcp[tcpflags] & (tcp-rst) != 0"