반응형

필자는 pcap 라이브러리를 사용하며 다양한 프로그램을 구현해본 경험이 있다.

최근 python으로도 pcap 라이브러리가 존재한다는 것을 알게되었다.

바로 PyPCAP인데, 자료가 많지 않더라. 공부해보자.


1. PyPCAP?

pypcap을 이야기하기 전에 pcap에 대해 먼저 알아야한다.

 

pcap이란 Packet Capture의 약자인데, 네트워크상의 패킷을 캡쳐하기 위한 API이다.

윈도우는 Winpcap, 리눅스에선 libpcap을 사용하여 이용 가능하다.

 

pypcap은 말그대로 python 버전의 pcap 라이브러리이다.

이를 이용하여 python 환경에서 네트워크 트래픽을 손쉽게 캡쳐하고, 분석 가능할 수 있다.

 

*공식 문서와 설명은 다음 링크에 있다.




2. 사용법

pypcap을 사용하기 위해선 pypcap을 먼저 설치해야한다.

이후 pcap을 import하여 사용하면 된다.

 

1. 설치

pip intall pypcap

  • python3의 경우 pip3 install pypcap
  • libpcap-dev, python-dev 패키지 의존

 

2. 사용법

import pcap




3. 실습/예제

이제 pypcap을 이용하여 간단한 코딩을 진행하자.

 

네트워크 패킷을 캡쳐하게 되면 호스트에선 Ethernet Header의 MAC Frame 부분부터 잡기 시작한다.

아래와 같이 첫 6바이트는 Destination의 MAC 주소를 가리키고, 다음 6바이트는 Source의 MAC 주소를 가리킨다.

 

다음은 Destination MAC주소와 Source MAC 주소를 출력하는 코드의 예문이다.

 

import pcap #pypcap 라이브러리

sniffer = pcap.pcap(name=None, promisc=True, immediate=True, timeout_ms=50)

for ts, pkt in sniffer:
    print('Dst MAC - ', end='', flush=True)
    print(':'.join('%02X' % i for i in pkt[0:6])) #패킷의 0번부터 5번 바이트까지 출력
    print('Src MAC - ', end='', flush=True)
    print(':'.join('%02X' % i for i in pkt[6:12])) #패킷의 6번부터 11번 바이트까지 출력
    print()

 

위와 같이 매우 짧은 코드로 잡힌 패킷의

출발지 맥주소와 도착지 맥주소를 출력할 수 있다.

 

코드를 잠시 살펴보자.

 

  • sniffer = pcap.pcap(name = None, promisc = True, immediate = True, timeout_ms = 50)
    • name = None > 디바이스 이름이다. None을 두면 디폴트값이 들어가게 되고, 작은따옴표 안에 직접 디바이스 명을 넣어줄 수 있다.
    • promisc = True > 프리큐어스(무차별) 모드이다. 해당 옵션을 True, 곧 사용하겠다는 뜻이다. 해당 옵션으로 모든 패킷을 캡쳐 가능하다.
    • immediate = True > immediate 옵션이다. 해당 옵션을 True로 설정하여 지연문제를 없앨 수 있다.
    • timeout_ms = 50 > 말그대로 타임아웃 시간이다. ms단위로 50이므로 0.05초로 설정하였다.
    • 해당 return 값을 sniffer에 반환한다.

print(sniffer)

  • for ts, pkt in sniffer
    • sniffer 객체의 첫번째 값은 timestamp, 두번째 값은 packet으로 반복문을 돌겠다는 의미이다.
    • 이후 pkt[idx] 형식으로 네트워크 패킷의 특정 위치 인덱스 값을 가져올 수 있다.



 

4. 응용

pypcap은 dpkt나 socket 모듈 등과 함께 편리하게 사용 가능하다.

다음은 dpkt 모듈을 이용하여 Ethernet의 정보를 파싱하여 출력하는 예문이다.

 

import pcap
import dpkt

sniffer = pcap.pcap(name='eth0', promisc=True, immediate=True, timeout_ms=50)
sniffer.setfilter('tcp and port 443')

def mac_addr(address):
    return ':'.join('%02X' % dpkt.compat.compat_ord(b) for b in address)

for ts, pkt in sniffer:
    eth = dpkt.ethernet.Ethernet(pkt)
    #ip = eth.data
    #tcp = ip.data
    print('Ethernet INFO - ', mac_addr(eth.dst), mac_addr(eth.src), eth.type)
  • eth0 디바이스를 이용하여 캡쳐를 진행하고,
  • setfilter() 함수를 통해 tcp 패킷과 443번 포트를 필터링
  • 이후 dpkt의 Ethernet 클래스로 ethernet 부분을 파싱
  • 해당 함수의 변수를 사용해 원하는 값을 출력

 

 

*eth.data, ip.data 등을 이용해 IP와 TCP Header에 대한 파싱도 손쉽게 가능하다.



4. 마무리

위와 같이 해당 모듈을 이용해 자신이 원하는 대로 네트워크 패킷을 캡쳐, 분석 가능하다.

 

  • 느낀점
    • C++보다 훨씬 짧은 코드로 원하는 결과를 표현 가능
    • python의 장점을 잘 살린 pcap 모듈
    • 하지만 관련 자료가 많지 않아 해당 라이브러리의 공식 문서를 찾는 수고가 필요

 

계속해서 공부하다보면 네트워크를 이용하는 프로그램을 손쉽게 만들 수 있게 될 것이다.


(이렇게 한글로 된 pypcap 자료 갯수에 이바지하였다.)

반응형

'Programming > Network' 카테고리의 다른 글

[소켓 프로그래밍] TCP Echo-Client, Server 구현  (0) 2020.06.09

+ Recent posts