libipq로 NIC로 들어오는 모든 패킷 캡쳐하기?

semigifn의 이미지

아래는 libipq 샘플코드입니다.
아래와 같이 설정하고 실행하면 시스템에서 실행되는 네트웍 응용프로그램의 패킷만 캡쳐가 됩니다.
즉, 네트웍 응용프로그램이 동작하지 않으면 패킷이 캡쳐가 되지 않습니다.
응용프로그램에 상관없이 시스템의 NIC에 들어오는 모든 패킷을 캡쳐하려면 어떻게 해야 할까요?

The quick intro to libipq
By: Chris, Christy and Frank
 
 
We are going to begin with looking at some of the sample code provided in the man page of libipq. Its not completely obvious whats going on here with the direction and flow of packets, so I'll try and explain as we go.
Before you try running the code, you need to do a couple things: 
modprobe iptable_filter 
modprobe ip_queue 
iptables rule to direct packets to QUEUE 
The ones we will be using are: 
iptables -A OUTPUT -p icmp -j QUEUE 
iptables -A INPUT -p tcp -j QUEUE 
iptables -A INPUT -p udp -j QUEUE 
The code begins... We have some includes, one of which is for libipq, and the other is netfilter. We use the libipq one for all of the functions prefixed with ipq_ and the netfilter header is for some of the constants we use through out. Other useful headers include the ip header, tcp header, and any other packet type that you might want to be able to map into a structure.
#include <linux/netfilter.h>
#include <libipq.h>
#include <stdio.h>
 
#define BUFSIZE 2048 
 
static void die(struct ipq_handle *h)
{
        ipq_perror("passer");
        ipq_destroy_handle(h);
        exit(1);
}
 
int main(int argc, char **argv)
{
        int status;
        unsigned char buf[BUFSIZE];
 
Here we need a ipq_handle in order to use later when we want to do things, such as read packets and do any other libipq operations. Note we also have a buf[BUFSIZE] above this, which is a static sized buffer for packet data. We create the handle, and move or die trying.
        struct ipq_handle *h;
 
        h = ipq_create_handle(0, PF_INET);
        if (!h)
                die(h);
 
 
Now we determine the mode that we want to use to get packets. The different modes are IPQ_COPY_META and IPQ_COPY_PACKET. Basically we need to know if we want payloads as well as meta-data. This also initiates the transfer of packets from the QUEUE to user-space. If we specify IPQ_COPY_PACKET, then the 3rd argument is the size of the payload we are going to want. If this fails we die.
        status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
        if (status < 0)
                die(h);
 
        do{
 
Next we read the contents of a packet, with ipq_read. This says to read into buf, for a maximum size of BUFSIZE (we don't want to overflow the buffer right...). The last arg, in this case 0, is the timeout for the read operation. This is the same as a select() function timeout.
                status = ipq_read(h, buf, BUFSIZE, 0);
                if (status < 0)
                        die(h);
 
                switch (ipq_message_type(buf)) {
                        case NLMSG_ERROR:
                                fprintf(stderr, "Received error message %d\n",
                                        ipq_get_msgerr(buf));
                                break;
 
 
Based on the message type, we can determine an error (NLMSG_ERROR) or if we got a packet (IPQM_PACKET). Then we use the packet_msg_t to access the packet, and then set the verdict (ACCEPT or DROP). ACCEPT allows the packet through the netfilter hooks, and into the appropriate service. DROP makes the packet disappear.
Also in the IPQM_PACKET block we have some additional code which is not in the man page. This is just an example of how to access parts of the packets, such as the IP layer header and the TCP header. To point the headers at the right places you basically just need the size of each previous header. Then by offsetting from the m->payload pointer we can access the different portions of the packet. Once we have this, you can get any of the data contained in the header, such as the port in this example.
                        case IPQM_PACKET: {
                                ipq_packet_msg_t *m = ipq_get_packet(buf);
 
                                struct iphdr *ip = (struct iphdr*) m->payload;
 
                                struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));
 
                                int port = htons(tcp->dest);        
 
                                status = ipq_set_verdict(h, m->packet_id,
                                                         NF_ACCEPT, 0, NULL);
                                if (status < 0)
                                        die(h);
                                break;
                        }
 
                        default:
                                fprintf(stderr, "Unknown message type!\n");
                                break;
                }
        } while (1);
 
 
After we are done, we cleanup and exit. Need to remove the hook to cleanly end all of the ipq stuff.
        ipq_destroy_handle(h);
        return 0;
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.