2013년 12월 27일 금요일

어느덧 패킷인사이드 4주년, 새해 복 많이 받으세요.

패킷인사이드 주인장 입니다. 12월쯤에 제가 블로그를 처음 시작했는데, 미쳐 잊고 있다 찾아보니 12월10일이 오픈일 이었네요. 어느덧 벌써 4년이라는 시간이 흘렀습니다. 2013년은 여느해 보다 개인적으로는 바쁘기도 하면서 어딘가 한 구석이 비워있는 듯한 느낌이었던것 같습니다. 2014년은 저도 다시 재 정비를 하고 더욱 많은 내용을 여러분들과 공유할 수 있도록 하겠습니다. 아직도 소개해 드리고 싶은 내용이 너무나도 많거든요.

이제 얼마 남지 않은 2013년 마무리 잘 하시고요, 2014년에 뵙겠습니다.

새해 복 많이 받으세요 그리고 모두 행복하세요 ^^

/Rigel

2013년 11월 13일 수요일

CaseStudy, FTP 접속 지연 원인 - 10초의 흔적을 찾아라!

오래간만에 쓰는 포스팅인것 같습니다. 이런저런 일들이 많다보니 블로깅도 게을러지고 있네요. :-)

오늘은 CaseStudy 형태로 애플리케이션의 접속 지연에 대해서 실제 사례를 한번 다뤄볼까 합니다. FTP 접속을 언급하려고 하는데, 이전에도 한번 사례로 FTP 를 다룬적이 있습니다. 약간 비슷할 수도 있지만 관점이 조금 다르긴 합니다. 일단 분석하게 된 이유는 이렇습니다.

FTP 를 통해서 특정 시스템에 접속하는데 접속이 바로 이뤄지지 않고 지연이 발생하는 것입니다.

C:\>ftp 192.168.0.1
Connected to 192.168.0.1.

여기서 10 초정도의 지연이 발생하고 다음과 같이 접속이 이뤄집니다.

C:\>ftp 192.168.0.1
Connected to 192.168.0.1.
220 TEST FTP server (Version 6.4/OpenBSD/Linux-ftpd-0.17) ready.
User (192.168.0.1:(none)):

일단 시스템에서 패킷 덤프를 해 보았습니다. 일반적인 3way Handshake 과정이 이뤄지고 있습니다. 클라이언트인 192.168.98.128 이 comm-gw(192.168.0.1) FTP 포트에 SYN 패킷을 보내면서 연결 시도를 합니다.

11:15:31.363275 IP 192.168.98.128.1087 > comm-gw.ftp: S 1725038219:1725038219(0) win 65535 <mss 1460,nop,nop,sackOK>
11:15:31.363305 IP comm-gw.ftp > 192.168.98.128.1087: S 3794060333:3794060333(0) ack 1725038220 win 5840 <mss 1460,nop,nop,sackOK>
11:15:31.363554 IP 192.168.98.128.1087 > comm-gw.ftp: . ack 1 win 65535



11:15:37.309023 IP 192.168.98.128.netbios-dgm > 192.168.255.255.netbios-dgm: NBT UDP PACKET(138)
11:15:42.577429 IP comm-gw.ftp > 192.168.98.128.1087: P 1:72(71) ack 1 win 5840
11:15:42.714480 IP 192.168.98.128.1087 > comm-gw.ftp: . ack 72 win 65464


그런데 ACK 까지 전달이 되고 통신을 하는 과정에서 지연이 보입니다. 11:15:31초 후에 42초 쯤 관련된 트래픽이 나타납니다. 클라이언트 관점에서 봤을때는 연결이 이뤄지고 서버에서 응답이 오기까지 지연이 보이는 것으로 추정됩니다.


일반적으로 이런 지연이 발생되는 원인중에 하나로 Name Lookup 이 있습니다. 그래서 /etc/hosts 파일에 해당 클라이언트 IP 를 넣어주고 패킷 덤프를 다시 해 봅니다.

# tcpdump -i eth4 host 192.168.98.128
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth4, link-type EN10MB (Ethernet), capture size 96 bytes


11:18:11.836148 IP aa-05-01.proofd > comm-gw.ftp: S 3515309442:3515309442(0) win 65535 <mss 1460,nop,nop,sackOK>
11:18:11.836173 IP comm-gw.ftp > aa-05-01.proofd: S 2006125397:2006125397(0) ack 3515309443 win 5840 <mss 1460,nop,nop,sackOK>
11:18:11.836340 IP aa-05-01.proofd > comm-gw.ftp: . ack 1 win 65535
11:18:11.837724 IP comm-gw.ftp > aa-05-01.proofd: P 1:72(71) ack 1 win 5840
11:18:11.955346 IP aa-05-01.proofd > comm-gw.ftp: . ack 72 win 65464
^C


그런데, 앞서 본 것과 달리 속도 지연이 없어졌습니다. 11:18:11 안에 모든 과정들이 끝나버렸습니다. 10초 이상 지연이 발생한 것과는 대조적입니다. 조금 더 자세히 살펴보기 위해 ftp 데몬을 추적해 보기로 했습니다. 다만, ftpd 데몬이 지속적으로 떠 있는 것이 아니라 inetd 데몬에 의해서 접속시 마다 프로세스가 생성되므로 다음과 같이 해 보았습니다.

1초마다 프로세스를 살펴봐서 in.ftp 문자열이 검색되면 해당 프로세스 ID 를 넘겨받아 strace -p PID 로 하는 것입니다.

# while true; do ps -ef | grep in.ftp | grep -v grep | gawk -F' ' '{system("strace -p "$2)}'; sleep 1; done

Process 16864 attached - interrupt to quit
restart_syscall(<... resuming interrupted call ...>) = 1
ioctl(4, FIONREAD, [43])                = 0
recvfrom(4, "\360\275\201\202\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, [16]) = 43
close(4)                                = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 28) = 0
fcntl64(4, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
gettimeofday({1382065750, 265867}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
send(4, "\360\275\1\0\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 43, MSG_NOSIGNAL) = 43
poll([{fd=4, events=POLLIN}], 1, 3000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [43])                = 0
recvfrom(4, "\360\275\201\202\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [16]) = 43
close(4)                                = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, 28) = 0
fcntl64(4, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
gettimeofday({1382065752, 399158}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
send(4, "\360\275\1\0\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 43, MSG_NOSIGNAL) = 43
poll([{fd=4, events=POLLIN}], 1, 6000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [43])                = 0
recvfrom(4, "\360\275\201\202\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, [16]) = 43
close(4)                                = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, 28) = 0
fcntl64(4, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
gettimeofday({1382065753, 199402}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
send(4, "\360\275\1\0\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 43, MSG_NOSIGNAL) = 43
poll([{fd=4, events=POLLIN}], 1, 5000)  = 0 (Timeout)
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, 28) = 0
fcntl64(5, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(5, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
gettimeofday({1382065758, 201686}, NULL) = 0
poll([{fd=5, events=POLLOUT}], 1, 0)    = 1 ([{fd=5, revents=POLLOUT}])
send(5, "\360\275\1\0\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 43, MSG_NOSIGNAL) = 43
poll([{fd=5, events=POLLIN}], 1, 3000)  = 1 ([{fd=5, revents=POLLIN}])
ioctl(5, FIONREAD, [43])                = 0
recvfrom(5, "\360\275\201\202\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("8.8.8.8")}, [16]) = 43
close(4)                                = 0
close(5)                                = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, 28) = 0
fcntl64(4, F_GETFL)                     = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
gettimeofday({1382065758, 888660}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
send(4, "\360\275\1\0\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 43, MSG_NOSIGNAL) = 43
poll([{fd=4, events=POLLIN}], 1, 6000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [43])                = 0
recvfrom(4, "\360\275\201\202\0\1\0\0\0\0\0\0\003128\00298\0015\003111\7in-addr"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("168.126.63.1")}, [16]) = 43
close(4)                                = 0
open("/etc/nologin", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/etc/ftpwelcome", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
uname({sys="Linux", node="TEST", ...}) = 0
stat64("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
stat64("/etc/resolv.conf", {st_mode=S_IFREG|0644, st_size=119, ...}) = 0
open("/etc/hosts", O_RDONLY|O_CLOEXEC)  = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=336, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f4f000
read(4, "127.0.0.1\tlocalhost\n127.0.1.1\tTES"..., 4096) = 336
read(4, ""..., 4096)                    = 0
close(4)                                = 0
munmap(0xb7f4f000, 4096)                = 0
fstat64(1, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f4f000
write(1, "220 TEST FTP server (Version"..., 71) = 71
rt_sigaction(SIGALRM, {0x804ef40, [ALRM], SA_RESTART}, {SIG_DFL}, 8) = 0
alarm(900)                              = 0
fstat64(0, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f4e000
read(0, ^C <unfinished ...>
Process 16864 detached
Process 16864 attached - interrupt to quit
read(0, ^C <unfinished ...>
Process 16864 detached
Process 16864 attached - interrupt to quit
read(0, quit
^\ <unfinished ...>
Process 16864 detached

Process 16864 attached - interrupt to quit
read(0, ^C <unfinished ...>
Process 16864 detached
Process 16864 attached - interrupt to quit
read(0,
^C <unfinished ...>
Process 16864 detached
^\Quit
Process 16864 attached - interrupt to quit
read(0, ^Z


여기서는 실제로 보여주는 것이 한계가 있지만, strace 로 해서 보면 name lookup 하는 부분에서 딜레이가 발생하는 것이 보입니다. 즉, 이런 형태를 검증해 보는 하나의 방법으로 보시면 될것 같습니다. 하지만, 여기에 문제가 있습니다. 접속하는 클라이언트가 수백대가 넘게 있습니다. 그 IP 들을 일일이 넣어주기도 쉽지가 않습니다. 분명히 또 다른 방법이 있을것입니다. 'man in.ftpd' 를 통해서 세부적인 옵션을 확인해 보았더니 -n 이라는 것이 있습니다.

 -n      Use numeric IP addresses in logs instead of doing hostname lookup.

ftpd 데몬을 많이 써보았지만 굳이 옵션을 찾아볼 일이 없었는데 -n 이 호스트이름 대신 IP 주소로 사용하여 로그를 기록하게 되어 있네요. 자 그래서 -n 옵션을 사용해 반영했더니, 동일하게 모든 클라이언트에서 접속해도 빠른 속도로 접속이 이뤄집니다.

/etc/hosts 파일에 개별적으로 사용할 수도 있지만 좀더 광범위하고 효율적인 작업면에서는 -n 옵션이 더욱 적절했던 것입니다.

패킷덤프를 통해서 패킷의 흐름을 살펴보고, 서버에서의 응답에 지연이 있는 것으로 판단되어 서버단에서 문제를 찾아들어가며 해결한 경우입니다. 문제가 발생할 경우 해결하기 위한 방법에는 메뉴얼 처럼 딱 정해진것이 없습니다. 기본 해결 방법은 같을 수 있지만 그것을 찾아들어가기 위한 것은 다양합니다. 이것또한 그 중에 하나입니다.

어떤이는 접속이 되니까 그냥 그대로 사용할 수도 있고 또 다른 사람은 왜 지연이 있을까 하고 의문을 갖게 됩니다. 물론 이런 지연이 영향을 미칠만큼이냐 또는 아니냐에 따라서 판단은 달라지게 됩니다. 하지만 이런것에 Question 을 가지고 계속 질문해 보면 그 답을 찾는 과정에서 많은 것을 얻고 배우게 됩니다. 바로 이런것이 Experience 입니다. 저 또한 블로그를 하는 이유가 이러한 경험을 여러분들과 함께 공유하기 위함입니다.

자, 그럼 오늘은 여기까지 하고 마무리 짓겠습니다.

문제가 발생했을때 실마리를 어떻게 풀어나갈것인지 참고가 되었으면 좋겠습니다.

/Rigel

2013년 10월 23일 수요일

구글에서 제공하는 무료 DDoS 방어 서비스, 프로젝트 쉴드(Project Shield)

구글에서 최근 프로젝트 쉴드라는 것을 발표했습니다. 구글의 인프라스트럭처를 이용해 분산서비스거부 공격(DDoS)을 막을 수 있는 서비스 입니다. 서비스 받고 있는 호스팅을 이동한다든지의 작업 없이 구글의 서비스를 통해 DDoS 를 완하시키겠다는 것입니다.

현재 이 서비스는 무료로 이용할 수 있으나, 초대된 웹 사이트만 이용이 가능합니다. 지원을 하게 되면 구글이 말하는 'Trusted Tester' 로 선정되고 사용하게 됩니다. 가입을 하고 선정되면 설정할 수 있는 정보를 이메일을 통해 전달받는것 같습니다.

아마도 이 서비스는 DNS 설정을 통해 구글쪽으로 변경하고 거기서 구글의 인프라를 통해 DDoS 와 같은 이벤트가 급격하게 증가시 보호 역할을 하게 되는것으로 보입니다. 다른 외부에서 제공하는 DDoS 차단 서비스를 유사하게 무료로 제공하는 것으로 중.소기업의 웹 사이트들이 이용하기에 괜챦아 보입니다. DDoS 공격을 받고 있는 사이트가 있다면 지금 한번 신청해 보세요.

[참고]
1. 프로젝트 쉴드
http://projectshield.withgoogle.com/
2. 구글 아이디어 프로젝트
http://www.google.com/ideas/projects/

2013년 10월 16일 수요일

SQL 쿼리로 패킷 데이터를 조회한다고 ?

패킷데이터를 SQL 쿼리문 형태로 출력할 수 있는 PacketQ 에 대해서 소개해 볼까합니다. 패킷데이터를 간단하고 빠르게 출력해 낼 수 있는 도구입니다. 원래 이 도구가 DNS2db 라는 이름으로 사용되다가 2011년에 이름을 PacketQ 로 변경했습니다. 변경한 이유는 원래의 이름에서 알 수 있듯이 주로 DNS 데이터 중심으로 데이터를 뽑아냈었는데, 다른 프로토콜 까지 확장해 SQL 쿼리문으로 뽑아내고자 하였기 때문입니다. 하지만 아직까지는 자유롭게 처리할 수 있는 것이 DNS 데이터쪽으로 맞춰져 있습니다. 그러므로 DNS 에 한해 쉽게 데이터를 뽑아내고자 하시는 분들한테는 유용할 수 있습니다. DNS 관리자 분들에게는 더욱 유용할수도 있겠습니다.

일단 다운로드 및 세부 정보는 다음 경로에서 확인할 수 있습니다:

https://github.com/dotse/packetq

주요한 기능을 보면 PCAP 파일을 빠르게 파싱할 수 있다는 것을 강점으로 내세우고 있고요 SQL 쿼리문 형태로 사용이 가능합니다. SQL 에 익숙하신 분에게는 더없이 좋겠죠. XML, CSV, JSON, Table 형태로도 데이터를 출력시킬 수 있습니다. 아직은 DNS 와 ICMP 프로토콜 정도만 지원하고 있다는 점입니다. 그리고 PacketQ 가 SQL 쿼리문 형태로 사용할 수 있다고 하지만 완벽한 SQL 문 형태로 지원하는 것은 아닙니다. 조인, 서브쿼리, distinct, like 같은것은 사용할 수 없습니다. 사용가능한 문법은 다음 페이지를 참고해 보시면 됩니다.

https://github.com/dotse/PacketQ/blob/master/src/grammar

간단한 사용방법을 몇개 살펴보겠습니다. SQL 쿼리 같이 * 로 해서 전체 데이터를 다 출력할 수도 있지만 특정필드로도 제한할 수 있습니다. 일단, DNS 데이터에서 추출해 낼 수 있는 데이터 형태는 다음과 같습니다.

      { "name": "id","type": "int" },
      { "name": "s","type": "int" },
      { "name": "us","type": "int" },
      { "name": "ether_type","type": "int" },
      { "name": "src_port","type": "int" },
      { "name": "dst_port","type": "int" },
      { "name": "src_addr","type": "text" },
      { "name": "dst_addr","type": "text" },
      { "name": "protocol","type": "int" },
      { "name": "ip_ttl","type": "int" },
      { "name": "fragments","type": "int" },
      { "name": "qname","type": "text" },
      { "name": "aname","type": "text" },
      { "name": "msg_id","type": "int" },
      { "name": "msg_size","type": "int" },
      { "name": "opcode","type": "int" },
      { "name": "rcode","type": "int" },
      { "name": "extended_rcode","type": "int" },
      { "name": "edns_version","type": "int" },
      { "name": "z","type": "int" },
      { "name": "udp_size","type": "int" },
      { "name": "qd_count","type": "int" },
      { "name": "an_count","type": "int" },
      { "name": "ns_count","type": "int" },
      { "name": "ar_count","type": "int" },
      { "name": "qtype","type": "int" },
      { "name": "qclass","type": "int" },
      { "name": "atype","type": "int" },
      { "name": "aclass","type": "int" },
      { "name": "attl","type": "int" },
      { "name": "aa","type": "bool" },
      { "name": "tc","type": "bool" },
      { "name": "rd","type": "bool" },
      { "name": "cd","type": "bool" },
      { "name": "ra","type": "bool" },
      { "name": "ad","type": "bool" },
      { "name": "do","type": "bool" },
      { "name": "edns0","type": "bool" },
      { "name": "qr","type": "bool" }

이중에서 qtype 과 opcode 를 출력하고 총 3개의 데이터로 제한을 한다면 다음과 같이 쿼리가 만들어질 수 있습니다. -s 뒤에 사용할 쿼리를 넣어주면 됩니다.

# ./packetq -s "select qname,opcode from dns limit 3" test.pcap
[
  {
    "table_name": "result-0",
    "query": "select qname,opcode from dns limit 3",
    "head": [
      { "name": "qname","type": "text" },
      { "name": "opcode","type": "int" }
    ],
    "data": [
      ["n.search.naver.com.",0],
      ["n.search.naver.com.",0],
      ["n.search.naver.com.",0]
    ]
  }
]


어떤 출발지에서 가장 많은 DNS 쿼리 요청을 했는지 출력해 봅니다.

# ./packetq -s "select src_addr,count(*) as count from dns group by src_addr order by count desc limit 1" sample.pcap
[
size = 2
  {
    "table_name": "result-0",
    "query": "select src_addr,count(*) as count from dns group by src_addr order by count desc limit 1",
    "head": [
      { "name": "src_addr","type": "text" },
      { "name": "count","type": "int" }
    ],
    "data": [
      ["172.xx.xx.52",4]
    ]
  }
]


만약 가장 많은 쿼리가 요청된 것을 뽑아낸다면 다음과 같이 합니다. qname 으로 groupby 를 해 줍니다. SQL 에 익숙하신 분들이라면 쿼리만 보고서도 쉽게 이해가 되실 것입니다. 하지만 SQL 경험이 없으신 분들은 group by 가 무엇인지도 혼란스러울 수도 있습니다. 여기서는 SQL 쿼리문 까지는 다루기 힘들기 때문에 의미만을 설명드리겠습니다. qname 으로 그룹을 만들어 주고 각 qname 마다의 카운트를 생성합니다. 그리고 정렬을 count 로 해서 가장 많은 숫자가 처음에 나오게 하고 limit 를 통해 출력데이터를 1개로만 합니다. 그 결과가 아래와 같습니다 :

# ./packetq -s "select qname,count(*) as count from dns group by qname order by count desc limit 1 " test.pcap
[
size = 1513
  {
    "table_name": "result-0",
    "query": "select qname,count(*) as count from dns group by qname order by count desc limit 1 ",
    "head": [
      { "name": "qname","type": "text" },
      { "name": "count","type": "int" }
    ],
    "data": [
      ["resolver3.xxxx[삭제].com.",238]
    ]
  }
]

이번에는 쿼리타입을 출력해 볼까요? 쿼리타입이 기본적으로는 정수 값입니다. 그런데 정수값으로 보면 사람한테는 익숙하지 않습니다. 이때 NAME 펑션 기능을 이용해 쿼리타입(qtype)을 텍스트 형태로 출력시킬 수 있습니다. qtype 으로 그룹을 묶고 타입과, 카운트 정보를 뽑아서 가장 많은 순서대로 출력을 시킵니다.

# ./packetq -s "SELECT NAME( 'qtype' , qtype ) AS qt, COUNT(*) AS antal FROM dns GROUP BY qtype ORDER BY Antal DESC" test.pcap
[
size = 10
  {
    "table_name": "result-0",
    "query": "SELECT NAME( 'qtype' , qtype ) AS qt, COUNT(*) AS antal FROM dns GROUP BY qtype ORDER BY Antal DESC",
    "head": [
      { "name": "qt","type": "text" },
      { "name": "antal","type": "int" }
    ],
    "data": [
      ["A",8626],
      ["AAAA",680],
      ["PTR",566],
      ["TXT",202],
      ["SRV",113],
      ["MX",16],
      ["SOA",8],
      ["0",8],
      ["*",8],
      ["NS",8]
    ]
  }
]

패킷 데이터를 SQL 쿼리문으로 추출해 낼 수 있다는 점에서 굉장히 유용한 부분이 있습니다. 아쉬운 점은 일부 프로토콜로만 한정되어 사용할 수 없지만 광범위하게 프로토콜을 지원한다면 정말 편할거 같은 느낌입니다. 예전에 DNS 프로토콜을 파싱하여 활용할 일이 있어서 찾다가 보게되었는데 나름 유용하게도 이용할 수 있겠다는 생각이 들었습니다.

SQL 쿼리로 패킷데이터를 조회한다는 점, 흥미롭지 않나요.  더 많은 예제는 해당 홈페이지 위키 페이지를 참고하시면 됩니다.

P.S 참고로 ICMP 로 출력할 수 있는 데이터는 다음과 같습니다:

      { "name": "id","type": "int" },
      { "name": "s","type": "int" },
      { "name": "us","type": "int" },
      { "name": "ether_type","type": "int" },
      { "name": "src_port","type": "int" },
      { "name": "dst_port","type": "int" },
      { "name": "src_addr","type": "text" },
      { "name": "dst_addr","type": "text" },
      { "name": "protocol","type": "int" },
      { "name": "ip_ttl","type": "int" },
      { "name": "fragments","type": "int" },
      { "name": "type","type": "int" },
      { "name": "code","type": "int" },
      { "name": "echo_identifier","type": "int" },
      { "name": "echo_sequence","type": "int" },
      { "name": "du_protocol","type": "int" },
      { "name": "du_src_addr","type": "text" },
      { "name": "du_dst_addr","type": "text" },
      { "name": "desc","type": "text" }

아래와 같은 형태로 사용하면 되겠죠. 
./packetq -s "select * from icmp limit 3" 

2013년 9월 27일 금요일

마이크로소프트 Message Analyzer 공식 릴리즈

마이크로소프트사의 Message Analyzer 가 그동안 베타로 테스트 되다가 드디어 공식적으로 다운로드센터에 등록되었습니다. 이제는 로그인 필요없이 편하게 바로 다운로드 받아 사용하실 수가 있습니다. Message Analyzer 는 새로운 형태의 메시지 분석기로서 트래픽 뿐만 아니라 시스템 메시지 또한 분석 대상입니다. 로그파일이나 Trace 파일을 분석을 할 수 있다는 의미입니다.

과거 Network Monitor 는 네트워크 트래픽 분석기로서의 역할만을 담당하지만 Message Analyzer 는 트래픽외 통합적으로 이벤트도 분석할수 있다는 부분이 다릅니다. 베타때부터 써보긴 했지만 와이어샤크만큼 사용 방법이 직관적이지는 않은것 같습니다.

그래도 새로운 분석기가 하나 더 생겼다는 것은 좋은일입니다. Message Analyzer 만의 장점이 있을테니 말이죠. 다운로드는 다음의 경로에서 할 수 있습니다.

http://www.microsoft.com/en-us/download/details.aspx?id=40308

앞으로 Message Analyzer 에 대한 기능도 소개해 보도록 하겠습니다.



[참고]
1. MS사의 새로운 네트워크 분석기, Message Analyzer
2. 마이크로소프트 네트워크 모니터의 프로세스별 통신 상태

2013년 9월 25일 수요일

차세대 패킷 포맷, Pcap-NG 를 알고싶다 _ 네번째 이야기

추석명절은 잘 보내셨는지요? 오늘은 드디어 Pcap-NG 포맷 소개의 마지막 글입니다. 여러가지 바쁜일들로 이제서야 마지막 편을 쓰게 되었습니다.

6. PCAP-NG 쉽게 들여다 보기


패킷파일을 쉽게 살펴볼 수 있는 것은 도구를 이용하는 방법입니다. 그 중에 대표적인 패킷 분석도구인 와이어샤크를 통해서 쉽게 차세대 패킷 포맷을 살펴볼 수 있습니다.

6-1. 와이어샤크를 통해 본 PCAP


와이어샤크에서는 Pcap-NG 포맷을 지원하고 있습니다. 아직 완벽하게 해당 포맷을 100% 다 지원하지는 않지만 기본적인 사용에는 큰 문제가 없습니다. 와이어샤크의 제약을 보면

- 일부(SHB, IDB, PB, EPB, SPB) 블럭만 지원하고 있어 다른 블럭은 무시가 됩니다.
- 많은 옵션들이 완벽하게 구현되지 않았습니다.
- 싱글 세션만 지원합니다.
- 많은 파일에 대해서 생성 테스트가 더 되어야 하고 파일을 합치는 기능에서는 약간의 제약이 있습니다.

일단 기본적으로 패킷 정보를 보여주는 형태는 이전의 PCAP 과 같습니다. 다만 GUI 관점에서 추가적인 메뉴가 더 생겼는데, Statistics 에서 Address Resolution 과 Comments Summary 를 더 볼 수 있습니다.

Address Resolution 은 PCAP-NG 에서 제공하는 NRB 블럭에서 기록된 정보와 유사한 정보를 제공해 줍니다. 패킷 내에서 사용된 도메인 정보를 한눈에 쉽게 볼 수 있도록 보여주고 있습니다. 이 것은 NRB 와는 별개로 와이어샤크에서 제공해 주는 기능입니다.


다음은 Comments Summary 로 주석 정보와 캡쳐가 된 운영체제 정보및 이더넷 정보를 추가적으로 확인할 수 있습니다. 아래 그림의 하단을 보면 주석정보를 볼 수가 있는데요, 주석정보는 PCAP-NG 에서 기록되는 정보중에 하나 입니다. 이 정보를 통해 분석가는 단순한 패킷 정보외에 패킷덤프가 이뤄진 곳의 환경정보와 기타 정보를 추가적으로 얻을 수 있어 분석에 참고할 수 있습니다. 또한 주석정보는 여러 분석가가 의견을 교환하고 분석을 계속 이어갈 수 있게 해주는 다리 역할을 해주기도 합니다.


다시말하지만, 분석은 패킷 자체의 정보만으로도 이용될 수 있지만 그렇지 않은 경우도 많습니다. 이럴 경우에는 전반적인 정보를 가지고 문제를 풀어나가야 합니다.


6-2. Pcap-NG 파일 리더


PcapNG 파일을 간단하게 파싱하여 정보를 출력해 줄 수 있는 코드가 있습니다. ntartest 라는 것으로 다음의 경로에서 다운로드 받을 수 있습니다.

http://wiki.wireshark.org/Development/PcapNg?action=AttachFile&do=view&target=ntartest.c

NTAR(Network Trace Archival and Retrieval)은 Pcap-NG 이전에 사용되어 오던 이름의 형태이며 블럭별로 간단한 정보를 출력해 주므로 해당 포맷을 파싱하려는 개발자 분들에게 초기 접근시 도움을 줄 수 있습니다. 일단 소스코드가 짧으니까요 :-)

실행하면 다음과 같은 결과를 얻을 수 있습니다.

# ./ntartest test.pcapng
+++Working on file: test.pcapng
This machine is little-endian.
This section is little-endian.

00000000: Block #1, Type = Section Header Block (0a0d0d0a)
+++ blockLength % 4 = 0, no pad bytes
00000004: Reported Block Length 96 (00000060), Adjusted Block Length 96 (00000060), next block at offset 00000060
00000008: Remainder of Block Data (00000058) bytes

0000005c: Block #2, Type = Interface Description Block (00000001)
+++ blockLength % 4 = 0, no pad bytes
00000060: Reported Block Length 56 (00000038), Adjusted Block Length 56 (00000038), next block at offset 00000094
00000064: Remainder of Block Data (00000030) bytes

00000094: Block #3, Type = Name Resolution Block (00000004)
+++ blockLength % 4 = 0, no pad bytes
00000098: Reported Block Length 5240 (00001478), Adjusted Block Length 5240 (00001478), next block at offset 0000150c
0000009c: Remainder of Block Data (00001470) bytes
Oops: short read, should have read 5232 bytes, only read 4096.

6-3. Pcap-NG 파일 RAW 로 들여다 보기


패킷 포맷 구조가 달라졌지만 사용자가 느끼는 부분에서는 큰 차이가 없을수도 있습니다. 똑같이 패킷 정보를 보여주기 때문이죠. 다만, 패킷 포맷 자체가 이전보다 유연해 졌고 보다 많은 정보를 저장하고 있다는 점에서는 분명 다릅니다. 포맷 자체 관점에서 들여다 보면 이전과는 큰 차이가 있다는 것을 느낄 수 있습니다.

단언컨대, Pcap-NG 는 패킷파일을 저장하는데 유연하면서도 앞으로 많이 쓰이게 될 패킷 포맷중에 하나입니다 :-)

여기에 소개하기 위하여 테스트로 와이어샤크에서 데이터를 pcap-ng 포맷으로 저장해 보았습니다. 패킷파일 포맷 구조를 살펴보면 다음과 같이 구성되어 있습니다.



제일 처음 SHB 가 시작되고 IDB,NRB 가 이어지고 EPB 에 패킷 데이터가 계속 기록되면서 마지막에 ISB 가 존재합니다. 해당 패킷 로우파일을 직접 들여다 보겠습니다.

다음 그림은 xxd 를 이용해 바이너리 형태를 본 것입니다. 제일 처음 SHB 가 시작되고 6000 0000 이라는 블럭 길이가 보입니다. 기본적으로 각 블럭마다 블럭의 길이가 타입 다음에 위치하고 블럭의 마지막에 다시 나타나게 됩니다. 그러므로 블럭타입을 보고 그 다음 길이를 본 후 해당 값과 매치되는 곳 까지 따라가게 되면 일반적으로 쉽게 블럭을 구분할 수 있습니다. 각 바이너리 값들은 우측에 추가적으로 기술해 놓았습니다.



각 포맷은 앞서 소개해 드린 포맷 구조에 맞춰서 보시면 쉽게 이해하실수가 있습니다. SHB 가 시작되고 IDB 가 이어지고 NRB 가 다시 나타납니다. NRB 는 블럭크기가 꽤 큽니다. 그래서 많은 내용이 반복되고 아래 그림과 같이 NRB 종료지점을 볼 수 있습니다. 종료지점은 쉽게 찾을 수 있겠죠? 새로 시작되는 블럭의 앞에 앞서 NRB 의 블럭길이인 7814 0000 을 찾으면 쉽게 찾을 수 있습니다. EPB 는 PCAP 구조와 같이 패킷 데이터를 저장하는 블럭입니다. 가장 많은 블럭의 분포를 보이게 되겠죠? EPB 의 블럭타입은 0600 0000 입니다. 그리고 크기는 6c00 0000 입니다. 다시 끝나는 위치는 6c00 0000 의 다음을 보면 0600 0000 으로 다시 EPB 가 시작이 됩니다. 그럼 첫 EPB 의 데이터는 무엇일까요? 잘 살펴보면 이더넷 타입을 가르키는 0800 과 IPv4 와 IP 헤더길이인 20 바이트를 뜻하는 4500 을 볼 수 있습니다. 직접 각 내용을 하나하나 뜯어보면 DNS 프로토콜임을 알 수가 있답니다. 계속 이어지는 것은 여러분의 몫으로 맡기겠습니다. 


다음 화면은 패킷파일의 제일 끝 부분입니다. EPB 가 시작된 이후로는 패킷데이터인 EPB 블럭이 계속 이어지다가 마지막에 인터페이스 상태정보인 ISB 가 나오게 됩니다. 블럭타입의 시작은 0500 0000 이 보이실 것이고요 6c00 0000 의 블럭크기값이 보입니다. 이후 옵션 헤더에 0100 으로 주석임을 알려주고 옵션길이인 1c00 만큼 (28 바이트) 의 주석 정보가 나오게 됩니다. dumpcap 에 의해서 카운트 정보가 제공되었다는 것입니다. 옵션 헤더는 추가적으로 다양하게 나타날 수 있습니다.


패킷 포맷을 직접 들여다 보면 어렵지는 않습니다. 이해가 쉽도록 보이는 내용 HEX 값 그대로를 표시해 놓았으니 비교해 보시고 블럭 포맷을 이해하시면 됩니다.

7. 마지막


4회에 걸쳐서 Pcap-NG 포맷을 소개해 드렸습니다. 아직은 해당 포맷이 완벽하게 정립되지는 않았고 실험적으로 사용하는 블럭도 존재합니다. 하지만 와이어샤크에서는 이제 기본 패킷파일 저장 포맷으로 Pcap-NG 를 사용하고 있기 때문에 앞으로 이 포맷형태로 파일을 받아보는 경우가 많아질 것입니다.

실제 직접 패킷 포맷을 살펴볼 일은 많지 않습니다. 일일이 살펴보는 것도 쉽지 않고, 전문 분석도구들이 알아서 보기쉽게 표현해 주기 때문입니다. 하지만, 포맷 구조는 이렇게 만들어져 있다는 정도는 가볍게 봐 두시면 좋겠습니다. 아주 가끔은 패킷파일을 직접 복원해야 하는 경우가 생길수도 있고, 빠른 분석을 위해 여러분들이 직접 패킷파일을 분석하는 프로그램을 만들어야 하는 경우가 있을지도 모르거든요.

다음번에 여유가 된다면 PCAP 과 PCAP-NG 를 더 보기 쉽게 문서로도 만들어 보도록 하겠습니다. 아~ 그럴 날이 오겠죠 ? ^^

[참고]
1. 와이어샤크 PcapNg 개발현황
http://wiki.wireshark.org/Development/PcapNg

2013년 9월 3일 화요일

차세대 패킷 포맷, Pcap-NG 를 알고싶다 _ 세번째 이야기

두번째 이야기에서 다루지 못한 2개의 블럭에 대한 설명입니다. Pcap-NG 를 설명하는데 생각보다 많은 시간이 필요하다 보니 먼저 작성한 내용을 공개하면서 어느덧 세번째 이야기 까지 왔습니다. 앞으로 네번째 이야기까지 다루면 Pcap-NG 소개는 끝입니다. :-)

5-5. NRB(Name Resolution Block)


이 블럭은 패킷 캡쳐를 하는 순간의 IP 주소와 연관된 도메인 이름을 지원해주는 역할을 합니다. 패킷캡쳐 파일안에 DNS Resolving 과 관련한 데이터들이 파일의 시작부분쯤에 위치하고 하고 있으며, Resolving 이 많은 경우 해당 블럭의 크기도 커지게 됩니다. 이 블럭의 장점은 Resolving 을 하면서 발생될 수 있는 Delay 를 줄여주며 캡쳐한 시점의 Resolving 정보를 가지고 있다는 것입니다. 예를들어, 캡쳐할 당시의 aaa.com 의 주소가 1.1.1.1 이었는데 분석할 당시에는 2.2.2.2 가 되어 있을수도 있습니다. 이런점에서 보면 유용하게 사용될 수 있는 부분이 있고, DNS 요청이 패킷파일에 많이 담겨있는 경우 Resolving 을 피할수도 있어 네트워크가 연결되어 있지 않더라도 정보를 얻을 수 있게됩니다.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                    Block Type = 0x00000004                    |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |      Record Type              |         Record Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 /                       Record Value                            /
   /          /* variable length, aligned to 32 bits */            /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   .                                                               .
   .                  . . . other records . . .                    .
   .                                                               .
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Record Type == end_of_recs   |  Record Length == 00          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+


블럭은 위와 같은 포맷으로 구성되어 있으며 블럭타입은 0x00000004 로 정의되어 있습니다. 블럭 타입 다음에 블럭에 대한 전체 길이가 나오고 각 레코드 정보가 나오게 되는데 레코드 타입은 아래와 같습니다.

레코드 타입 이름코드번호설명
nres_endofrecord0Name Resolution Record 가 끝남을 알려준다.
nres_ip4record1IPv4 주소에 해당하는 DNS 레코드 정보
nres_ip6record2IPv6 주소에 해당하는 DNS 레코드 정보

각 레코드 값은 32비트로 구성되어 있으며 레코드 길이에 해당 도메인 이름의 실제 길이가 들어가게 됩니다. 마지막으로 옵션이 추가적으로 올 수 있는데, 옵션은 다음과 같습니다.

옵션 이름코드번호설명
ns_dnsname2이름 변환에 사용된 DNS 서버 이름 (UTF-8문자열)
ns_dnsIP4addr3DNS 서버의 IPv4 주소
ns_dnsIP6addr4DNS 서버의 IPv6 주소


5-6. ISB(Interface Statistics Block)


캡쳐에 사용된 인터페이스의 통계정보를 가지고 있습니다. 통계정보라 함은 인터페이스를 통해 받은 패킷 개수, 유실된 패킷개수등이 있습니다. 해당 블록에 정의된 Interface ID 값에 해당하는 인터페이스 정보를 기록하고, 통계정보를 담아야 하기에 보통 파일의 끝부분에 위치하게 되는 블럭입니다. 하지만, 같은 인터페이스에 여러번 반복되어 해당 블럭이 나타날수는 있습니다.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                   Block Type = 0x00000005                     |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |                         Interface ID                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 |                        Timestamp (High)                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 |                        Timestamp (Low)                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+


블럭타입은 0x00000005 를 사용하고 있고, 바로 다음 블럭의 전체길이가 나타납니다.그리고 통계정보를 담을 인터페이스 ID 번호가 위치합니다. 이 ID 는 IDB(Interface Description Block)에서 정의된 인터페이스중에 하나가 됩니다. 그 다음으로 EPB(Enhanced Packet Block)와 같은 타임스탬프가 정보가 나오며, 옵션에는 아래와 같은 정보가 들어가게 됩니다.


옵션 이름코드번호설명
isb_starttime2캡쳐가 시작된 시간으로, 4바이트 2개 블럭으로 시간이 저장된다.
isb_endtime3캡쳐가 끝난 시간으로, 4바이트 2개 블럭으로 시간이 저장된다.
isb_ifrecv4패킷 캡쳐가 시작된 이후로 물리적 인터페이스에서 받은 패킷 개수
isb_ifdrop5패킷 캡쳐가 시작된 이후로 컴퓨터 자원의 부족으로 유실된 패킷 개수
isb_filteraccept6패킷 캡쳐가 시작된 이후로 필터에 의해서 받은 패킷 개수
isb_osdrop7패킷 캡쳐가 시작된 이후로 운영체제에 의해서 유실된 패킷 개수
isb_usrdeliv8패킷 캡쳐가 시작된 이후로 사용자에게 전달된 패킷 개수



2013년 8월 21일 수요일

차세대 패킷 포맷, Pcap-NG 를 알고싶다 _ 두번째 이야기

Pcap-NG 의 두 번째 이야기 입니다. 첫번째 이야기를 쓰고 두 번째 이야기를 쓰기까지 시간이 많이 걸렸네요.  PCAP 포맷보다 더욱 커져서 소개해야 될 내용들이 많고 하다보니 길어지고 있습니다. 대부분의 내용은 PCAPNG 파일 포맷에서 소개하고 있는 내용을 나름대로 정리하여 본 것입니다. 몇 가지 더 적을 내용들이 있는데, 두 번째 이야기에서는 여기까지만 소개하고 나머지 계속 이어서 하겠습니다 :-)

참고로 파일의 기본 확장자는 .pcapng 를 사용합니다.

1. PCAPNG 기본 블럭 구조


캡쳐파일은 여러개의 블럭으로 이뤄지는데, 기본적으로 사용되는 골격 형태는 다음과 같은 포맷을 가지고 있습니다.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Block Type                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Block Total Length                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                          Block Body                           /
/          /* variable length, aligned to 32 bits */            /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Block Total Length                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

32비트의 블럭 타입이 있습니다. 이 블록 타입은 이미 사전정의되어 있으며, 뒤에서 차차 언급하도록 하겠습니다. 그리고 블럭의 전체길이, 블럭 몸체, 블럭의 전체길이가 다시 이어집니다. 특이한 것은 뒷 부분에 다시 블럭의 전체길이가 나오는데, 이것은 패킷 구조내에서 이동에 참고하기 위해서 중복되어 기록되는 내용입니다.

블럭은 해당 패킷파일을 다루는 프로그램에 따라 사용될 수도 있고 안될 수도 있습니다. 어떤 블럭은 반드시 포함되어야 하는 블럭이 있는 반면 어떤 블럭은 옵션에 따라 선택 되는 것이므로 프로그램에서도 해당 블럭을 처리할 것인지는 옵션일 뿐입니다.

2. 블럭 타입 소개


블럭 타입은 아래 [블럭 타입 정보] 에 기술되어 있으며, 각 패킷파일에는 항상 2개의 블럭이 존재해야 합니다.
  • Section Header Block
  • Interface Description Block 

그리고 옵션 블럭으로 가능한 것은
  • Enhanced Packet Block
  • Simple Packet Block
  • Name Resolution Block 
  • Interface Statistics Block 

입니다. 이외 실험적으로 사용되고 있는 블럭은 다음과 같습니다.
  • Alternative Packet Blocks
  • Compression Block
  • Encryption Block
  • Fixed Length Block
  • Directory Block
  • Traffic Statistics and Monitoring Blocks
  • Event/Security Blocks

실험적으로 사용되는 블럭에 대해서는 언급하지 않도록 하겠습니다.

3. 패킷 파일헤더 레이아웃


파일은 처음 SHB(Section Header Block) 부터 시작되어야 합니다. 차세대패킷 포맷은 여러개의 블럭 형태로 이루어져 있기 때문에 해당 블록의 시작을 대표할 수 있는 SHB 가 필요한 것입니다. 블럭 단위로 헤더를 인식하기 위해서 각 헤더는 헤더 초반에 블럭의 타입과 길이에 대한 정보를 반드시 가지고 있어야 합니다. 이후 설명드리는 각 블럭 정보를 보면 아시겠지만 모두 타입과 길이 정보를 가지고 있습니다.

블럭 단위로 패킷 파일이 만들어지기 때문에 기존 패킷파일보다 좀더 유연한 구성이 가능해 집니다. 블럭 단위로 만들어지는 패킷 파일의 다양한 레이아웃을 다음과 같이 살펴보겠습니다.


위와 같이 여러개의 블럭의 조합으로 다양한 레이아웃 형태로 패킷파일을 구성할 수 있습니다.

4. 옵션(Option)


모든 블럭은 옵션 필드를 포함할 수 있습니다. 옵션 필드는 말그대로 선택될 수 있는 정보로 패킷 처리에 있어서 반드시 필요한 정보가 아닙니다. 옵션의 이름대로 데이터를 읽었을때 좀더 유용한 정보를 제공해 줄 수 있는 부가정보라고 볼 수 있습니다. 이런 정보는 구현할 때 해당 정보를 읽을 수도 있고 그렇지 않을수도 있습니다. 즉, 구현하는 소프트웨어에 따라 정보가 있음에도 불구하고 출력해주지 않을수 있는 것입니다. 옵션 필드는 크게 3 가지로 이루어져 있습니다. 타입, 크기 그리고 해당 옵션의 값입니다.

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|      Option Code              |         Option Length         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                       Option Value                            /
/          /* variable length, aligned to 32 bits */            /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/                                                               /
/                 . . . other options . . .                     /
/                                                               /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Option Code == opt_endofopt  |  Option Length == 0          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


- 옵션 타입 (2바이트) : 각 블럭에서 사용되는 2바이트 코드 값
- 옵션 길이 (2바이트) : 실제 옵션 값의 길이
- 옵션 값 (유동적) : 옵션의 실제 값이 들어가 있는 필드

옵션은 여러번 반복이 될 수도 있습니다. 예를들어 인터페이스가 여러개의 IP 를 가지고 구성되어 있는 경우 해당 정보를 기록하려면 반복이 될수 있습니다. 옵션 정보가 끝났다는 것은 마지막에 opt_endofopt 코드 정보를 참고합니다. 해당 코드가 있다면 더 이상 옵션 정보를 참고하지 않습니다. 참고로, 패킷 코멘트 정보가 바로 여기에 기록됩니다.

옵션 이름코드번호설명
opt_endofopt0옵션 필드가 끝났다는 것을 알려주는 것
opt_comment1해당 블럭의 코멘트 정보 

5. 블럭정의


5-1. SHB(Section Header Block) - 필수


이 세션 헤더블럭은 꼭 있어야 되는 블럭중에 하나이며, 캡쳐 덤프파일 세션의 가장 처음에 나타납니다. 이 헤더 자체에는 데이터가 포함되지 않으며, 사용될 블럭 정보들이 기록되게 됩니다.

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                   Block Type = 0x0A0D0D0A                     |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |                      Byte-Order Magic                         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 |          Major Version        |         Minor Version         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 |                                                               |
   |                          Section Length                       |
   |                                                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+

각 포맷의 의미를 알아보면 처음 시작되는 블럭 타입에 대한 고정된 값이 있습니다. 이 값은 캐리지리턴값 과도 같은 "\r\n\n\r" 입니다. 16진수로는 0x0A0D0D0A 가 되겠죠. 다음은 블럭전체에 대한 길이가 나오고 바이트 오더 매직인 0X1A2B3C4D 가 나옵니다. 1234 와 ABCD 로 연속적인 값이니 외우기는 쉽겠죠? 이 값은 리틀엔디안 또는 빅엔디안 시스템에서 저장된 데이터인지 판별하는데 사용됩니다. 그 다음으로 Major, Minor 버전 정보는 해당 포맷에 대한 정보로 현재 Major 는 1 이고 Minor 는 0 입니다. 포맷 자체가 변경되지 않는 이상 해당 값은 블럭타입과 같이 항상 고정되어 있는 값으로 볼 수 있습니다. Section Length는 이어지는 세션에대한 길이 정보롤 64비트 값을 가지고 있습니다. 이 세션 길이에 대한 계산시에는 SHB 헤더 자체는 포함되지 않습니다. 그리고 이 필드는 조금 다른 용도로도 이용되는데요, 큰 패킷파일을 처리할때 빠른 이동을 위해 세션 정보를 스킵하는데 사용될 수 있습니다. 만약 세션 길이가 -1 (0xFFFFFFFFFFFFFFFF) 로 정의되어 있다면 이 세션에 대한 크기가 정의되어 있지 않고 해당 블록이 포함이 하고 있는 데이터의 세션은 Skip 하는데 사용되는데 이용됩니다. 마지막으로 옵션 필드는 이름 그대로 추가적인 정보가 덧 붙을 수 있는데, 다음과 같습니다.


이름코드번호설명
shb_hardware2이 세션이 만들어지는데 이용된 하드웨어 정보
shb_os3이 세션이 만들어지는데 이용된 운영체제 이름 정보
shb_userappl4이 세션이 만들어지는데 이용된 애플리케이션 이름 정보

5-2. IDB(Interface Description Block) - 필수


IDB 또한 SHB 와 마찬가지로 필수적으로 필요한 블럭입니다. 이 블럭은 패킷 캡쳐를 수행한 네트워크 인터페이스에 대한 정보를 담고 있습니다. 이 블럭은 다른 블럭정보를 표시하기 전에 사전에 정의되어 있어야 하므로 보통은 SHB 블럭 다음에 위치합니다.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                    Block Type = 0x00000001                    |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |           LinkType            |           Reserved            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 |                            SnapLen                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+


IDB 의 포맷을 살펴보면 처음 블럭타입을 지정하는 정보가 나옵니다. 그리고 블럭 대한 전체 길이 정보와 인터페이스의 링크레이어 타입 정보가 이어집니다. 대부분의 경우라면 링크타입은 이더넷이 될 것입니다. Snaplen 은 패킷 덤프할 시에도 지정할 수 있는 값으로 각 패킷의 최대 바이트 값이 되고 다양한 옵션 정보가 추가될 수 있습니다.

옵션 이름코드번호설명
if_name2캡쳐 디바이스로 사용된 인터페이스 이름  
if_description3캡쳐 디바이스로 사용된 인터페이스 설명. 예를들면 "Broadcom NetXtreme"
if_IPv4addr4인터페이스의 네트워크 주소와 넷마스크 - IPv4
if_IPv6addr5인터페이스의 네트워크 주소와 프리픽스 길이 - IPv6
if_MACaddr6인터페이스 하드웨어 맥 주소 (48비트)
if_EUIaddr7인터페이스 하드웨어 EUI 주소 (64비트)
if_speed8인터페이스 속도 ( bps 단위)
if_tsresol9타임스탬프 표현 (만약 값이 6이면 1970/1/1 이후 마이크로세컨드 표시)
if_tzone10타임존 
if_filter11캡쳐필터로 사용한 필터 정보 (ex. "tcp port 80" )
if_os12운영체제 정보
if_fcslen13FCS(Frame Check Sequence) 길이 값
if_tsoffset14각 패킷에 더해지는 특정 오프셋 정수 값

5-3. EPB(Enhanced Packet Block)


EPB 가 네트워크 패킷 정보를 저장하는 기본 블럭이 됩니다. 패킷저장을 할때 EPB 또는 아래에서 설명드릴 SPB(Simple Packet Block) 가 사용될 수 있으므로 반드시 사용되어야 할 블럭이기 보단 옵션으로 선택할 수 있는 블럭입니다.

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                    Block Type = 0x00000006                    |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |                         Interface ID                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 |                        Timestamp (High)                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 |                        Timestamp (Low)                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 |                         Captured Len                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 |                          Packet Len                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 /                                                               /
   /                          Packet Data                          /
   /          /* variable length, aligned to 32 bits */            /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+

EPB 블럭의 필드를 살펴보면 블럭타입은 6 을 가지고 있습니다. (0x00000006) 그 다음 다른 블럭과 마찬가지로 해당 블럭의 전체 크기가 나옵니다. Interface ID 는 패킷이 어떤 인터페이스를 통해 들어왔는지에 대한 해당 인터페이스 정보가 들어갑니다. 즉 이 정보는 IDB(Interface Description Block)에 정의된 정보와 같게 됩니다. 이 부분이 SPB 와는 다른 정보로 32 비트 값을 사용하고 있습니다. 또 타임스탬프 값으로 2개를 사용하고 있습니다. high, low 로 나뉘어져 있는 32비트를 사용하여 타임스탬프를 표현하는데 있어 64비트를 사용합니다. 1970년1월1일 부터 64bit unsinged 로 표시하며 libpcap 파일 포맷의 타임스탬프 저장시 사용하던 초, 마이크로세컨드 형태로 나누어 저장되는 것이 아닌 한개의 64비트 형태로 값이 표현되는 것입니다. Captured Len 은 패킷 캡쳐된 크기 값입니다. 이 필드는 패킷 데이터 필드 크기를 맞추기 위해 수행하는 Align 데이터 값, 즉 패딩이라고 부르는 데이터가 포함되어 있습니다. Packet Len 은 네트워크 상에서 실제 전송된 패킷 크기 입니다. 사용자가 패킷 덤프시 Snaplen 값을 따로 정의하여 사용하면 Captured Len 과 크기가 달라질 수 있습니다. Snaplen 이 60 바이트로 정의했다면 실제 전송된 패킷은 150 바이트가 되더라도 캡쳐된 크기는 60 바이트가 되는 것입니다. 그리고 이 필드 후에 실제 패킷데이터가 오게 됩니다. 마지막으로 옵션이 붙을 수 있는데 간단하게만 설명하면 다음과 같습니다.

옵션 이름코드번호설명
epb_flags2링크 레이어 정보가 포함된 플래그 (비트 단위로 표현한 것으로 패킷의 인바운드 또는 아웃 바운드도 표현할 수 있다)
epb_hash3패킷 해쉬 정보 
epb_dropcount4패킷 손실된 개수 - 64비트

5-4. SPB(Simple Packet Block)


SPB 는 EPB 보다 가벼운 패킷 저장 구조입니다. SPB 는 PB(Packet Block)와 유사하면서 더 작은 구조로 최소한의 정보만을 담고 있습니다. EPB 보다 저장하는 것이 적기 때문에 빠른 속도로 패킷 저장이 필요하다면 이 블럭이 더 유리합니다. SPB 의 큰 차이점은 인터페이스 ID 필드를 포함하고 있지 않습니다. 그렇기 때문에 IDB 에서 정의된 첫번째 인터페이스에서 캡쳐가 되고 있는 것으로 가정할 수 있습니다. 이 뜻은 한 개 이상의 인터페이스 패킷정보를 가질수가 없다는 뜻이 되기도 합니다. 인터페이스 ID 필드가 없기 때문에 해당 패킷이 어떤 인터페이스를 통해 들어왔는지 알수 없기 때문입니다. 또, 타임스탬프(Timestamp) 필드도 존재하지 않습니다. 타임스탬프가 필요한 경우도 있지만, 패킷 자체만을 고속으로 봐야 하는 경우는 타임스탬프 자체도 영향을 줄 수 있는 요소이기 때문에 SPB 에서는 사용되지 않습니다. 참고로 PB 는 더 이상 사용되지 않는 블럭이므로 패킷 데이터 저장에는 EPB 또는 SPB 로 저장된다고 볼 수 있습니다.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                    Block Type = 0x00000003                    |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |                          Packet Len                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 /                                                               /
   /                          Packet Data                          /
   /          /* variable length, aligned to 32 bits */            /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+


블럭타입은 3 (0x00000003) 이며, 다른 블럭과 마찬가지로 해당 블럭의 전체 크기가 이어집니다. 패킷 데이터가 기록되기 전 패킷 길이 필드가 존재하고 이후 데이터가 저장됩니다. EPB 에 비해 저장되는 필드 정보가 적기 때문에 디스크 용량 사용면에서도 유리하게 됩니다.

참고 정보- 블럭 타입 코드 

블럭 타입 코드설명
0x00000000Reserved
0x00000001IDB(Interface Description Block)
0x00000002Packet Block
0x00000003Simple Packet Block
0x00000004Name Resolution Block
0x00000005Interface Statistics Block
0x00000006Enhanced Packet Block
0x0A0D0D0ASection Header Block


2013년 8월 6일 화요일

패킷에서 HTTP 를 전문적으로 뽑아주는 httpry

HTTP 트래픽을 캡쳐하는 간단한 도구를 소개해 드립니다. httpry 는 HTTP 트래픽에 대해서만 패킷 캡쳐를 하는 도구로 HTTP 트래픽에 한해 네트워크 정보를 살펴볼 때 사용할 수 있습니다.

HTTP 요청 정보 현황, HTTP 를 통해 다운로드 되는 의심스러운 파일 감시, HTTP 트래픽 사용 패턴 파악, HTTP 통계 정보 등 사용하고자 하는 형태에 따라 사용되는 목적은 다양할 것 같습니다.

다운로드는 다음 사이트에서 받을 수 있습니다.

http://dumpsterventures.com/jason/httpry/

소스 자체가 간결해서 컴파일은 아주 쉽게 할 수 있습니다.

# tar -xvf httpry-0.1.7.tar
# cd httpry-0.1.7
# make
# make install

도움말은 -h 옵션을 사용하면 됩니다. -i 로 덤프할 인터페이스를 지정할 수 있고 -r 로 패킷파일을 읽어들일 수 있습니다.

Usage: httpry [ -dFhpqs ] [-b file ] [ -f format ] [ -i device ] [ -l threshold ]
              [ -m methods ] [ -n count ] [ -o file ] [ -P file ] [ -r file ]
              [ -t seconds] [ -u user ] [ 'expression' ]

사용방법이 간단해서 도움말 한번 보시면 어떤 기능인지 쉽게 이해하실 수 있습니다. 기본 출력되는 형태는 다음과 같습니다.

# ./httpry -i eth0
httpry version 0.1.7 -- HTTP logging and information retrieval tool
Copyright (c) 2005-2012 Jason Bittel <jason.bittel@gmail.com>
Starting capture on eth0 interface
2013-08-06 08:45:16 192.168.1.1 173.194.72.121 > GET www.packetinside.com / HTTP/1.0 - -
2013-08-06 08:45:16 173.194.72.121 192.168.1.1 < - - -HTTP/1.0 200 OK
2013-08-06 08:45:34 192.168.1.1 74.125.31.121 > GET www.packetinside.com / HTTP/1.0 - -
2013-08-06 08:45:35 74.125.31.121 192.168.1.1 < - - -HTTP/1.0 200 OK
2013-08-06 08:45:49 192.168.1.1 74.125.235.68 > GET google.com / HTTP/1.0 - -
2013-08-06 08:45:50 74.125.235.68 192.168.1.1 < - - -HTTP/1.0 301 Moved Permanently
2013-08-06 08:45:50 192.168.1.1 74.125.235.84 > GET www.google.com / HTTP/1.0 - -
2013-08-06 08:45:50 74.125.235.84 192.168.1.1 < - - -HTTP/1.0 302 Found
2013-08-06 08:45:50 192.168.1.1 74.125.235.159 > GET www.google.co.kr /?gws_rd=cr HTTP/1.0 - -
2013-08-06 08:45:50 74.125.235.159 192.168.1.1 < - - -HTTP/1.0 200 OK
^CCaught SIGINT, shutting down...
484 packets received, 0 packets dropped, 16 http packets parsed
397.8 packets/min, 13.2 http packets/min

HTTP 트래픽에 대해서 모니터링 하실 분들은 참고하세요

2013년 7월 25일 목요일

차세대 패킷 포맷, Pcap-NG 를 알고싶다 _ 첫번째 이야기

저번 포스팅에서 pcap-ng 를 pcap 으로 그리고 pcap 을 pcap-ng 로 변환하는 방법에 대해서 소개했습니다. 오늘은 말씀드렸던것과 같이 차세대 패킷 저장 포맷인 pcap-ng 를 자세히 알아보고자 합니다. 첫번째로, pcap-ng 의 주요한 특징/기능 에 대해서 말씀드리겠습니다.

차세대 패킷 저장 포맷을 만들시 고려사항, 즉 최종 목표는 다음과 같습니다.

- Extensibility
- Portability
- Merge/Append data

확장성도 좋아야 하고 패킷 파일을 덤프한 곳에 대한 최대한 많은 정보를 포함시키고 데이터를 통합하거나 추가하기도 유연해야 했습니다. 이렇게 해서 디자인 된 것이 pcap-ng 입니다.

주요한 사항들에 대해서 아래와 같이 적어보았습니다.

- 와이어샤크 1.8 에서 기본 파일 포맷이 Pcap-NG 로 변경됨
- Tcpdump 버전 4.1.1 이상에서 Pcap-NG 를 지원
- NTAR(Network Trace Archival and Retrieval) 로 불리기도 함
- Pcap-NG 에서 메타 데이터를 포함할 수 있음 (운영체제, 패킷 캡쳐 프로그램, 캡쳐 필터 등)

<주요특징>

- 한개의 파일에 여러개의 인터페이스 트래픽이 캡쳐되어 저장될 수 있습니다. 인터페이스가 다른 형태의 데이터 링크 타입이라도 가능합니다. 예를들어 802.11, PPP 를 동시에 저장하는 것이 가능하게 되었습니다.

- 메타데이터 정보 기록이 가능합니다. 어떤 운영체제, 하드웨어 인지, 캡쳐 프로그램에 사용한 패킷 캡쳐 프로그램과 같은 정보로 와이어샤크와 dumpcap 은 Pcap-NG로 저장할때 자동생성합니다.

- 패킷 시간 기록 한계가 해결되었습니다. 현재 10^6 의 마이크로세컨드를 이용하여 표현을 하다보니 초당 999,999 개 이상의 패킷 시간 기록에 한계가 있습니다. 오늘날과 같은 1기가 이상의 고속 네트워크에서는 이 비율을 쉽게 초과하므로 문제가 있죠. pcapng 에서는 64비트 시간을 이용하여 표현하게 되어 이런 문제를 해결할 수 있습니다. 아래 화면은 10g 구간에서 패킷 덤프를 한 것으로 같은 타임스탬프가 찍히는 것을 볼 수 있습니다. 바로 이런 문제가 극복된 것이죠.
[Image]
[Image Source] CESNET

- 각 개별 프레임마다 코멘트가 기록되어 저장될 수 있습니다. 와이어샤크에서 필터이름 "pkt_comment" 로 출력이 가능합니다. 예를들어, tshark -r test.pcapng -T fields -e pkt_comment -R pkt_comment 로 사용하면 코멘트를 출력할 수 있습니다.

- 유연한 파일포맷을 제공하여 해당 포맷을 이용하는 소프트웨어에서 유연하게 사용할 수 있게 되었습니다. 포맷 형태가 블럭별로 되어 있어 필요치 않은 블럭은 제외되어도 패킷 포맷을 처리하는데 문제가 없게 되었고 이것은 도구에서 제공하는 기능상황에 따라 유연한 포맷형태로 사용가능하다는 뜻입니다.

- 각 인터페이스에 대한 메타 정보가 기록되어 있습니다. 이런 정보는 인터페이스 이름, 손실된 패킷, 캡쳐 필터 정보가 해당됩니다.

너무 길게 설명하면 지루하니 오늘은 pcap-ng 의 특징들 까지만 알아보고 다음번에 포맷에 대해서 좀더 알아보겠습니다.

[참고]
[1] PCAPNG 파일 포맷
http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
[2] 차세대 패킷 포맷 PCAP-NG 를 PCAP 으로 쉽게 변환하기
http://www.packetinside.com/2013/07/pcap-ng-pcap.html

2013년 7월 19일 금요일

차세대 패킷 포맷 PCAP-NG 를 PCAP 으로 쉽게 변환하기

인기있는 패킷분석 도구인 최신 와이어샤크를 사용하면 패킷파일 저장시에 기본적으로 차세대 PCAP 포맷인 PCAPNG 형태로 저장되고 있습니다. 항상 확장자가 cap 또는 pcap 으로 되어 있는 것으로만 익숙해져 있는데 말이죠. 디폴트로 사용되다 보니 과거 보다는 pcapng 포맷이 조금 더 증가한 느낌입니다. pcapng 포맷은 pcap 보다 패킷 파일 저장시 더 많은 정보를 기록하고 있습니다. 더 많은 정보를 주니 분석가 입장에서는 싫을 이유는 없겠죠. 다만, 패킷 파일 사이즈가 더 커지는 문제는 있습니다.

오늘은 PCAP 에 익숙하신 분들을 위하여 PCAP-NG 포맷을 PCAP 으로 쉽게 바꾸는 방법에 대해서 알려드릴께요.

와이어샤크가 설치되어 있다면 editcap 을 통해 쉽게 하실 수가 있습니다. editcap 의 -F 옵션을 보면 캡쳐 타입 리스트를 볼 수 있습니다.

# editcap -F
editcap: The available capture file types for the "-F" flag are:
    5views - Accellent 5Views capture
    btsnoop - Symbian OS btsnoop
    commview - TamoSoft CommView
    dct2000 - Catapult DCT2000 trace (.out format)
    erf - Endace ERF capture
    eyesdn - EyeSDN USB S0/E1 ISDN trace format
    k12text - K12 text file
    lanalyzer - Novell LANalyzer
    libpcap - Wireshark/tcpdump/... - libpcap
    modlibpcap - Modified tcpdump - libpcap
    netmon1 - Microsoft NetMon 1.x
    netmon2 - Microsoft NetMon 2.x
    nettl - HP-UX nettl trace
    ngsniffer - NA Sniffer (DOS)
    ngwsniffer_1_1 - NA Sniffer (Windows) 1.1
    ngwsniffer_2_0 - NA Sniffer (Windows) 2.00x
    niobserver - Network Instruments Observer
    nokialibpcap - Nokia tcpdump - libpcap
    nseclibpcap - Wireshark - nanosecond libpcap
    nstrace10 - NetScaler Trace (Version 1.0)
    nstrace20 - NetScaler Trace (Version 2.0)
    pcapng - Wireshark - pcapng
    rf5 - Tektronix K12xx 32-bit .rf5 format
    rh6_1libpcap - RedHat 6.1 tcpdump - libpcap
    snoop - Sun snoop
    suse6_3libpcap - SuSE 6.3 tcpdump - libpcap
    visual - Visual Networks traffic capture

눈에 익숙한 libpcap 과 pcapng 가 보입니다. 바로 이것을 이용하면 됩니다.

1. PCAPNG 포맷 PCAP 으로 변환하기 


editcap 을 이용해 캡쳐 타입과 -T 를 통해 캡슐화를 정의해 주어야 합니다. 캡슐화라는 용어가 익숙하지 않다면 다음글을 우선 참고해 보세요.

패킷을 보다 자주 접하는 캡슐화(Encapsulation)는 무엇이지?



# editcap -F libpcap -T ether test.pcapng test.pcap

만약 -T 로 encapsulation 을 지정하지 않으면 다음과 같은 에러가 발생합니다.

# editcap -F libpcap test.pcapng test3.pcapeditcap: Can't open or create test3.pcap: Files from that network type can't be saved in that forma

2. PCAP 포맷을 PCAPNG 포맷으로 변경하기 


PCAPNG -> PCAP 변환이 있다면 이 반대 방법도 존재하겠죠. 여기서는 -T 옵션을 사용할 필요가 없습니다.

# editcap -F pcapng test.pcap test.pcapng

또는 tshark 를 이용할 수도 있습니다.

# tshark -F pcapng -r test.pcap -w test.pcapng

만들어진 파일을 살펴보겠습니다.

# ls -l
-rw-r--r-- 1 root    root     3015906 Jul 10 06:25 test.pcap
-rw-r--r-- 1 root    root     3551608 Jul 10 06:28 test.pcapng

원본 test.pcap 이 3메가 정도가 되는데, pcapng 포맷으로 변경하니 3.5 메가 정도로 크기가 증가하였습니다. file 명령어를 이용해 타입을 살펴보겠습니다.

# file test.pcapng
test.pcapng: pcap-ng capture file - version 1.0
# file test.pcap
test.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 1514)

정확히 포맷을 인식하고 있네요. 정상적으로 변환이 잘 된것 같습니다. 이 2개 파일을 비교하면 당연히 완전 다릅니다. 패킷 내용 자체는 같더라도 부가적으로 포함되어 있는 내용과 구조가 다르기 때문입니다.

차세대 패킷 파일 포맷, PCAP-NG 를 다음번 포스팅에서 자세히 소개해 보도록 하겠습니다.

아, 참고로 pcapng.com  에서는 온라인에서 pcap-ng 를  pcap 으로 변환할 수 있습니다.

2013년 7월 9일 화요일

수성 탐사선 메신저호에 사용된 CPU 는 겨우 25MHz


몇일 전 부터 읽어보기 시작한 '행성이야기'라는 책이 있습니다. 제목과 같이 각 행성별로 다양한 이야기를 풀어 놓고 있습니다. 수성편을 보다가 2011년에 수성궤도에 안착한 '메신저호' 가 궁금해 살짝 찾아보았습니다. 수성을 탐사했던 것이 1975년 '마리너 10호'가 표면의 일부 사진을 찍어 전송해 왔습니다. 수성은 상대적으로 알려진 것이 많지 않은 행성이었고, 나사에서는 수성의 신비를 캐기 위해 2004년 8월 메신저호를 발사합니다.


6년7개월간 79Km 긴 항해 끝에 2011년3월18일 수성 궤도에 진입하여 본격적인 수성탐사가 시작되었습니다. 그리고 첫번째로 전송되어 온 사진이 아래와 같습니다.


메신저호에 관한것은 검색해 보면 많은 내용들이 있으니 한번 보시고요, 제가 관심이 갔던 내용은 이 위성에 사용된 하드웨어 입니다. 그 중에서도 프로세서 인데요, IBM RAD6000 이라는 것입니다. 2개의 CPU 가 탑재되어 있고 메인 프로세서는 25MHz 로 동작하고 나머지 백업프로세서는 10MHz 라고 합니다. 이걸로 모든 데이터를 취합하고 압축하여 위성에 달린 3개의 안테나를 이용해 지구로 데이터를 전송합니다. 저희가 지금 사용하는 프로세서가 GHz 에 달하는데 아니 겨우 25MHz 라니 놀랍지 않은가요?

해당 프로세서는 또 우주의 환경을 잘 견딜 수 있도록 방사능 같은것에서도 안정적으로 동작할 수 있도록 만들어졌다고 합니다. 그만큼 빠른 속도보다도 안정적으로 동작하는 것이 최우선이기 때문입니다. RAD6000 은 클럭을 33 또는 66MHz 를 선택할 수 있는데 낮은 클럭을 선택할 수록 신뢰성은 더욱 높아진다고 볼 수 있습니다. 그래서 메신저호에서 선택한 클럭 스피드는 25MHz 입니다. 그리고 해당 프로세서가 파이프라인을 통해 한 클럭 사이클에서도 여러 명령어를 한번에 실행할 수 있다고 합니다. 이 뜻은 클럭이 낮은 경우라도 보다 빠른 처리를 할 수 있는 부분입니다. 또 전체 칩셋은 110만개의 트랜지스터로 구성되어 있어 보다 낮은 전력을 소모합니다. 트랜지스터가 적을 수록 우주 방사능 노출 에서도 더 안정적이라고 하더군요. 이외 태양 전지판으로 전력을 받는 것도 제한적이므로 전력 소모가 적어야 하는 것은 당연한 일입니다.

RAD6000 은 화성 탐사선 스피릿 로버와 오퍼튜니티에서도 사용되었다고 합니다. 중요한 임무를 수행하는 로봇에서도 이 정도로도 가능하다니 대단하지 않나요. 그래도 이 작은 프로세서가 가격이 $200,000 이 넘는다고 합니다.

이상 위성의 CPU 가 궁금했던 Rigel 이었습니다.

[ 참고]
1. RAD6000 위키피디아
2. 나사 메신저 홈페이지
3. 네이버 과학지식(수성 탐사선 메신저호)

2013년 7월 2일 화요일

미 국가안보국의 감청 프로젝트, 프리즘(PRISM)

Edward Snowden 이 미국의 종합적인 감청 시스템에 대해 폭로하면서 많은 이야기들이 나오고 있습니다. NSA 감청 프로그램인 프리즘(PRISM) 에 대한 세부적인 슬라이드가 워싱펀 포스트지에 의해 추가로 공개되었습니다. 초기(6월6일)에 4장의 슬라이드가 공개되었고 이후(6월29일)에 4장의 슬라이드가 또 공개되어졌습니다. 이 슬라이드에 따르면 NSA 는 이메일 로긴, 이메일 발송, 채팅 서비스등의 이벤트를 감청할 수 있는 것으로 보인다고 합니다. 실시간으로 가능한지 여부는 정확히 모르겠네요.

데이타 수집에 대한 프로세스도 세부적으로 표시되어 있는데, 인터넷 데이터, 전화 기록, 음성 데이터, 비디오 데이터를 포함해 광범위하게 수집되고 있습니다. 프리즘 데이터베이스에는 117,675 개의 주요 감청 대상이 있으나 정확하게 알려져 있지는 않습니다.

프리즘 프로그램에 처음으로 참여한 기업은 마이크로소프트로 2007년9월부터라고 합니다. 슬라이드에 있는 프리즘 Provider 를 보면 Microsoft, Yahoo, Google, Facebook, PalTalk, YouTube, Skype, AOL, Apple 입니다. 굵직한 기업은 다 포함되어 있네요.

슬라이드중 PRINTAURA 가 트래픽 데이터를 자동으로 수집하는 것인가 봅니다. 이 트래픽 데이터를 다 수집하려면 만만치 않은 작업인거 같은데, 대단하네요. 기사에 보니까 한국도 감청 대상이었다고 하네요 ㅜㅜ



[참고]
1. 워싱턴포스트 프리즘 자료
http://www.washingtonpost.com/wp-srv/special/politics/prism-collection-documents/

2013년 6월 27일 목요일

TCP/IP Fundamentals for Microsoft Windows

윈도우 시스템에서 TCP/IP 를 잘 기술해 놓은 온라인 문서가 있기에 공유합니다.
아래 경로로 가시면 PDF 파일로 다운로드 받을 수 있고, 560 페이지나 됩니다.

http://www.microsoft.com/en-us/download/details.aspx?id=8781

윈도우 환경에서 네트워크 환경을 이해하는데 좋은 것 같고, 윈도우 뿐만 아니라
TCP/IP 의 기본적인 내용, 서브네팅, 라우팅등 많은 내용이 기술되어 있습니다.

총 16 Chapter 까지 있고 목차만 봐도 내용이 튼실합니다.

추천드립니다.



2013년 6월 21일 금요일

두 개의 GPU를 이용한 패스워드 해쉬 해독 리얼 사용기

오랜만에 쓰는 포스팅인것 같습니다. 이런저런 일로 글 쓸 시간이 많이 없다 보니 힘드네요 :-)

GPU 를 가지고 패스워드 해쉬를 찾아내는데 얼마나 속도가 나오는지 테스트를 해보았습니다. NVIDIA 사의 GTX 660 Ti 를 가지고 진행했고요, 그 녀석 실물은 다음과 같습니다.


포스팅한 글 중에서 15기가 단어사전을 소개한적이 있습니다. 해당 단어 사전을 이용하는 경우에는 어떨까 우선 테스트를 해 보았습니다. 압축되어 있는 파일은 4.5 기가 입니다.

$ ls -l
total 4469864
-rw-r--r-- 1 xxx xxx 4500756826 Apr 23 18:35 crackstation.txt.gz

해당 파일의 압축을 풀어 보니 15 기가나 되고, 라인수만 12억 라인이 나오네요.

$ gzip -d crackstation.txt.gz
$ ls -l
total 15402816
-rw-r--r-- 1 xxx xxx 15696118781 Apr 23 18:35 crackstation.txt

$ wc -l crackstation.txt
1212356398 crackstation.txt

자 그럼 사전파일을 이용해 성능은 어떤지 테스트 해보겠습니다. packetinside 의 MD5 HASH 값을 사용했는데, 30초 만에 패스워드를 찾아냈습니다. 사전파일에 packetinside 가 들어 있었다니 감사하네요 :-)

해쉬값을 찾는데 사용한 프로그램은 해쉬캣 입니다. 아래 사이트에서 다운로드 받으실 수 있습니다.

[Hashcat] http://hashcat.net/

$ time ./hashcat-cli64.bin -m 0 t ../crackstation.txt

Input.Mode: Dict (../crackstation.txt)
Index.....: 303/468 (segment), 2843682 (words), 33550339 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: - plains, - words
Progress..: 2843682/2843682 (100.00%)
Running...: --:--:--:--
Estimated.: --:--:--:--

48bd28f405a9e3713ac0605a48b2bd0b:packetinside
All hashes have been recovered

real 0m30.466s
user 1m26.821s
sys 0m2.372s

즉, 많은 사용자들의 경우가 단순한 조합의 단어 같은 경우를 사용한다면 사전파일에 의해서 쉽게 해독될수도 있다는 의미입니다. 무작정 Brute Force 를 수행하는 경우보다 더 빨리 맞출 확률이 높아집니다. 만약 packetinside 문자열을 사전 없이 추측해서 찾는 경우는 얼마나 걸릴까요? 얼마나 오래 걸리는지는 잠시후에 확인해 드리겠습니다.

일단 이번에는 같은 사전파일을 쓰는데 대신 GPU 를 사용하는 cudaHashcat 을 이용해서 해 보았습니다.

$ time ./cudaHashcat-plus64.bin -m 0 -n 160 -u 1024 ../hashcat-0.44/t ../crackstation.txt
cudaHashcat-plus v0.14 by atom starting...

Hashes: 1 total, 1 unique salts, 1 unique digests
Bitmaps: 8 bits, 256 entries, 0x000000ff mask, 1024 bytes
Rules: 1
Workload: 1024 loops, 160 accel
Watchdog: Temperature abort trigger set to 90c
Watchdog: Temperature retain trigger set to 80c
Device #1: GeForce GTX 660 Ti, 2047MB, 1045Mhz, 7MCU
Device #1: Kernel ./kernels/4318/m0000_a0.sm_30.64.ptx

Cache-hit dictionary stats ../crackstation.txt: 15696118781 bytes, 1035765763 words, 1035765763 keyspace

[s]tatus [p]ause [r]esume [b]ypass [q]uit => s
Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: File (../crackstation.txt)
Hash.Target....: 48bd28f405a9e3713ac0605a48b2bd0b
Hash.Type......: MD5
Time.Started...: 0 secs
Time.Estimated.: Fri May  3 09:15:43 2013 (1 min, 49 secs)
Speed.GPU.#1...: 72826.3k/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 7741441/1035765763 (0.75%)
Rejected.......: 1/7741441 (0.00%)
HWMon.GPU.#1...: -1% Util, 37c Temp, 10% Fan

[s]tatus [p]ause [r]esume [b]ypass [q]uit => s
Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: File (../crackstation.txt)
Hash.Target....: 48bd28f405a9e3713ac0605a48b2bd0b
Hash.Type......: MD5
Time.Started...: Fri May  3 09:13:53 2013 (3 secs)
Time.Estimated.: Fri May  3 09:15:43 2013 (1 min, 46 secs)
Speed.GPU.#1...: 72912.7k/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 35840001/1035765763 (3.46%)
Rejected.......: 1/35840001 (0.00%)
HWMon.GPU.#1...: -1% Util, 37c Temp, 10% Fan

48bd28f405a9e3713ac0605a48b2bd0b:packetinside
                                           
Session.Name...: cudaHashcat-plus
Status.........: Cracked
Input.Mode.....: File (../crackstation.txt)
Hash.Target....: 48bd28f405a9e3713ac0605a48b2bd0b
Hash.Type......: MD5
Time.Started...: Fri May  3 09:13:53 2013 (1 min, 25 secs)
Speed.GPU.#1...: 71962.8k/s
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 796221441/1035765763 (76.87%)
Rejected.......: 1/796221441 (0.00%)
HWMon.GPU.#1...: -1% Util, 39c Temp, 10% Fan

Started: Fri May  3 09:13:53 2013
Stopped: Fri May  3 09:15:18 2013

real 1m25.139s
user 1m23.773s
sys 0m1.396s

처음에 사전파일 캐쉬를 만들어서 그런지 오히려 속도가 더 늦어진 1분 25초가 나왔습니다.

GPU 를 이용했는데 속도가 더 느리다고요? 그래서 실망하셨나요. 그렇지 않습니다. GPU 의 힘을 한번 보여드릴께요. 6 자리의 패스워드로 가정하고 GPU 로 bruteforce 해 보도록 하겠습니다.

$ time ./cudaHashcat-plus64.bin -m0 -a 3 --force t ?a?a?a?a?a?a
cudaHashcat-plus v0.14 by atom starting...

Hashes: 1 total, 1 unique salts, 1 unique digests
Bitmaps: 8 bits, 256 entries, 0x000000ff mask, 1024 bytes
Workload: 256 loops, 80 accel
Watchdog: Temperature abort trigger set to 90c
Watchdog: Temperature retain trigger set to 80c
Device #1: GeForce GTX 660 Ti, 2047MB, 1045Mhz, 7MCU
Device #1: Kernel ./kernels/4318/m0000_a3.sm_30.64.ptx

[s]tatus [p]ause [r]esume [b]ypass [q]uit => s
Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: Mask (?a?a?a?a?a?a)
Hash.Target....: 9c509e44db33400b9ffef2157ada8b5a
Hash.Type......: MD5
Time.Started...: Fri May  3 10:18:40 2013 (6 secs)
Time.Estimated.: Fri May  3 10:26:50 2013 (8 mins, 3 secs)
Speed.GPU.#1...:  1544.1M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 10331955200/735091890625 (1.41%)
Rejected.......: 0/10331955200 (0.00%)
HWMon.GPU.#1...: -1% Util, 56c Temp, 13% Fan

9c509e44db33400b9ffef2157ada8b5a:packet    
                                           
Session.Name...: cudaHashcat-plus
Status.........: Cracked
Input.Mode.....: Mask (?a?a?a?a?a?a)
Hash.Target....: 9c509e44db33400b9ffef2157ada8b5a
Hash.Type......: MD5
Time.Started...: Fri May  3 10:18:40 2013 (19 secs)
Speed.GPU.#1...:  1543.3M/s
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 28537528320/735091890625 (3.88%)
Rejected.......: 0/28537528320 (0.00%)
HWMon.GPU.#1...: -1% Util, 52c Temp, 16% Fan

Started: Fri May  3 10:18:40 2013
Stopped: Fri May  3 10:19:00 2013

real 0m19.095s
user 0m0.192s
sys 0m0.124s

속도를 보셨나요? 초당 1544M/s 의 속도로 대입해 봅니다. 6자리가 단지 19초 만에 해독되었습니다. 이번에는 그럼 GPU 가 아닌 형태로 해보죠. cudaHashcat 에서 hashcat 을 이용하는 것으로만 바꾸고 똑같이 6자리라는 힌트를 줍니다.

$ time ./hashcat-cli64.bin -m 0 -a 3 t ?a?a?a?a?a?a
Initializing hashcat v0.44 by atom with 8 threads and 32mb segment-size...

Added hashes from file t: 1 (1 salts)
Activating quick-digest mode for single-hash

NOTE: press enter for status-screen

Input.Mode: Mask (?a)
Index.....: 0/1 (segment), 95 (words), 0 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: - plains, - words
Progress..: 95/95 (100.00%)
Running...: --:--:--:--
Estimated.: --:--:--:--

Input.Mode: Mask (?a?a)
Index.....: 0/1 (segment), 9025 (words), 0 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: - plains, - words
Progress..: 9025/9025 (100.00%)
Running...: --:--:--:--
Estimated.: --:--:--:--

Input.Mode: Mask (?a?a?a)
Index.....: 0/1 (segment), 857375 (words), 0 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: - plains, - words
Progress..: 857375/857375 (100.00%)
Running...: --:--:--:--
Estimated.: --:--:--:--

Input.Mode: Mask (?a?a?a?a)
Index.....: 0/1 (segment), 81450625 (words), 0 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: 92.80M plains, 92.80M words
Progress..: 81450625/81450625 (100.00%)
Running...: 00:00:00:01
Estimated.: --:--:--:--

Input.Mode: Mask (?a?a?a?a?a)
Index.....: 0/1 (segment), 7737809375 (words), 0 (bytes)
Recovered.: 0/1 hashes, 0/1 salts
Speed/sec.: 95.85M plains, 95.85M words
Progress..: 7737809375/7737809375 (100.00%)
Running...: 00:00:01:21
Estimated.: --:--:--:--

9c509e44db33400b9ffef2157ada8b5a:packet
All hashes have been recovered

real 18m40.477s
user 148m1.191s
sys 0m4.644s

18 분만에 결과가 나왔습니다. 초당 95M/s 속도밖에 안 나왔고 GPU 를 이용한 것과는 너무나 큰 차이를 확인할 수 있습니다.

GPU 의 성능을 더 확인해 볼까요? 6자리 테스트에서 2자리를 늘려 8자리로 해 보겠습니다. 패스워드는 packetin 이고 MD5 는 8ebf50fe1d60d34fba86bf48cbec7f3b 와 같습니다.
                                           
Session.Name...: cudaHashcat-plus
Status.........: Cracked
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a)
Hash.Target....: 8ebf50fe1d60d34fba86bf48cbec7f3b
Hash.Type......: MD5
Time.Started...: Fri May  3 14:29:57 2013 (16 mins, 7 secs)
Speed.GPU.#1...:  1545.7M/s
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 1493089239040/6634204312890625 (0.02%)
Rejected.......: 0/1493089239040 (0.00%)
HWMon.GPU.#1...: -1% Util, 61c Temp, 39% Fan

Started: Fri May  3 14:29:57 2013
Stopped: Fri May  3 14:46:05 2013

real 16m7.484s
user 0m2.108s
sys 0m1.040s

6자리 19초에 비해 8 자리는 시간이 크게 늘어난 16분 7초가 소요되었습니다. 더 궁금해 지기 시작합니다. 다시 한번 2자리를 늘려서 10자리로 해 보겠습니다.

Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a?a?a)
Hash.Target....: ffc67bb0648c6f880f100719b3442e63
Hash.Type......: MD5
Time.Started...: Mon May  6 18:27:36 2013 (4 days, 0 hours)
Time.Estimated.: > 10 Years
Speed.GPU.#1...:  1248.2M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 433747785318400/4533461702709235777 (0.01%)
Rejected.......: 0/433747785318400 (0.00%)
HWMon.GPU.#1...: -1% Util, 67c Temp, 36% Fan

Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a?a?a)
Hash.Target....: ffc67bb0648c6f880f100719b3442e63
Hash.Type......: MD5
Time.Started...: Mon May  6 18:27:36 2013 (6 days, 13 hours)
Time.Estimated.: > 10 Years
Speed.GPU.#1...:  1249.5M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 710475091558400/4533461702709235777 (0.02%)
Rejected.......: 0/710475091558400 (0.00%)
HWMon.GPU.#1...: -1% Util, 67c Temp, 36% Fan


Started: Mon May  6 18:27:36 2013
Stopped: Mon May 13 07:50:25 2013

real 9442m48.279s
user 24m9.631s
sys 13m39.319s

아, 이럴수가 6일이 넘었는데도 해독될 기미가 보이지 않아서 중도에 포기를 했습니다. 예상 기간은 10년 이상으로 나오네요. 제가 몇번 패스워드 관련해서 포스팅한적이 있는데, 왜 패스워드를 길게 사용해야 하는 이유가 여기서 나오지요 ? :-)

HASH 해독 속도를 더 높일 수는 없을까요? 더 많은 GPU 를 이용하면 되겠지요. 일전에 소개해 드린 분산환경을 이용할수도 있고 여기서는 GPU 1개를 더 추가하여 2개를 가지고 한번 테스트해 보았습니다. 아래 그림과 같이 2개의 그래픽 카드를 황금색으로 보이는 케이블로 연결했습니다. Nvidia 에서는 SLI 기술이라고 합니다.


2개의 GPU 를 이용해 8 자리 패스워드 해독을 해 보겠습니다.

$ time ./cudaHashcat-plus64.bin -m0 -a 3 --force tt ?a?a?a?a?a?a?a?a
cudaHashcat-plus v0.14 by atom starting...

Hashes: 1 total, 1 unique salts, 1 unique digests
Bitmaps: 8 bits, 256 entries, 0x000000ff mask, 1024 bytes
Workload: 256 loops, 80 accel
Watchdog: Temperature abort trigger set to 90c
Watchdog: Temperature retain trigger set to 80c
Device #1: GeForce GTX 660 Ti, 2047MB, 1045Mhz, 7MCU
Device #2: GeForce GTX 660 Ti, 2047MB, 1045Mhz, 7MCU
Device #1: Kernel ./kernels/4318/m0000_a3.sm_30.64.ptx
Device #2: Kernel ./kernels/4318/m0000_a3.sm_30.64.ptx

[s]tatus [p]ause [r]esume [b]ypass [q]uit => s
Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a)
Hash.Target....: 8ebf50fe1d60d34fba86bf48cbec7f3b
Hash.Type......: MD5
Time.Started...: Mon May 13 10:31:41 2013 (3 secs)
Time.Estimated.: Wed Jun 12 21:23:23 2013 (30 days, 10 hours)
Speed.GPU.#1...:  1529.8M/s
Speed.GPU.#2...:  1547.9M/s
Speed.GPU.#*...:  3077.7M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 9615441920/6634204312890625 (0.00%)
Rejected.......: 0/9615441920 (0.00%)
HWMon.GPU.#1...: -1% Util, 72c Temp, 48% Fan
HWMon.GPU.#2...: -1% Util, 71c Temp, 46% Fan

[s]tatus [p]ause [r]esume [b]ypass [q]uit => s
Session.Name...: cudaHashcat-plus
Status.........: Running
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a)
Hash.Target....: 8ebf50fe1d60d34fba86bf48cbec7f3b
Hash.Type......: MD5
Time.Started...: Mon May 13 10:31:41 2013 (18 secs)
Time.Estimated.: Sat Jun  8 09:35:02 2013 (25 days, 23 hours)
Speed.GPU.#1...:  1530.1M/s
Speed.GPU.#2...:  1547.8M/s
Speed.GPU.#*...:  3077.9M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 55123640320/6634204312890625 (0.00%)
Rejected.......: 0/55123640320 (0.00%)
HWMon.GPU.#1...: -1% Util, 72c Temp, 48% Fan
HWMon.GPU.#2...: -1% Util, 72c Temp, 47% Fan

8ebf50fe1d60d34fba86bf48cbec7f3b:packetin  
                                           
Session.Name...: cudaHashcat-plus
Status.........: Cracked
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a)
Hash.Target....: 8ebf50fe1d60d34fba86bf48cbec7f3b
Hash.Type......: MD5
Time.Started...: Mon May 13 10:31:41 2013 (8 mins, 9 secs)
Speed.GPU.#1...:  1530.3M/s
Speed.GPU.#2...:  1546.9M/s
Speed.GPU.#*...:  3077.3M/s
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 1503071682560/6634204312890625 (0.02%)
Rejected.......: 0/1503071682560 (0.00%)
HWMon.GPU.#1...: -1% Util, 70c Temp, 51% Fan
HWMon.GPU.#2...: -1% Util, 70c Temp, 50% Fan

Started: Mon May 13 10:31:41 2013
Stopped: Mon May 13 10:39:51 2013

real 8m9.412s
user 0m3.232s
sys 0m1.952s

실행될 때 GPU 가 추가로 하나 더 잡혀서 나오는 것을 볼 수 있고요, 각 GPU 속도가 대략 15XXM/s 이고 합쳐서 3077M/s 를 처리가 가능합니다. 1개 이용했을때 보다는 분명히 속도가 2배 가까이 향상되었고 결과도 그렇게 나왔습니다. 1개의 GPU 를 이용했을 경우는 16분이 걸렸는데, 2개의 GPU 를 이용했더니 그 반인 8분으로 줄었습니다.
분명 2개를 사용하니 효과는 확실히 입증되었습니다.

속도도 2배 빨라졌으니 자릿수를 한자리만 늘려서 9 자리로 테스트 해 보겠습니다.

Session.Name...: cudaHashcat-plus
Status.........: Aborted
Input.Mode.....: Mask (?a?a?a?a?a?a?a?a?a)
Hash.Target....: 8ebf50fe1d60d34fba86bf48cbec7f3b
Hash.Type......: MD5
Time.Started...: Mon May 27 08:15:06 2013 (2 hours, 10 mins)
Time.Estimated.: Sun May 30 14:40:52 2021 (8 years, 3 days)
Speed.GPU.#1...:  1239.5M/s
Speed.GPU.#2...:  1254.7M/s
Speed.GPU.#*...:  2494.2M/s
Recovered......: 0/1 (0.00%) Digests, 0/1 (0.00%) Salts
Progress.......: 19528334622720/630249409724609375 (0.00%)
Rejected.......: 0/19528334622720 (0.00%)
HWMon.GPU.#1...: -1% Util, 67c Temp, 51% Fan
HWMon.GPU.#2...: -1% Util, 70c Temp, 50% Fan

Started: Mon May 27 08:15:06 2013
Stopped: Mon May 27 10:25:37 2013

real 130m31.495s
user 0m40.211s
sys 0m23.233s

2시간 정도 돌려 보고 포기를 했습니다. 예상 시간이 8년으로 나오네요. 8자리와 9자리의 차이가 이렇게 큽니다.  :-)

간단한 GPU 해쉬 사용기는 여기서 마무리 하고요, 패스워드 해쉬가 더 궁금하신 분들은 다음 글들을 참고하세요.

2013년04월10일 25개의 GPU 를 이용해 6시간안에 윈도우 패스워드를 깨트린다고 ?
2013년03월13일 15기가의 1,493,677,782 패스워드 단어 사전 공개
2011년07월14일 분산 기반의 CPU/GPU 해쉬 크랙 프로젝트 'Durandal'
2010년09월15일 8자리 패스워드는 저리가~ 12자리 패스워드를 사용하자 
2010년11월23일 당신의 패스워드는 안전한가? 클라우드 기반 패스워드 크랙킹
2010년12월01일 자바스크립트기반의 분산 해쉬 크랙킹

이상 Rigel 이었습니다.