Network

pcap(Packet Capture, 패킷 캡처)

hunger626 2025. 7. 18. 16:27

Overview

pcap에 대한 설명과 linux 환경에서 libpcap을 사용해 패킷 스니핑(Packet Sniffing)을 하는 예제를 기술한다.

 

 

pcap

  • 네트워크 트래픽을 캡처하고 저장하기 위한 파일 형식 및 API를 의미한다.
  • Packet Capture의 약자로 Wireshark, tcpdump 등을 통해서 패킷을 저장하게 되면 pcap 형식으로 파일이 저장되기 때문에 네트워크 오류 발생 혹은 네트워크 프로그램을 구현할 때 데이터 확인 및 분석을 위해 사용된다.

 

Packet

pcap을 확인하기 위해서는 Packet과 OSI 7계층에 대한 내용을 이해할 필요가 있는데 아래 링크를 통해 확인하자.

https://en.wikipedia.org/wiki/Network_packet

 

Network packet - Wikipedia

From Wikipedia, the free encyclopedia Formatted unit of data carried by a packet-switched network In telecommunications and computer networking, a network packet is a formatted unit of data carried by a packet-switched network. A packet consists of control

en.wikipedia.org

https://ko.wikipedia.org/wiki/OSI_%EB%AA%A8%ED%98%95

 

OSI 모형 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. OSI 모형의 통신 (3-5계층의 예) OSI 모형(Open Systems Interconnection Reference Model)은 국제표준화기구(ISO)에서 개발한 모델로, 컴퓨터 네트워크 프로토콜 디자인과 통신

ko.wikipedia.org

 

pcap Programming

libpcap을 통해 개발자는 패킷을 캡처하고, 원하는 방식으로 분석/필터링/처리/저장 등을 하기 위한 프로그램을 구현 가능하다.

 

C++을 통해 TCP 패킷만 출력 해 주는 프로그램 예제를 만들어보자.

 

libpcap 설치

sudo apt update
sudo apt install libpcap-dev

 

설치 후 C/C++ 에서 #include <pcap.h>를 통해 사용 가능하다.

 

소스코드 예제

#include <pcap.h>
#include <iostream>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

// 패킷을 캡처할 때 호출되는 콜백 함수
void packet_handler(u_char *userData, const struct pcap_pkthdr* pkthdr, const u_char* packet) 
{
    // Ethernet 헤더는 14바이트
    const struct ip* ip_header = (struct ip*)(packet + 14); // IP 헤더 위치
    int ip_header_length = ip_header->ip_hl * 4;

    // IP 프로토콜이 TCP일 경우에만 처리(IP 프로토콜에서 TCP에 해당하는 값는 6)
    if (ip_header->ip_p == IPPROTO_TCP) 
    {
        const struct tcphdr* tcp_header = (struct tcphdr*)(packet + 14 + ip_header_length);

        // 출력: IP 주소와 포트 정보
        std::cout << "TCP Packet: "
                  << inet_ntoa(ip_header->ip_src) << ":" << ntohs(tcp_header->th_sport)
                  << " -> "
                  << inet_ntoa(ip_header->ip_dst) << ":" << ntohs(tcp_header->th_dport)
                  << std::endl;
    }
}

int main() 
{
    // error 메시지 버퍼
    char errbuf[PCAP_ERRBUF_SIZE];

    // 사용할 네트워크 장치 이름
    const char* device = "eth0";

    // 장치를 열어 패킷을 캡처할 준비
    pcap_t* handle = pcap_open_live(device, BUFSIZ, 1, 1000, errbuf);
    if (handle == nullptr) 
    {
        // 장치 열기에 실패한 경우 에러 메시지 출력(예:sudo 권한 없이 실행하면 해당 오류 출력)
        std::cerr << "pcap_open_live() 실패: " << errbuf << std::endl;
        return 1;
    }

    std::cout << "eth0 - TCP 패킷 수신 중..." << std::endl;

    // 캡처 루프 시작: 패킷이 수신될 때마다 packet_handler 호출
    pcap_loop(handle, 0, packet_handler, nullptr);

    // 종료
    pcap_close(handle);

    return 0;
}

 

빌드 명령 예제

g++ -o test_program main.cc -lpcap

 

핵심

네트워크에서 내가 원하는 패킷만 확인하거나 처리를 하기 위해서는 OSI 7계층에서 어떤 계층의 헤더 값에서 데이터를 확인해야 할지는 많은 공부가 필요하기 때문에 이에대한 사전 학습이 필요할 것이다.

위 예제에서는 TCP 패킷만 출력하기 위해 네트워크 계층IP 헤더에서 protocol 값이 tcp인지를 확인하는 부분이 존재한다.

 if (ip_header->ip_p == IPPROTO_TCP)

이를 통해서 원하는 패킷만을 사용자는 출력하여 확인이 가능하게 된다.

 

 

결론

네트워크에 대한 공부를 우선적으로 하자

'Network' 카테고리의 다른 글

Raw Socket  (2) 2025.08.15
Snort  (5) 2025.07.26
Netfilter  (7) 2025.07.16
VLAN (Virtual LAN)  (0) 2025.06.09
CommonAPI(4) - Service / Client  (0) 2025.05.27