서핑하다가 본 패킷 관련 블로그 글 하나를 소개하고자 한다. 유닉스 환경에 익숙한 사용자 분들이라면
awk, uniq, sed 와 같은 유틸리티들이 얼마나 막강하고 유용한지를 알 것이다. tcpdump 의 출력내용을
이 도구를 이용해 활용하는 방법이다. 원문의 글은 아래 경로에서 볼 수 있고,
필자가 명령어 관점에서 적절히 내용을 요약 소개하도록 하겠다. 일부 명령어는 조금 수정하였다. 이 글은 SANS 의 Incident Handler 인 Guy Bruneau 가 작성한 글이며, 여러분들에게 소개해도 좋다는 승낙을 받았다.
수집된 큰 파일의 PCAP 파일을 분석하려고 하면 시간이 많이 소요될 뿐만 아니라 복잡하기만 하다. 3개의 예제를 소개할 것인데, 한개는 의심스러운 포트를 찾기 위한 것과 출발지 IP 를 찾는 것이다.
참고로 여기서 사용한 IP 는 필자가 가지고 있는 PCAP 파일의 IP 를 랜덤하게 rewrite 한 것이다.
첫번째 예제는 어떤 소스IP 가 목적지 107.251.237.45 번에 80 번 포트로 SYN 패킷을 보냈는지 찾는 것이다.
일단 사용한 명령어를 보면 아래와 같으며, 하나하나 살펴볼 것이다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}' | sort | uniq -c | awk '{print $2 "\t" $1 }'
1) tcpdump 를 사용하면서 -n 은 resolving 을 하지 말라는 것이다. 그리고 -t 옵션은 날짜/시간을 출력하지 않으며, -r 은 fake2.pcap 파일을 읽어들이라는 뜻이다. resolving 이라고 표현한 것은 tcpdump 를 통해서 볼때 IP 주소로 안 나오고 DNS 로 변환되어 나오는 것들을 말하는데, -n 은 IP 로만 출력된다고 보면 된다.
2) 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' 는 필터 문법을 사용한 것으로 tcp[13] = 0x02 는 TCP SYN 패킷을 뜻하고 dst host 107.251.237.46 가 목적지 IP 주소와 dst port 80 은 목적지 포트 80번을 뜻한다. 아래와 같은 결과를 얻을 수 있다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
IP 45.129.53.45.1107 > 107.251.237.46.80: S 2848095605:2848095605(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1109 > 107.251.237.46.80: S 2969874981:2969874981(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1113 > 107.251.237.46.80: S 3283036520:3283036520(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1117 > 107.251.237.46.80: S 1316869520:1316869520(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1118 > 107.251.237.46.80: S 416262863:416262863(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1119 > 107.251.237.46.80: S 1231482360:1231482360(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1120 > 107.251.237.46.80: S 4007769174:4007769174(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1121 > 107.251.237.46.80: S 2037777415:2037777415(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1122 > 107.251.237.46.80: S 2064521910:2064521910(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1125 > 107.251.237.46.80: S 2824615168:2824615168(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1126 > 107.251.237.46.80: S 578435425:578435425(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1127 > 107.251.237.46.80: S 3649101981:3649101981(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1128 > 107.251.237.46.80: S 4156669539:4156669539(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1130 > 107.251.237.46.80: S 2942142219:2942142219(0) win 65535 <mss 1460,nop,nop,sackOK>
IP 45.129.53.45.1131 > 107.251.237.46.80: S 1880140019:1880140019(0) win 65535 <mss 1460,nop,nop,sackOK>
3) 파이프와 awk ( | awk '{print $2}') 를 이용하여 tcpdump 의 결과중 출발지 IP 만 출력하게 한 것이다. 필드 $2 가 출발지 IP 이며, 목적지 주소로 할 경우 $4 로 변경하면 된다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
45.129.53.45.1107
45.129.53.45.1109
45.129.53.45.1113
45.129.53.45.1117
45.129.53.45.1118
45.129.53.45.1119
45.129.53.45.1120
45.129.53.45.1121
45.129.53.45.1122
45.129.53.45.1125
45.129.53.45.1126
45.129.53.45.1127
45.129.53.45.1128
45.129.53.45.1130
45.129.53.45.1131
4) 파이프와 tr (| tr . ' ')를 이용하여 . 을 공백으로 바꾸는 것이다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '
reading from file fake2.pcap, link-type EN10MB (Ethernet)
45 129 53 45 1107
45 129 53 45 1109
45 129 53 45 1113
45 129 53 45 1117
45 129 53 45 1118
45 129 53 45 1119
45 129 53 45 1120
45 129 53 45 1121
45 129 53 45 1122
45 129 53 45 1125
45 129 53 45 1126
45 129 53 45 1127
45 129 53 45 1128
45 129 53 45 1130
45 129 53 45 1131
5) 다시 파이프와 awk (| awk '{print $1"."$2"."$3"."$4}') 를 이용하여 IP 주소 형태로 구성한 것이다. $5는 포트인데 제외시킨 것이다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
6) sort 명령어를 ( | sort) 를 이용하여 트래픽을 IP 로 정렬한다. ** 여기 예에서는 하나의 IP 만 이용되었음을 참고하길 바란다.
0# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}' | sort
reading from file fake2.pcap, link-type EN10MB (Ethernet)
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
45.129.53.45
7) 다음으로 | uniq -c 명령어를 통해 출발지 IP 가 몇번 반복했는지 출력하는 것이다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}' | sort | uniq -c
reading from file fake2.pcap, link-type EN10MB (Ethernet)
15 45.129.53.45
8) 그러면 출발지 IP 45.129.53.45 가 15번 SYN 을 보냈다는 것을 알 수 있다. 다음 명령어인 awk '{print $2 "\t" $1 }' 는 보기 좋게 IP 주소와 카운트 출력을 서로 맞바꾼 것이다.
# tcpdump -ntr fake2.pcap 'dst host 107.251.237.46 and tcp[13] = 0x02 and dst port 80' | awk '{print $2}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}' | sort | uniq -c | awk '{print $2 "\t" $1 }'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
45.129.53.45 15
다른 예제로 사용한 것은 목적지 80 번 포트로 목적지 IP 의 건수를 출력한 것이다. 위 예제와 큰 차이는 없다.
# tcpdump -ntr fake2.pcap 'dst port 80' | awk '{print $4}' | tr . ' '| awk '{print $1"."$2"."$3"."$4}' | sort | uniq -c | awk '{print $2 "\t" $1 }'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
103.215.23.19 119
105.143.221.251 5
105.143.229.47 5
107.211.203.241 20
107.251.105.215 34
107.251.237.46 75
111.157.46.185 653
111.190.92.253 12
111.200.248.236 21
111.212.148.21 40
121.166.117.57 25
121.205.250.221 10
121.205.250.223 24
123.187.14.83 31
123.187.14.89 15
125.167.70.221 15
159.180.121.215 11
189.252.57.215 5
189.252.57.217 5
43.197.190.189 6
45.219.248.116 15
59.185.219.21 5
59.185.219.245 28
59.185.219.57 113
다음은 목적지 포트번호인 $5 를 사용하였는데 출력을 시키고 정렬하면서 , sed 명령어로 제일 끝부부의 출력인 : 를 삭제하여 출력한 것이다.
# tcpdump -n -r fake2.pcap | awk '{print $5}' | tr . ' ' | awk '{print $5}' | sort | uniq -c | sed 's/:$//'
reading from file fake2.pcap, link-type EN10MB (Ethernet)
2
16 1039
3 1040
3 1041
30 1042
10 1043
10 1044
7 1045
6 1046
6 1047
7 1048
9 1049
7 1050
3 1051
3 1052
3 1053
21 1054
42 1055
64 1056
15 1057
10 1058
77 1059
49 1060
22 1061
16 1062
24 1063
22 1064
19 1065
21 1066
간단하게 원문의 예제와 다르게 수정한 것을 소개해 보았는데, 아주 기본적인 형태를 언급한 것이다. awk, sed 와 파이프 문만 잘 사용해도 출력되는 스트링을 자유자재로 편집하여 유용한 수치를 뽑아낼 수 있다. 나 또한 즐겨쓰는 유틸리티 인데, 이 각각의 도구가 책 한권씩 소개되어 있을만큼 문자열을 다루는데 있어서는 최고다.
tcpdump 를 예로 들어 설명했는데 tshark 의 결과를 이용하는데도 유용하다. tshark 는 출력시키고자 하는 내용을 원하는 포맷 형태로 맞추어 출력도 가능하여 효과적으로 사용할 수 도 있는데, 정리가 되는대로 여러분들에게 소개할 것이다.