2012년 12월 31일 월요일

패킷인사이드 3주년, 새해 복 많이 받으세요.


벌써 블로그를 시작한지 3년이 되었습니다. 패킷 관련 정보를 많이 써 온것 같은데도, 아직 여러분들에게 소개할 내용이 많이 남아 있네요.

그만큼 이쪽도 빠르게 변화하고 있다보니 새로운 내용도 많고, 아직도 배워야 할게 많은것 같은 느낌입니다. 찾고 찾다 보면 몰랐던 내용도 많고 인터넷은 정말 드넓다는 것을 다시 한번 배웁니다. 물론, 매번 느끼지만 말이죠 :-)

내년에도 계속 패킷인사이드의 글들은 이어집니다. 언제까지 이어 나갈 수 있을까는 모르겠지만, 한번 끝까지 해 봐야 겠죠. 장기적인 계획으로는 글들이 충분히 모아지면 책으로도 엮어볼까 합니다. 그 시점이 언제일지는 모르겠지만, 제 스스로가 어느정도는 만족해야 겠지요.

둘째 아이도 태어나고 개인적으로도 바쁜 나날을 보내고 있다보니, 글 쓰는 것도 점점 어려워 지고 있습니다. 매년 쓰여지는 포스팅 건수가 줄어들고 있다는 것이 증명해 주고 있습니다. 하하~

이제 내년 까지는 몇 시간 남지 않았습니다. 여러분들 마무리 잘 하시고요, 2013년 한해는 모두 복 많이 받으시고 계획했던 모든 것을 이루길 기원할께요.

/ 패킷인사이드 주인장 드림.

2012년 12월 27일 목요일

콘솔기반의 실시간 웹 로그 분석기 - GoAccess


콘솔기반의 괜챦은 웹 로그 분석기를 보게 되어 소개한다. 회사분의 소개로 보게되었는데, 콘솔기반 치고는 깔끔하게 만들어져 있다. 일반적인 웹 로그 분석 기능은 모두 포함하고 있으며, 아파치의 CLF 또는 XLF 포맷 그리고 W3C 포맷을 지원한다.



실시간으로 로그분석을 해서 볼 수 있다는 점도 장점이고, HTML 리포트 형태로 출력도 지원한다. 속도는 대략 초당 10만 라인 정도 ( 인텔 제온 CPU 2.4 GHz 2GB RAM) 로 빠르게 동작한다. 사용방법도 아주 간단하여 다음과 같이 사용하면 된다.

# goaccess -f /data/apache/logs/access.log -a

컴파일 하기 위해서는 ncurses 라이브러리와 GLib >= 2.0.0 이상이 필요하다. 필요에 따라 MaxMind 사의 GeoIP 도 필요하다.

파일 다운로드 및 추가 정보는 다음 사이트에서 얻을 수 있다.

http://goaccess.prosoftcorp.com/

Curses 를 이용한 프로그램 작성에도 해당 소스를 활용하면 도움이 될 것같다.


2012년 12월 14일 금요일

리눅스 3.7 커널 릴리즈: TCP Fast Open, vxLan 지원

리눅스 3.7 커널이 12월10일에 릴리즈 되었다. 이번 릴리즈는 ARM 64비트 아키텍쳐를 지원하고 서명된 커널 모듈, Btrfs 파일시스템 업데이트, strace 후의 새로운 "perf trace" 도구, 서버측면의 TCP Fast Open 기능, 안정적인 NFS 4.1 등 많은 기능이 업데이트 되었다.

눈에 띄는 변화는 ARM 멀티 플랫폼과 64 비트 지원이다. 싱글 ARM 커널 이미지로 여러 하드웨어에서 부팅이 가능해 졌다. ARM 플랫폼을 지원하도록 배포할때 더욱 쉬워지게 된 것이다.

보안적으로는 서명된 커널모듈을 지원해서, 올바르게 서명되지 않은 모듈은 커널에 로드하지 못하도록 한 것이다. 이 기능은 루트킷등을 이용해 모듈을 추가할 수 없도록 해 보안적으로도 상당히 유용한 기능이다.

네트워크 관점으로 보면 서버 측면에서 TCP Fast Open 을 지원한다. 이미 이 기능은 3.6 커널에서 추가된 것이나 이번 릴리즈는 서버측을 지원하는 것이다. TCP 연결을 맺을때 "Fast Open" 은 더욱 최적화하여 페이지 로드시 4% ~ 41% 정도 속도 향상을 가져온다. 물론 사용되는 환경마다 다르지만 말이다. 이 기능은 추후 블로그에서 다시 한번 소개할 예정이다.

또한 SMBv2 를 지원하고(시험적인 기능) NFS 4.1 이 오랜 기간을 끝내고 드디어 안정 버전으로 릴리즈 되었다. NFS 4.1 의 주 기능은 pNFS 라 하여 패러랠 NFS 을 지원한다. 이로 인해 분산된 여러 서버들 간의 파일시스템에 패러랠한 접근이 가능하다. UDP 프로토콜을 통해 레이어 2 이더넷 패킷을 전송할 수 있는 터널링 프로토콜 vxlan 을 지원한다. vxlan 은 가상화된 환경에서 터널링된 네트워크 환경을 지원하는데 주로 이용된다. VLAN 은 4096 개로 제한되었지만 이것은 24bit 로 확장되어 훨씬 많은 개수를 지원하게 된다. 이것또한 블로그에서 추후 언급할 예정이다.

마지막으로 네트워킹 관점의 변화된 주요 내용은 다음과 같다

  • loopback: set default MTU to 64K (commit)
  • Providing protocol type via system.sockprotoname xattr of /proc/PID/fd entries (commit)
  • Use a per-task frag allocator (commit)
  • Netfilter
    • Add protocol-independent NAT core (commit)
    • Add IPv6 MASQUERADE target (commit)
    • Add IPv6 NETMAP target (commit)
    • Add IPv6 REDIRECT target (commit)
    • Add IPv6 NAT support (commit)
    • Support IPv6 in FTP NAT helper (commit)
    • Support IPv6 in IRC NAT helper (commit)
    • Support IPv6 in SIP NAT helper (commit)
    • Support IPv6 in amanda NAT helper (commit)
    • Add stateless IPv6-to-IPv6 Network Prefix Translation target (commit)
    • Remove xt_NOTRACK (commit)
  • Near Field Communication (NFC): Add an Link Layer Control (LLC) Core layer to HCI (commit), add an shdlc llc module to llc core(commit), LLCP raw socket support (commit)
  • bonding: support for IPv6 transmit hashing (and TCP or UDP over IPv6), bringing IPv6 up to par with IPv4 support in the bonding driver (commit)
  • team: add support for non-Ethernet devices (commit)
  • gre: Support GRE over IPv6 (commit), add GSO support (commit), add GRO capability (commit)
  • packet: Diag core and basic socket info dumping (commit)
  • ethtool: support for setting MDI/MDI-X state for twisted pair wiring (commit)
  • ppp: add 64-bit stats (commit)
  • Add generic netlink support for tcp_metrics (commit)


[참고]
1. 리눅스 커널 3.7 릴리즈
http://kernelnewbies.org/Linux_3.7

2012년 12월 12일 수요일

vi 에서 ^M 문자열 지우기와 유닉스 포맷으로 변경

윈도우에서 만들어진 데이터를 가져와 *NIX 시스템에서 사용하다 보면 윈도우 캐리지 리턴 값이 들어가 있는 경우가 있다. 해당 파일을 열어 보면,

blablabla^M
blabla^M

와 같이 끝에 ^M 에 붙어 있는 것이다. 쉽게 사용할 수 있는 방법은 vi 에디터에서

:%s/^M//g

로 다 제거해 버리면 된다. 여기서 주의할 점은 ^M 이 그냥 입력하면 안되고 Ctrl + v + m 으로 입력해 주어야 한다.

이외 텍스트파일을 검색해서 사용하려고 하는데, 이상하게도 해당 데이터가 들어있는데도 불구하고 검색이 되지 않는 것이었다. vi 로 열어보니 아래와 같이 나온다.

" test-dataset.txt" [dos] 999715L, 16340756C

[dos] 라고 표시가 되고 있다. 이럴때는

:set ff=unix

로 설정하고 w 로 저장해 주면 된다.

윈도우와 *NIX 시스템 사이에 데이터를 주고 받는 과정에서 쉽게 발생될 수 있는 일이므로 알아두자.

2012년 12월 7일 금요일

IP 주소 (ARP Conflict) 충돌에 대한 이야기

네트워크 안에서 한번쯤 IP 충돌을 경험해 본 사람이 있을것이다. 많은 경우는 같은 IP 를 서로 설정해서 사용한 경우이다.

그런데 특정 시스템 접속시 연결이 잘 되다가도 가끔 연결이 안되는 이상한 현상이 발생하였다. 그렇다고 인터페이스에 같은 IP 설정은 더더욱 아니었다. 맥 인증 장비에서 IP 충돌이 난다는 이슈를 접하고 해당 네트워크 대역에 대해서 ARP 스캐닝을 해 보았다.

ARP 스캐닝에는 arp-scan 을 이용하였으며,

# apt-get install arp-scan

으로 쉽게 설치가 가능하다.

이더넷 인터페이스를 지정하기 위하여 -I 를 사용하였고 특정 대역을 넣어주었다. -l 옵션을 사용하면 인터페이스에 설정된 로컬 네트워크 주소를 사용한다. 만약 서브넷이 255.255.0.0 이었다면 B 클래스 대상으로 스캐닝이 될 것이다.

# arp-scan -I eth0 192.168.11.0/24
ioctl: Cannot assign requested address
WARNING: Could not obtain IP address for interface eth0. Using 0.0.0.0 for
the source address, which is probably not what you want.
Either configure eth0 with an IP address, or manually specify the address
with the --arpspa option.
Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.6 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
192.168.11.39   00:14:22:xx:xx:xx   Dell Inc.
192.168.11.52   00:14:22:xx:xx:xx   Dell Inc.
192.168.11.91   00:04:75:xx:xx:xx  3 Com Corporation
192.168.11.110  00:25:64:xx:xx:xx   (Unknown)
192.168.11.94   08:00:20:xx:xx:xx  SUN MICROSYSTEMS INC.
192.168.11.125  00:1e:c9:xx:xx:xx   (Unknown)
192.168.11.207  00:22:19:xx:xx:xx (Unknown)
192.168.11.208  xx:xx:xx:fa:a8:0d   (Unknown)
192.168.11.209  d4:be:d9:xx:xx:xx   (Unknown)
192.168.11.210  xx:xx:xx:fa:a8:0d   (Unknown)
192.168.11.210 xx:xx:xx:fa:10:1c   (Unknown) (DUP: 2)
192.168.11.214  78:2b:cb:xx:xx:xx (Unknown)
192.168.11.215  78:2b:cb:xx:xx:xx  (Unknown)
[삭제 - 일부는 xx:xx:xx 처리 ]

38 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.6: 256 hosts scanned in 1.334 seconds (191.90 hosts/sec).  38 responded

결과와 같이 192.168.11.210 이 2개의 맥 주소를 가지고 있는 것으로 나타난다. fa:a8:0d 와 fa:10:1c 이다. 192.168.11.208 번에 할당된 맥 주소는 fa:a8:0d 이다. 즉, 210 번 IP 에 fa:a8:0d 를 가져서는 안되는 것이다. 이러니 어떤 경우에는 접속이 되다가도 갑자기 끊어져서 접속이 안된다든지의 상황이 발생하는 것이다.

192.168.11.208 ,210 인터페이스를 살펴보았으나 IP 중복 설정은 보이지 않는다. 그럼 도대체 어디서 이게 나타나는 것인가? 일단 208 번이 의심된다. 208 번에서 해당 맥을 가지고 있는 것으로 추정되고 시스템 전체에서 해당 IP 설정이 없는지 찾아보기로 하였다.

# find / -exec grep "11.210" {} \;

11.210 번 문자열을 grep 으로 찾아보았는데, 하나 나타나는 것이 있다. keepalived 설정 파일이었다. 이때 바로 생각이 나는 것이었다. 해당 장비를 사용하기전 로드발랜싱 테스트를 위하여 잠깐 설정을 한적이 있었고, 잊고 있었던 것이다.

/etc/keepalived/keepalived.conf

해당 파일을 살펴보니 역시나 192.168.11.210 IP 가 설정되어 있었다.

해당 데몬을 disable 하고서는 다시 정상으로 돌아왔다. 역시나, 분명 어딘가에는 문제점이 존재한다는 사실!

IP 충돌(ARP Conflict)의 많은 경우는 직접 IP 를 동일하게 설정하거나 또는 필자가 경험했던 것과 같이 관련 소프트에어의 설정에 의한 것 그리고 ARP 테이블에서 지워지지 않고 잘못된 맥 정보를 가지고 있거나 중간 단계의 장비에 의한 문제정도로 생각된다.

/Rigel

[참고]
1. IPv4 Address Conflict Detection
http://tools.ietf.org/html/rfc5227

2012년 12월 5일 수요일

프로세스별 네트워크 활동 추적은 어떻게?

tcpdump, wireshark 도구를 이용해 쉽게 네트워크 트래픽 상태를 감시할 수 있다. 그런데, 어떤 프로세스가 해당 트래픽과 연관되어 있는지 알고자 하는 경우에는 어떻게 해야 하는가 ? 윈도우 사용자라면 ProcessExplorer 로 간단하게 연결 형태 정도를 확인할 수 있고, MS 사의 네트워크 분석기를 이용하면 쉽게 프로세스별 트래픽을 모니터링 할 수 있다.

[참고]

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


리눅스 환경에서는 어떻게 살펴볼까? MS 네트워크 분석기만큼 편리한 것은 없어 보인다. 일단 lsof 로 간단하게 네트워크 연결 상태를 확인해 볼 수 있다.

# lsof -i
로 네트워크 상황을 볼 수 있고 -i :80 , -i @packetinside.com 과 같이 포트 번호 또는 호스트로도 제한할 수 있다. 비슷한 기능의 명령어로는

# netstat -a -p

정도가 될 것같다. 이외 lsof 로 해당 네트워크 프로그램의 오픈된 파일 정보등도 더 살펴볼 수 있다.

$ ping www.packetinside.com
PING ghs.l.google.com (74.125.128.121) 56(84) bytes of data.
64 bytes from hg-in-f121.1e100.net (74.125.128.121): icmp_req=1 ttl=43 time=173 ms
64 bytes from hg-in-f121.1e100.net (74.125.128.121): icmp_req=2 ttl=43 time=183 ms

# ps -ef | grep ping
test   8976  8842  0 08:10 pts/8    00:00:00 ping www.packetinside.com
root      8991  8764  0 08:13 pts/7    00:00:00 grep --color=auto ping

root@banana:~# lsof -p 8976
lsof: WARNING: can't stat() fuse.gvfs-fuse-daemon file system /home/test/.gvfs
      Output information may be incomplete.
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
ping    8976 test  cwd    DIR    8,6     4096 16777218 /home/test
ping    8976 test  rtd    DIR    8,6     4096        2 /
ping    8976 test  txt    REG    8,6    35712 16515194 /bin/ping
ping    8976 test  mem    REG    8,6   101192  6816351 /lib/x86_64-linux-gnu/libresolv-2.13.so
ping    8976 test  mem    REG    8,6    27032  6816344 /lib/x86_64-linux-gnu/libnss_dns-2.13.so  
ping    8976 test  mem    REG    8,6    10368  6815809 /lib/libnss_mdns4_minimal.so.2
ping    8976 test  mem    REG    8,6    51736  6816363 /lib/x86_64-linux-gnu/libnss_files-2.13.so
ping    8976 test  mem    REG    8,6  1694008  6816367 /lib/x86_64-linux-gnu/libc-2.13.so
ping    8976 test  mem    REG    8,6   141088  6816365 /lib/x86_64-linux-gnu/ld-2.13.so
ping    8976 test    0u   CHR  136,8      0t0       11 /dev/pts/8
ping    8976 test    1u   CHR  136,8      0t0       11 /dev/pts/8
ping    8976 test    2u   CHR  136,8      0t0       11 /dev/pts/8
ping    8976 test    3u   raw             0t0   243673 00000000:0001->00000000:0000 st=07
root@banana:~#

ping 을 하는 프로세스를 찾고 lsof -p 옵션으로 pid 값을 주고 살펴보면 추가 정보를 얻을 수 있다.

또 strace 를 이용하면 해당 프로세스에서 네트워크 부분만을 확인할 수 도 있다. strace 는 시스템 콜 또는 시그널을 추적할 수 있는데 다음과 같은 몇 가지 옵션을 이용하면 쉽게 확인이 가능하다.

-p : 프로세스 PID 
-f : 현 프로세스가 fork 하는 자식프로세스까지 추적
-e : 지정한 시스템 콜만 추적 , 예를들면 trace=open,close,read,write 는 4개의 시스템 콜만 추적

# strace -p 9016  -f -e trace=network
Process 9016 attached - interrupt to quit
recvmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("74.125.128.121")}, msg_iov(1)=[{"E\0\0T\337B\0\0+\1/4J}\200y\254\24\n(\0\0\10q#8\0&\332\204\276P"..., 192}], msg_controllen=32, {cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=0x1d /* SCM_??? */, ...}, msg_flags=0}, MSG_DONTWAIT) = 84
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.1.1")}, 16) = 0
sendto(4, "\277\263\1\0\0\1\0\0\0\0\0\0\003121\003128\003125\00274\7in-a"..., 45, MSG_NOSIGNAL, NULL, 0) = 45
recvfrom(4, "\277\263\201\200\0\1\0\1\0\4\0\4\003121\003128\003125\00274\7in-a"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.1.1")}, [16]) = 225
sendmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("74.125.128.121")}, msg_iov(1)=[{"\10\0wj#8\0'\333\204\276P\0\0\0\0\374\215\10\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64}], msg_controllen=0, msg_flags=0}, MSG_CONFIRM) = 64

위와 같이 ping 프로그램이 이용하는 네트워크 시스템 콜을 추적한다.

또는 수동적이지만 프로그램을 동작시키고 해당 소스 포트 또는 목적지 IP , 포트 정보등을 함께 이용하여 필터를 하여 트래픽을 덤프할 수도 있겠다. 이외 nethogs 라는 도구를 이용하면 프로세스별 트래픽양을 확인할 수 있다.

# apt-get install nethogs
# nethogs eth0

NetHogs version 0.7.0

  PID USER     PROGRAM                                 DEV        SENT      RECEIVED
2088  test  pidgin                                  eth0       0.087       1.150 KB/sec
2349  test  remmina                                 eth0       0.077       0.110 KB/sec
2308  test  /usr/lib/firefox/firefox                eth0       0.026       0.026 KB/sec
2986  test  ssh                                     eth0       0.000       0.000 KB/sec
5979  test  ssh                                     eth0       0.000       0.000 KB/sec
2145  test  /opt/google/chrome/chrome               eth0       0.000       0.000 KB/sec
1792  test  ../google/chrome/chrome --type=service  eth0       0.000       0.000 KB/sec
0     root     unknown TCP                                        0.000       0.000 KB/sec

  TOTAL                                                           0.190       1.286 KB/sec

리눅스 환경에서는 윈도우에 비해 프로세스별 감시가 다소 불편한 부분이 있다. 특히 MS 사의 네트워크 분석기는 프로세스별 트래픽 추적을 할 수 있어 해당 기능이 가장 유용한 부분이기도 하다.

추후 리눅스 환경에서 프로세스별 추적에 좀더 유용한 도구가 있다면 다시 소개하도록 하겠다. 그리고 윈도우 사용자는 MS 사의 네트워크 분석기를 이용하면 도움이 될 것이다.