libpcapÀ» ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö
ÃÑ ÆäÀÌÁö ¼ö : 3224

Àüü ÇÔ¼ö/¿ë¾î»çÀü
Facebook Joinc ±×·ì   Joinc QA »çÀÌÆ®



joinc´Â Firefox¿Í chrome¿¡¼­ Å×½ºÆ® Çß½À´Ï´Ù. IE¿¡¼­´Â Å×À̺íÀÌ ±úÁö°Å³ª À̹ÌÁö°¡ º¸ÀÌÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ƯÈ÷ ±¸±Û DocsÀ̹ÌÁöÀÇ °æ¿ì ¿¢¹Úó¸®µÉ ¼ö ÀÖ½À´Ï´Ù.
Docbook ¿ø¹®
libpcap ¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö

libpcap ¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö

À± »ó¹è

dreamyun@yahoo.co.kr

교정 과정
교정 0.52003³â 1¿ù 28ÀÏ 21½Ã
ÃÖÃÊ ¹®¼­ ÀÛ¼º


1절. ¼Ò°³

À̹ø °­Á´ libpcap À» »ç¿ëÇÑ ÆÐŶ ĸÃç¿¡ ´ëÇÑ ³»¿ëÀÌ´Ù.


2절. Libpcap ±âº»

2.1절. Libpcap ¿¡ ´ëÇÏ¿©

Libpcap(ÀÌÇÏ pcap)Àº "Portable Packet Capturing Library"ÀÇ ÁÙÀÓ¸»À̸ç, ÇØ¼®±×´ë·Î "°£´ÜÇÏ°Ô ÆÐŶÀ» ĸÃÄÇϱâ À§ÇÑ ÇÔ¼ö¸ðÀ½(¶óÀ̺귯¸®)" ÀÌ´Ù.

¹°·Ð pcap ¿Ü¿¡µµ ÆÐŶĸÃĸ¦ À§ÇÑ µµ±¸µéÀÌ ÀÖ±â´Â ÇÏÁö¸¸, ´ëºÎºÐÀÇ °æ¿ì ¿î¿µÃ¼Á¦¿¡ Á¾¼ÓÀûÀÌ¿©¼­, ¿î¿µÃ¼Á¦º°·Î Äڵ带 ´Ù½Ã Â¥¾ß ÇÑ´Ù´Â ºÒÆíÇÔÀÌ ÀÖ´Ù. ´ëÇ¥ÀûÀÎ µµ±¸·Î´Â SOCK_PACKET, LSF, SNOOP, SNIT µîÀÌ ÀÖ´Ù.

ÀÌ¿¡ ºñÇØ pcap ´Â ¿î¿µÃ¼Á¦¿¡ »ó°ü¾øÀÌ ¹ü¿ëÀûÀ¸·Î »ç¿ë°¡´ÉÇÑ API¸¦ Á¦°øÇØÁÜÀ¸·Î, °ø¿ëÇÁ·Î±×·¥ ȤÀº °ø¿ë¶óÀ̺귯¸®ÀÇ Á¦ÀÛÀÌ °¡´ÉÇϵµ·Ï µµ¿ÍÁØ´Ù. ¶ÇÇÑ °£´ÜÇÏ°Ô »ç¿ë°¡´ÉÇÑ »ç¿ëÀÚ ·¹º§ ¶óÀ̺귯¸®ÀÌ´Ù.

libpcap ¸¦ ÀÌ¿ëÇÑ °¡Àå ´ëÇ¥ÀûÀÎ ÇÁ·Î±×·¥ÀÌ tcpdump ¿Í SAINT ¿Í °°Àº ÇÁ·Î±×·¥µéÀÌ´Ù.

¶ÇÇÑ »ó¿ë IDS [1] Á¦Ç°ÀÇ »ó´ç¼ö°¡ ÆÐŶºÐ¼®À» À§Çؼ­ libpcap À» »ç¿ëÇϰí ÀÖ´Ù.


2.2절. libpcap ÀÇ ¼³Ä¡

¿©·¯ºÐÀÌ Unix °è¿­ ¿î¿µÃ¼Á¦¸¦ »ç¿ëÇϰí ÀÖ´Ù¸é, °ÅÀÇ ´ëºÎºÐ tcpdump ¸¦ °ð¹Ù·Î »ç¿ëÇÒ¼ö ÀÖÀ»°ÍÀÌ´Ù. tcpdump ¸¦ »ç¿ëÇÒ¼ö ÀÖ´Ù´Â °ÍÀº ±× ±â¹ÝÀÌ µÇ´Â libpcap ¿ª½Ã ¼³Ä¡µÇ¾î ÀÖ´Ù´Â ¸»ÀÌ µÈ´Ù.

±×·¯³ª ¸¸¾àÀÇ °æ¿ì ¼³Ä¡°¡ µÇ¾î ÀÖÁö ¾Ê´Ù¸é tcpdump.org ¿¡¼­ ¹Þ¾Æ¼­ ÄÄÆÄÀÏÈÄ ¼³Ä¡Çϱ⠹ٶõ´Ù.

ÄÄÆÄÀÏ ÇϱⰡ ±ÍÂú´Ù¸é ±×¸®°í ·¹µåÇòÀ̳ª µ¥ºñ¾È °è¿­ÀÇ ¸®´ª½º »ç¿ëÀÚ¶ó¸é ÇØ´ç ÆÐŰÁö¸¦ ¹èÆ÷ÇÏ´Â ftp »çÀÌÆ®¿¡¼­ ´Ù¿î ¹Þ¾Æ¼­ ¼³Ä¡ÇÏ¸é µÈ´Ù. ¼Ö¶ó¸®½º ¿î¿µÃ¼Á¦ ¶ó¸é www.sunfreeware.com ¿¡¼­ ÆÐŰÁö¸¦ ¹Þ¾Æ¼­ ¼³Ä¡Çϱ⠹ٶõ´Ù.


2.3절. ÆÐŶ ĸÃÄÀÇ ±âº»ÀÌÇØ

ÆÐŶ ĸÃÄ´Â ³×Æ®¿÷ »ó¿¡¼­ µ¹¾Æ´Ù´Ï´Â ÆÐŶÀ» µé¿©´Ù º¸´Â °É ¸»ÇÑ´Ù. ÆÐŶ ĸÃĶó´Â ¾î°¨»ó ÆÐŶÀ» "Àâ´Â"°Ô ¾Æ´Ñ°¡ ¶ó°í »ý°¢ÇÒ¼ö ÀÖÁö¸¸, ÆÐŶÀ» "ÀâÁö"´Â ¾Ê°í ´ÜÁö µé¿©´Ù¸¸ º¼ »ÓÀÌ´Ù.

¸¸¾à ¿©·¯ºÐÀÇ È£½ºÆ®°¡ Æ÷ÇÔµÈ ³×Æ®¿÷À» °ü¸®ÇÏ´Â ¶ó¿ìÅͰ¡ ÀϹÝÀûÀÎ(½ºÀ§ÄªÀÌ ¾Æ´Ñ) ¶ó¿ìÅͶó¸é, ³»ºÎ·Î ÇâÇÏ´Â ¸ðµç ÆÐŶÀº ºê·Îµåij½ºÆÃ(Broadcasting) µÈ´Ù. ÀÌ´Â ½ºÀ§Äª ¶ó¿ìÅͰ¡ ¾Æ´ÑÇÑÀº ¸ðµç ·ÎÄÃ³×Æ®¿÷ÀÇ ÆÐŶÀ» µé¿©´Ù º¼¼ö ÀÖÀ½À» ÀǹÌÇϱ⵵ ÇÑ´Ù. ¾î¶µç À̰æ¿ì ¿î¿µÃ¼Á¦´Â Àڽſ¡°Ô µµÂøµÈ ÆÐŶÁß ¸ñÀûÁö°¡ ÀÚ½ÅÀÎ ÆÐŶ¸¸À» ó¸®Çؼ­ Application Layer ±îÁö ¿Ã·Á º¸³»°Ô µÈ´Ù.

libpcap À» »ç¿ëÇϸé ÀÌ·¯ÇÑ ÆÐŶÀÇ Ä¸Ãİ¡ °¡´ÉÇØÁø´Ù. ÀÎÅÍ³Ý »óÀÇ ÆÐŶÀº »ó´ë¹æ¿¡°Ô º¸³¾°æ¿ì encapuslation °úÁ¤À» °ÅÄ¡°í, ¹ÞÀº ÆÐŶ¿¡ ´ëÇØ¼­´Â demultiplexing °úÁ¤À» °ÅÄ£´Ù´Â °ÍÀ» ¾Ë°í ÀÖÀ»°ÍÀÌ´Ù - TCP/IP °³¿ä(3) Âü°í - libpcap À» »ç¿ëÇØ¼­ ĸÃÄÇÑ ÆÐŶÀº demultiplexing °úÁ¤À» °ÅÄ¡±â ÀüÀÇ ÆÐŶÀÌ´Ù. ÀÌ·¸°Ô ÇØ¼­ ĸÃÄÇÑ ÆÐŶÀº °¢ ÇÁ·ÎÅäÄÝ ´ÜÀ§·Î(±¸Á¶Ã¼) Àо ó¸®ÇÏ¸é µÈ´Ù. ´ÙÀ½Àº encapuslation&demultiplexing °úÁ¤ÀÌ´Ù.

그림 1. Encapuslation & demultiplexing


2.4절. ÆÐŶ ĸÃÄÀÇ ÀÀ¿ë

ÆÐŶ ĸÃÄ´Â ¿©·¯°¡Áö ¸ñÀûÀ¸·Î »ç¿ëµÉ¼ö ÀÖ´Ù. NIDS(Network Intrusion Detection System) ÇÁ·Î±×·¥ÀÌ °¡Àå ´ëÇ¥ÀûÀÎ ÀÀ¿ëÀ̸ç, ³×Æ®¿÷ Æ®·¡ÇÈ °¨½Ã, ³×Æ®¿÷ µð¹ö±ëÀ» À§ÇÑ ¿ëµµ·Î »ç¿ë°¡´ÉÇÏ´Ù.


3절. libpcap ÇÁ·Î±×·¡¹Ö

À̹øÀå¿¡¼­´Â libpcap ¿¡¼­ ÇʼöÀûÀ¸·Î »ç¿ëµÇ´Â Áß¿ä API ¿¡ ´ëÇØ¼­ ¾Ë¾Æº¼°ÍÀÌ´Ù.


3.1절. µð¹ÙÀ̽º&³×Æ®¿÷ Á¤º¸ °ü·Ã API

3.1.1절. int pcap_lookupnet()

int pcap_lookupnet(char *device, bpf_u_int32 *netp, 
               bpf_u_int32 *maskp, char *errbuf)
				

³×Æ®¿÷ µð¹ÙÀ̽º¿¡ ´ëÇÑ ³×Æ®¿÷ ¹× mask ¹øÈ£¸¦ µÇµ¹·ÁÁØ´Ù. ³×Æ®¿÷ ¹øÈ£´Â netp¿¡ mask ¹øÈ£´Â maskp¿¡ ÀúÀåµÈ´Ù. device´Â pcap_lookupdev µîÀ» ÅëÇØ ¾ò¾î¿Â ³×Æ®¿÷ µð¹ÙÀ̽º À̸§ÀÌ´Ù.

¿¡·¯°¡ ¹ß»ýÇÒ°æ¿ì -1 ÀÌ ¸®ÅϵǸç, ¿¡·¯ ³»¿ëÀÌ errbuf ¿¡ ÀúÀåµÈ´Ù.


3.1.2절. char* pcap_lookupdev

pcap_open_live() ¿Í pcap_lookupnet() ¿¡¼­ »ç¿ëÇϱâ À§ÇÑ ³×Æ®¿÷ µð¹ÙÀ̽º¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ µÇµ¹·ÁÁØ´Ù. ¼º°øÇÒ °æ¿ì "eth0", "eth1" °ú °°Àº À̸§À» µÇµ¹·ÁÁÖ¸ç ½ÇÆÐÇÒ°æ¿ì 0À» µÇµ¹·ÁÁØ´Ù.


3.1.3절. pcap_datalink

int pcap_datalink(pcap_t *p)
				
link layer ŸÀÔÀ» µÇµ¹·ÁÁØ´Ù(DLT_EN10MB °ú °°Àº)


3.1.4절. ¿¹Á¦

¿¹Á¦ : pcap.c

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>     //libpcap Çì´õ Æ÷Çè
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    char *dev;    // »ç¿ëÁßÀÎ ³×Æ®¿÷ µð¹ÙÀ̽º À̸§ 
    char *net;    // ³×Æ®¿÷ ¾îµå·¹½º 
    char *mask;   // ³×Æ®¿÷ mask ¾îµå·¹½º 
    int ret;      //  
    char errbuf[PCAP_ERRBUF_SIZE];
    bpf_u_int32 netp;  // ip 
    bpf_u_int32 maskp; // submet mask
    struct in_addr addr;

    // ³×Æ®¿÷ µð¹ÙÀ̽º À̸§À» ¾ò¾î¿Â´Ù. 
    dev = pcap_lookupdev(errbuf);

    // ¿¡·¯°¡ ¹ß»ýÇßÀ»°æ¿ì 
    if(dev == NULL)
    {
        printf("%s\n",errbuf);
        exit(1);
    }

    // ³×Æ®¿÷ µð¹ÙÀ̽º À̸§ Ãâ·Â 
    printf("DEV: %s\n",dev);

    // ³×Æ®¿÷ µð¹ÙÀ̽º À̸§ dev ¿¡ ´ëÇÑ 
    // mask, ip Á¤º¸ ¾ò¾î¿À±â   
    ret = pcap_lookupnet(dev,&netp,&maskp,errbuf);

    if(ret == -1)
    {
        printf("%s\n",errbuf);
        exit(1);
    }

    // ³×Æ®¿÷ ¾îµå·¹½º¸¦ Á¡¹ÚÀÌ 3ÇüÁ¦ ½ºÅ¸ÀÏ·Î
    addr.s_addr = netp;
    net = inet_ntoa(addr);

    if(net == NULL)
    {
        perror("inet_ntoa");
        exit(1);
    }

    printf("NET: %s\n",net);

    // ¸¶Âù°¡Áö·Î mask ¾îµå·¹½º¸¦ Á¡¹ÚÀÌ 3ÇüÁ¦ ½ºÅ¸ÀÏ·Î
    addr.s_addr = maskp;
    mask = inet_ntoa(addr);
  
    if(mask == NULL)
    {
        perror("inet_ntoa");
        exit(1);
    }
  
    printf("MASK: %s\n",mask);
    return 0;
}
				
´ÙÀ½Àº ÄÄÆÄÀÏ ¹æ¹ýÀÌ´Ù. ÄÄÆÄÀÏ È¯°æÀº Redhat Linux 8.x, gcc 3.x ÀÌ´Ù.
[root@localhost test]# gcc -o pcap pcap.c -lpcap -I/usr/include/pcap
				
pcap.h ÀÇ À§Ä¡´Â ¿î¿µÃ¼Á¦ ¸¶´Ù ´Ù¸¦¼ö ÀÖÀ¸´Ï È®ÀÎÈÄ ÄÄÆÄÀÏ Çϱ⠹ٶõ´Ù.

´ÙÀ½Àº ½ÇÇà°á°úÀÌ´Ù.

[root@localhost test]# ./pcap 
DEV: eth0
NET: 192.168.xxx.x
MASK: 255.255.xxx.x
				


3.2절. ÆÐŶ ĸÃÄ ÃʱâÈ­ °ü·Ã API

ÆÄÀϰü·Ã ÀÛ¾÷À» ÇÒ¶§ file descriptor(ÆÄÀÏÁöÁ¤ÀÚ)¸¦ ÀÌ¿ëÇØ¼­ ÀÛ¾÷Çϴ°Ͱú ¸¶Âù°¡Áö·Î, ÆÐŶ ĸÃİü·Ã ÀÛ¾÷À» ÇÒ¶§¿¡µµ packet capture descriptor ¸¦ °¡Áö°í ÀÛ¾÷À» ÇÑ´Ù.

packet capture descriptor ´Â pcatp_t * ÇüÀ¸·Î ¼±¾ðµÇ¾î ÀÖ´Ù.


3.2.1절. pcatp_t *pcap_open_live

pcap_t *pcap_open_live(char *device, int snaplen,
           int promisc, int to_ms, char *ebuf)
				
ù¹øÂ° ÀÎÀÚ·Î ÁÖ¾îÁö´Â ³×Æ®¿÷ µð¹ÙÀ̽º device¿¡ ´ëÇÑ packet capture descriptor(ÀÌÇÏ PCD) À» ¸¸µé±â À§ÇÑ ÇÔ¼öÀÌ´Ù. ÆÐŶÀ» ĸÃçÇÏ´Â ½ÇÁúÀûÀÎ ¸ðµçÀÏÀº pcap_open_live ÇÔ¼ö¸¦ È£ÃâÇØ¼­ ¸¸µé¾îÁø PCD ¸¦ ÀÌ¿ëÇØ¼­ ÀÌ·ç¾îÁö°Ô µÈ´Ù.

linux Ä¿³Î 2.2 ÀÌ»óÀÇ °æ¿ì device ¸¦ "any" ȤÀº NULL·Î ÇÒ°æ¿ì ¸ðµç ³×Æ®¿÷µð¹ÙÀ̽º¿¡ ´ëÇØ¼­ ÆÐŶ ĸÃİ¡ ÀϾ°Ô µÈ´Ù.

snaplenÀº ¹Þ¾ÆµéÀϼö ÀÖ´Â ÆÐŶÀÇ ÃÖ´ë Å©±â(byte)ÀÌ´Ù.

promisc ´Â ³×Æ®¿÷ µð¹ÙÀ̽º¸¦ promiscuous mode ·Î ÇÒ°ÍÀÎÁö¸¦ °áÁ¤Çϱâ À§Çؼ­ »ç¿ëÇÑ´Ù. promisc °¡ 1Àϰæ¿ì promiscuous ¸ðµå°¡ µÇ¸ç, ·ÎÄà ³×Æ®¿÷ÀÇ ¸ðµç ÆÐŶÀ» ĸÃÄÇÏ°Ô µÈ´Ù. 0 Àϰæ¿ì ¿¡´Â Àڱ⿡°Ô¸¸ ÇâÇÏ´Â ÆÐŶÀ» ĸÃÄÇÏ°Ô µÇ´Âµ¥, ¸î¸î °æ¿ì¿¡ À־ promiscuous ¸ðµå·Î ÀÛµ¿Çϱ⵵ ÇÑ´Ù.

to_ms ´Â Àб⠽ð£Ãʰú(time out) ÁöÁ¤À» À§Çؼ­ »ç¿ëµÇ¸ç millisecond ´ÜÀ§ÀÌ´Ù.

ebuf ´Â pcap_open_live ÇÔ¼ö È£Ãâ¿¡ ¹®Á¦°¡ »ý°åÀ»°æ¿ì ¿¡·¯ ¸Þ½ÃÁö¸¦ ÀúÀåÇϱâ À§Çؼ­ »ç¿ëÇÑ´Ù. ¸¸¾à pcap_open_live ÇÔ¼ö È£Ãâ½Ã ¿¡·¯°¡ ¹ß»ýÇÒ°æ¿ì NULL À» ¸®ÅÏÇÏ°í ¿¡·¯³»¿ëÀ» ebuf ¿¡ º¹»çÇÑ´Ù.


3.2.2절. pcap_t *pcap_open_offline

	
pcap_t *pcap_open_offline(char *fname, char *ebuf)
				
fname ¸¦ °¡Áö´Â ÆÄÀÏ·Î ºÎÅÍ ÆÐŶÀ» ÀоîµéÀδÙ. ¸¸¾à fname ÀÌ "-" ÀÏ °æ¿ì stdinÀ¸·Î ºÎÅÍ ÀоîµéÀδÙ.

ebuf ´Â ¿¡·¯¸Þ½ÃÁö¸¦ ÀúÀåÇϱâ À§Çؼ­ »ç¿ëµÈ´Ù.


3.3절. ÆÐŶ ĸÃÄ(Read) °ü·Ã API

À̹øÀå¿¡¼­´Â ½ÇÁ¦ ÆÐŶÀ» ĸÃÄÇÏ´Â °ü·Ã API µé¿¡ ´ëÇØ¼­ ¾Ë¾Æº¼°ÍÀÌ´Ù. ÀÌ ÆÐŶ ĸó °ü·Ã API ¸¦ Á¦´ë·Î ÀÌÇØÇÏ°í »ç¿ëÇϱâ À§Çؼ­´Â TCP/IP¿Í ÀÌ´õ³Ý ÇÁ·ÎÅäÄÝÀÇ ±¸Á¶¿¡ ´ëÇØ¼­ ¾î´ÀÁ¤µµ ÀÌÇØ¸¦ ÇØ¾ß ÇÑ´Ù. ±×·³À¸·Î API ¸¦ ´Ù·ç±â Àü¿¡ ÀÌµé ´ëÇ¥ÀûÀÎ ÇÁ·ÎÅäÄݵ鿡 ´ëÇÑ Çì´õ Á¤º¸¿¡ ´ëÇØ¼­ °£·«ÇÏ°Ô ¸ÕÀú ¾Ë¾Æº¸µµ·Ï ÇϰڴÙ.


3.3.1절. TCP,IP,Eternet ±¸Á¶Ã¼

ÆÐŶ Read °ü·Ã API¿¡¼­´Â ÆÐŶÀ» ÀоúÀ»¶§, Demultiplexing ÀÌ µÇÁö ¾ÊÀº ¿ÏÀüÇÑ ±¸Á¶ÀÇ ÆÐŶÀ» ³Ñ°ÜÁØ´Ù. ±×·³À¸·Î ÃÖ¼ÒÇÑ ÀÌµé °¢ ÆÐŶÀÇ ±¸Á¶Ã¼ Á¤º¸¸¦ ¾Ë°í ÀÖ¾î¾ß °¢ °èÃþ(Layer)ÀÇ µ¥ÀÌŸ¸¦ Àоî¿Ã¼ö ÀÖ´Ù.

´ÙÀ½Àº TCP, IP, Eternet ±¸Á¶Ã¼Á¤º¸ÀÌ´Ù.

tcp Çì´õ ±¸Á¶Ã¼

struct tcphdr
  {
    u_int16_t th_sport;     /* source port */
    u_int16_t th_dport;     /* destination port */
    tcp_seq th_seq;     /* sequence number */
    tcp_seq th_ack;     /* acknowledgement number */
#  if __BYTE_ORDER == __LITTLE_ENDIAN
    u_int8_t th_x2:4;       /* (unused) */
    u_int8_t th_off:4;      /* data offset */
#  endif
#  if __BYTE_ORDER == __BIG_ENDIAN
    u_int8_t th_off:4;      /* data offset */
    u_int8_t th_x2:4;       /* (unused) */
#  endif
    u_int8_t th_flags;
#  define TH_FIN    0x01
#  define TH_SYN    0x02
#  define TH_RST    0x04
#  define TH_PUSH   0x08
#  define TH_ACK    0x10
#  define TH_URG    0x20
    u_int16_t th_win;       /* window */
    u_int16_t th_sum;       /* checksum */
    u_int16_t th_urp;       /* urgent pointer */
};

				

IP Çì´õ ±¸Á¶Ã¼

struct ip
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ip_hl:4;       /* header length */
    unsigned int ip_v:4;        /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
    unsigned int ip_v:4;        /* version */
    unsigned int ip_hl:4;       /* header length */
#endif
    u_int8_t ip_tos;            /* type of service */
    u_short ip_len;         /* total length */
    u_short ip_id;          /* identification */
    u_short ip_off;         /* fragment offset field */
#define IP_RF 0x8000            /* reserved fragment flag */
#define IP_DF 0x4000            /* dont fragment flag */
#define IP_MF 0x2000            /* more fragments flag */
#define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
    u_int8_t ip_ttl;            /* time to live */
    u_int8_t ip_p;          /* protocol */
    u_short ip_sum;         /* checksum */
    struct in_addr ip_src, ip_dst;  /* source and dest address */
  };
				

ETHERNET Çì´õ ±¸Á¶Ã¼

struct ethhdr
{
    unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
    unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
    unsigned short  h_proto;            /* packet type ID field */
};
				

ip, tcp Çì´õ ÆÄÀÏÀº /usr/include/netinet ¹Ø¿¡¼­ ãÀ»¼ö ÀÖÀ¸¸ç, ethernet Çì´õ ÆÄÀÏÀº /usr/include/linux/if_ether.h ¿¡¼­ ãÀ»¼ö ÀÖ´Ù.

Ethernet Çì´õ¿Í IP Çì´õÀÇ °æ¿ì demultiplexing °úÁ¤À» °ÅÄ¡±â À§Çؼ­ »óÀ§ Layer ÀÇ ÇÁ·ÎÅäÄÝ Å¸ÀÔÀ» ÁöÁ¤Çϰí ÀÖÀ½À» ¾Ë¼ö ÀÖ´Ù. Ethernet Çì´õÀÇ h_proto ¿Í IP Çì´õÀÇ ip_p °¡ °¢ »óÀ§ Layer ÀÇ ÇÁ·ÎÅäÄÝ Å¸ÀÔÀ» ¾Ë·ÁÁÖ±â À§Çؼ­ »ç¿ëµÈ´Ù.

ºÎ¿¬¼³¸íÀ» ÇÏÀÚ¸é ¿î¿µÃ¼Á¦°¡ ÆÐŶÀ» ¹ÞÀ¸¸é °¡Àå ¸ÕÀú Link ·¹À̾ °ÅÄ¡´Âµ¥, Link ·¹À̾¼­´Â Ethernet Çì´õ¸¦ ºÐ¼®Çؼ­ ÆÐŶÀÌ Network ·¹ÀÌ¾î ·Î Àü´ÞµÇ´Â ÆÐŶÀÎÁö È®ÀÎÇØ¼­ Network ·¹À̾î·Î Àü´ÞµÈ´Ù¸é ÇØ´ç ÆÐŶÀÌ IP ÆÐŶÀÎÁö ¾Æ´Ï¸é ICMP, IGMP ¿Í °°Àº ÆÐŶÀÎÁö¸¦ °Ë»çÇÑÈÄ Network ·¹À̾îÀÇ ¾Ë¸ÂÀº 󸮷çƾÀ¸·Î º¸³¾°ÍÀÌ´Ù. Network ·¹À̾¼­´Â ÆÐŶÀ» ¹ÞÀº ´ÙÀ½ ÀÚ½ÅÀÇ ÇÁ·ÎÅäÄÝ Çì´õ¸¦ °Ë»çÇØ¼­ ÀÌ ÆÐŶÀÌ Transport ·¹À̾î·Î Àü´ÞµÇ´Â ÆÐŶÀÎÁö È®ÀÎÇϰí, Transport ·¹À̾î·Î Àü´ÞµÈ´Ù¸é UDP ÀÎÁö, TCP ÀÎÁö¸¦ È®ÀÎÇÑ´ÙÀ½¿¡ Transport ·¹À̾îÀÇ Àû´çÇÑ Ã³¸®·çƾÀ¸·Î ÆÐŶÀ» ´øÁú°ÍÀÌ´Ù. ÃÖÈÄ¿¡ ´Â TCP Çì´õ¸¸ ³²°Ô µÇ´Âµ¥, TCP Çì´õÀÇ PORT ¸¦ °Ë»çÇØ¼­ ¾î¶² ¾îÇø®ÄÉÀ̼ǿ¡°Ô Àü´ÞµÇ¾î¾ß ÇÏ´ÂÁö¸¦ ÃÖÁ¾ °áÁ¤ÇÏ°Ô µÈ´Ù.


3.3.2절. u_char *pcap_next

u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
				
´ÙÀ½ ÆÐŶ¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ¸®ÅÏÇÑ´Ù.

¿ì¸®´Â ÀÌ ÆÐŶÀ» ÀÐÀ½À¸·Î½á ÆÐŶÀÇ Á¤º¸¸¦ ¾ò¾î¿Ã¼ö ÀÖ´Ù. ½ÇÁö·Î ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ ÆÐŶĸÃÄ¿Í °ü·ÃµÈ ¸ðµç ÀÏÀ» ÇÒ¼ö ÀÖ´Ù. ³ª¸ÓÁö ÆÐŶĸÃÄ¿Í °ü·ÃµÈ ÇÔ¼öµéÀº (pcap_loop °°Àº) ÀÌ ÇÔ¼öÀÇ ±â´É Ãß°¡¹öÁ¯ À̶ó°í º¼¼ö ÀÖ´Ù.


3.3.3절. pcap_loop

int pcap_loop(pcap_t *p, int cnt,
        pcap_handler callback, u_char *user)
				
p ´Â PCD À̸ç, cnt ´Â ÆÐŶ ĸÃĸ¦ ¸î¹ø¿¡ °ÉÃļ­ ÇÒ°ÍÀÎÁö¸¦ °áÁ¤Çϱâ À§Çؼ­ »ç¿ëÇÑ´Ù. ¸¸¾à 0ÀÌ ÁöÁ¤µÇ¸é °è¼Ó ÆÐŶÀ» ¹Þ¾ÆµéÀÌ°Ô µÈ´Ù.

callback ´Â ÆÐŶÀÌ µé¾î¿ÔÀ»¶§ ½ÇÇàÇÏ´Â ÇÔ¼öÀÇ Æ÷ÀÎÅÍÀÌ´Ù. º¸ÅëÀº ÆÐŶÇÊÅ͸µ°ú °ü·ÃµÈ ÇÔ¼ö°¡ ½ÇÇàµÉ°ÍÀÌ´Ù.


3.3.4절. pcap_dispatch

int pcap_dispatch(pcap_t *p, int cnt,
         pcap_handler callback, u_char *user)
				
pcap_loop ¿Í °ÅÀÇ ºñ½ÁÇÏ´Ù.


3.4절. ÆÐŶ ÇÊÅ͸µ °ü·Ã API

3.4.1절. pcap_compile

int pcap_compile(pcap_t *p, struct bpf_program *fp,
          char *str, int optimize, bpf_u_int32 netmask)
				
µé¾î¿À´Â ÆÐŶÀ» ÇÊÅ͸µ ÇØ¼­ ¹Þ¾ÆµéÀ̱â À§Çؼ­ »ç¿ëÇÑ´Ù. ¿¹¸¦ µé¾î tcpdump ¿¡¼­ port 80 À¸·Î ¿À´Â ÆÐŶ¸¸À» ĸÃÄÇϱâ À§Çؼ­ ´ÙÀ½°ú °°ÀÌ »ç¿ëÇÏ´Â°É º¸¾ÒÀ»°Í ÀÌ´Ù.
[root@coco /root]# tcpdump port 80
Kernel filter, protocol ALL, TURBO mode (575 frames), datagram packet socket
tcpdump: listening on all devices
				
tcpdump ¸í·É ½ÇÇà½Ãų¶§ µÚ¿¡ ÁØ ¿É¼ÇÀÎ "port 80" ÀÌ filter rule À̸ç, str ¾Æ±Ô¸ÕÆ®¸¦ ÅëÇØ¼­ Àü´ÞµÈ´Ù.

fp bfp_program ±¸Á¶Ã¼ÀÇ Æ÷ÀÎÅÍÀ̸ç pcap_compile ¿¡ ÀÇÇØ¼­ ä¿öÁø´Ù. netmask´Â ·ÎÄà ³×Æ®ÀÇ netmask ÀÌ´Ù.

filter rule ¿¡ ´ëÇÑ ³»¿ëÀº tcpdump ÀÇ man ÆäÀÌÁö¿¡ »ó¼¼ÇÏ°Ô ³ª¿Í ÀÖÀ¸´Ï Âü°íÇϱ⠹ٶõ´Ù.


3.4.2절. pcap_setfilter

int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
				
pcap_compile À» ÅëÇØ¼­ ÁöÁ¤µÈ ÇÊÅ͸¦ Àû¿ë½Ã۱â À§Çؼ­ »ç¿ëµÇ¸ç, ¾ÕÀ¸·Î µé¾î¿À´Â ÆÐŶ¿¡ ´ëÇØ¼­´Â ÀÌ ÇÊÅÍ·ê¿¡ ÀÇÇØ¼­ ÇÊÅ͸µ µÈ´Ù.


4절. ¿¹Á¦ ÄÚµå

pcap ÀÇ ±âº»ÀûÀÎ API ¸¦ »ìÆìºÃÀ¸´Ï Á÷Á¢ Äڵ带 ÀÛ¼ºÇØ º¸µµ·Ï ÇϰڴÙ.

¿¹Á¦ : pcap_test.c

#include <sys/time.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <pcap/pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

#define PROMISCUOUS 1
#define NONPROMISCUOUS 0

// IP Çì´õ ±¸Á¶Ã¼
struct ip *iph;

// TCP Çì´õ ±¸Á¶Ã¼
struct tcphdr *tcph;

// ÆÐŶÀ» ¹Þ¾ÆµéÀϰæ¿ì ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù.  
// packet °¡ ¹Þ¾ÆµéÀÎ ÆÐŶÀÌ´Ù.
void callback(u_char *useless, const struct pcap_pkthdr *pkthdr, 
                const u_char *packet)
{
    static int count = 1;
    struct ether_header *ep;
    unsigned short ether_type;    
    int chcnt =0;
    int length=pkthdr->len;

    // ÀÌ´õ³Ý Çì´õ¸¦ °¡Á®¿Â´Ù. 
    ep = (struct ether_header *)packet;

    // IP Çì´õ¸¦ °¡Á®¿À±â À§Çؼ­ 
    // ÀÌ´õ³Ý Çì´õ Å©±â¸¸Å­ offset ÇÑ´Ù.   
    packet += sizeof(struct ether_header);

    // ÇÁ·ÎÅäÄÝ Å¸ÀÔÀ» ¾Ë¾Æ³½´Ù. 
    ether_type = ntohs(ep->ether_type);

    // ¸¸¾à IP ÆÐŶÀ̶ó¸é 
    if (ether_type == ETHERTYPE_IP)
    {
        // IP Çì´õ¿¡¼­ µ¥ÀÌŸ Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù.  
        iph = (struct ip *)packet;
        printf("IP ÆÐŶ\n");
        printf("Version     : %d\n", iph->ip_v);
        printf("Header Len  : %d\n", iph->ip_hl);
        printf("Ident       : %d\n", ntohs(iph->ip_id));
        printf("TTL         : %d\n", iph->ip_ttl); 
        printf("Src Address : %s\n", inet_ntoa(iph->ip_src));
        printf("Dst Address : %s\n", inet_ntoa(iph->ip_dst));

        // ¸¸¾à TCP µ¥ÀÌŸ ¶ó¸é
        // TCP Á¤º¸¸¦ Ãâ·ÂÇÑ´Ù. 
        if (iph->ip_p == IPPROTO_TCP)
        {
            tcph = (struct tcp *)(packet + iph->ip_hl * 4);
            printf("Src Port : %d\n" , ntohs(tcph->source));
            printf("Dst Port : %d\n" , ntohs(tcph->dest));
        }

        // Packet µ¥ÀÌŸ ¸¦ Ãâ·ÂÇÑ´Ù. 
        // IP Çì´õ ºÎÅÍ Ãâ·ÂÇÑ´Ù.  
        while(length--)
        {
            printf("%02x", *(packet++)); 
            if ((++chcnt % 16) == 0) 
                printf("\n");
        }
    }
    // IP ÆÐŶÀÌ ¾Æ´Ï¶ó¸é 
    else
    {
        printf("NONE IP ÆÐŶ\n");
    }
    printf("\n\n");
}    

int main(int argc, char **argv)
{
    char *dev;
    char *net;
    char *mask;

    bpf_u_int32 netp;
    bpf_u_int32 maskp;
    char errbuf[PCAP_ERRBUF_SIZE];
    int ret;
    struct pcap_pkthdr hdr;
    struct in_addr net_addr, mask_addr;
    struct ether_header *eptr;
    const u_char *packet;

    struct bpf_program fp;     

    pcap_t *pcd;  // packet capture descriptor

    // »ç¿ëÁßÀÎ µð¹ÙÀ̽º À̸§À» ¾ò¾î¿Â´Ù. 
    dev = pcap_lookupdev(errbuf);
    if (dev == NULL)
    {
        printf("%s\n", errbuf);
        exit(1);
    }
    printf("DEV : %s\n", dev);

    // µð¹ÙÀ̽º À̸§¿¡ ´ëÇÑ ³×Æ®¿÷/¸¶½ºÅ© Á¤º¸¸¦ ¾ò¾î¿Â´Ù. 
    ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
    if (ret == -1)
    {
        printf("%s\n", errbuf);
        exit(1);
    }

    // ³×Æ®¿÷/¸¶½ºÆ® Á¤º¸¸¦ Á¡¹ÚÀÌ 3ÇüÁ¦ ½ºÅ¸ÀÏ·Î º¯°æÇÑ´Ù. 
    net_addr.s_addr = netp;
    net = inet_ntoa(net_addr);
    printf("NET : %s\n", net);

    mask_addr.s_addr = maskp;
    mask = inet_ntoa(mask_addr);
    printf("MSK : %s\n", mask);
    printf("=======================\n");

    // µð¹ÙÀ̽º dev ¿¡ ´ëÇÑ packet capture 
    // descriptor ¸¦¾ò¾î¿Â´Ù.   
    pcd = pcap_open_live(dev, BUFSIZ,  NONPROMISCUOUS, -1, errbuf);
    if (pcd == NULL)
    {
        printf("%s\n", errbuf);
        exit(1);
    }    

    // ÄÄÆÄÀÏ ¿É¼ÇÀ» ÁØ´Ù.
    if (pcap_compile(pcd, &fp, argv[2], 0, netp) == -1)
    {
        printf("compile error\n");    
        exit(1);
    }
    // ÄÄÆÄÀÏ ¿É¼Ç´ë·Î ÆÐŶÇÊÅÍ ·êÀ» ¼¼ÆÃÇÑ´Ù. 
    if (pcap_setfilter(pcd, &fp) == -1)
    {
        printf("setfilter error\n");
        exit(0);    
    }

    // ÁöÁ¤µÈ Ƚ¼ö¸¸Å­ ÆÐŶĸÃĸ¦ ÇÑ´Ù. 
    // pcap_setfilter À» Åë°úÇÑ ÆÐŶÀÌ µé¾î¿Ã°æ¿ì 
    // callback ÇÔ¼ö¸¦ È£ÃâÇϵµ·Ï ÇÑ´Ù. 
    pcap_loop(pcd, atoi(argv[1]), callback, NULL);
}
		

ÄÄÆÄÀÏ ¹æ¹ýÀº ¾Æ·¡¿Í °°´Ù.

[root@localhost pcap_test]# gcc -o pcap_test pcap_test.c -lpcap -I/usr/include/pcap
		
´ÙÀ½Àº ÇÊÀÚÀÇ Linux ¹Ú½º¿¡¼­ Å×½ºÆ®ÇÑ °á°úÀÌ´Ù.
[root@localhost pcap_test]# ./pcap_test -1 "port 80"
DEV : eth0
NET : 192.168.100.0
MSK : 255.255.255.0
=======================
IP ÆÐŶ
Version     : 4
Header Len  : 5
Ident       : 51804
TTL         : 64
Src Address : 192.168.100.130
Dst Address : 218.234.19.87
Src Port : 4996
Dst Port : 80
45000034ca5c400040065cfbc0a86482
daea1357138400502e7a303b2e7cc456
801021f0badb00000101080a0014e136
22631d7b485454502f312e3120323030
204f

IP ÆÐŶ
Version     : 4
Header Len  : 5
Ident       : 41787
TTL         : 54
Src Address : 218.234.19.87
Dst Address : 192.168.100.130
Src Port : 80
Dst Port : 4996
		


5절. °á·Ð

ÀÌ»ó °£´ÜÇÏ°Ô libpcap ÀÇ »ç¿ë¹æ¹ý¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸¾Ò´Ù. À̹ø ±Û¿¡¼­´Â libpcap ÀÇ »ç¿ë¹ý¿¡¸¸ ÃÊ÷À» ¸ÂÃß°í Àִµ¥, ´ÙÀ½¹ø °­Á¿¡¼­´Â ¸î°¡Áö "ÀÀ¿ë" ¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸µµ·Ï ÇϰڴÙ.

주석

[1]

Intrusion Detection System ÀÇ ÁÙÀÓ¸» À̸ç, ħÀÔŽÁö ½Ã½ºÅÛÀ» ¸»ÇÑ´Ù. ³×Æ®¿÷ ħÀÔŽÁö¸¦ À§ÇÑ NIDS, È£½ºÆ® ħÀÔŽÁö¸¦ À§ÇÑ HIDS ·Î ³ª´­¼ö ÀÖ´Ù. ÀϹÝÀûÀ¸·Î IDS ¶ó°í ÇÏ¸é ³×Æ®¿÷ ħÀÔ Å½Áö ½Ã½ºÅÛÀ» ¸»ÇÑ´Ù.


category_network
programing
category__5
EmailÀ» ±âÀÔÇϸé, ´ñ±ÛÀÌ ¸ÞÀÏ·Î Àü´ÞµË´Ï´Ù.