본문 바로가기
Hack/Network

[Netfilter] netfilter_queue 사용 방법

by Becoming a Hacker 2022. 8. 28.
반응형

netfilter_queue 설치

먼저 netfilter_queue를 사용하기 위해 linfnetlinklibmnl을 설치해준뒤, libnetfilter_queue를 설치해줍니다.

# Install libnfnetlink
$ wget https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2
$ tar -xf libnfnetlink-1.0.2.tar.bz2
$ cd libnfnetlink-1.0.2
$ ./configure
$ make
$ sudo make install
$ cd..

# Install libmnl
$ wget https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2
$ tar -xf libmnl-1.0.5.tar.bz2
$ cd libmnl-1.0.5
$ ./configure
$ make
$ sudo make install
$ cd..

# Install libnetfilter_queue
$ wget https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2
$ tar -xf libnetfilter_queue-1.0.5.tar.bz2
$ cd libnetfilter_queue-1.0.5
$ ls -l
$ ./configure
$ cd ..

 

make install을 통해 library가 /usr/local/lib에 생성되는데, 해당 library가 파일 실행 시 포함되도록 명령어를 실행합니다.

$ sudo vi /etc/ld.so.conf
include /usr/local/lib
$ sudo ldconfig

 

Sample Code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h>		/* for NF_ACCEPT */
#include <errno.h>
#include <libnetfilter_queue/libnetfilter_queue.h>


/* returns packet id */


static u_int32_t print_pkt (struct nfq_data *tb)
{

	int id = 0;
	struct nfqnl_msg_packet_hdr *ph;
	struct nfqnl_msg_packet_hw *hwph;
	u_int32_t mark,ifi;
	int ret;
	unsigned char *data;
	ph = nfq_get_msg_packet_hdr(tb);

	if (ph) {
		id = ntohl(ph->packet_id);
		printf("hw_protocol=0x%04x hook=%u id=%u ",
			ntohs(ph->hw_protocol), ph->hook, id);
	}

	hwph = nfq_get_packet_hw(tb);

	if (hwph) {
		int i, hlen = ntohs(hwph->hw_addrlen);
		printf("hw_src_addr=");

		for (i = 0; i < hlen-1; i++)
			printf("%02x:", hwph->hw_addr[i]);

		printf("%02x ", hwph->hw_addr[hlen-1]);
	}

	mark = nfq_get_nfmark(tb);

	if (mark)
		printf("mark=%u ", mark);

	ifi = nfq_get_indev(tb);

	if (ifi)
		printf("indev=%u ", ifi);

	ifi = nfq_get_outdev(tb);

	if (ifi)
		printf("outdev=%u ", ifi);

	ifi = nfq_get_physindev(tb);

	if (ifi)
		printf("physindev=%u ", ifi);

	ifi = nfq_get_physoutdev(tb);

	if (ifi)
		printf("physoutdev=%u ", ifi);

	ret = nfq_get_payload(tb, &data);

	if (ret >= 0)
		printf("payload_len=%d ", ret);

	fputc('\n', stdout);
	return id;
}


static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
	      struct nfq_data *nfa, void *data)
{
	u_int32_t id = print_pkt(nfa);

	printf("entering callback\n");
	return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
}


int main(int argc, char **argv)
{

	struct nfq_handle *h;
	struct nfq_q_handle *qh;
	struct nfnl_handle *nh;
	int fd;
	int rv;
	char buf[4096] __attribute__ ((aligned));

	printf("opening library handle\n");

	h = nfq_open();

	if (!h) {
		fprintf(stderr, "error during nfq_open()\n");
		exit(1);
	}

	printf("unbinding existing nf_queue handler for AF_INET (if any)\n");

	if (nfq_unbind_pf(h, AF_INET) < 0) {
		fprintf(stderr, "error during nfq_unbind_pf()\n");
		exit(1);
	}

	printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");

	if (nfq_bind_pf(h, AF_INET) < 0) {
		fprintf(stderr, "error during nfq_bind_pf()\n");
		exit(1);
	}

	printf("binding this socket to queue '0'\n");

	qh = nfq_create_queue(h,  0, &cb, NULL);

	if (!qh) {
		fprintf(stderr, "error during nfq_create_queue()\n");
		exit(1);
	}

	printf("setting copy_packet mode\n");


	if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
		fprintf(stderr, "can't set packet_copy mode\n");
		exit(1);
	}

	fd = nfq_fd(h);

	for (;;) {
		if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
			printf("pkt received\n");
			nfq_handle_packet(h, buf, rv);
			continue;
		}

		/* if your application is too slow to digest the packets that
		 * are sent from kernel-space, the socket buffer that we use
		 * to enqueue packets may fill up returning ENOBUFS. Depending
		 * on your application, this error may be ignored. Please, see
		 * the doxygen documentation of this library on how to improve
		 * this situation.
		 */

		if (rv < 0 && errno == ENOBUFS) {
			printf("losing packets!\n");
			continue;
		}

		perror("recv failed");
		break;
	}

	printf("unbinding from queue 0\n");
	nfq_destroy_queue(qh);


#ifdef INSANE

	/* normally, applications SHOULD NOT issue this command, since
	 * it detaches other programs/sockets from AF_INET, too ! */

	printf("unbinding from AF_INET\n");
	nfq_unbind_pf(h, AF_INET);

#endif


	printf("closing library handle\n");
	nfq_close(h);

	exit(0);
}

 

Compile 명령어

$ gcc -Wall -o test nfqnl_test.c -lnfnetlink -lnetfilter_queue

 

iptables 설정

# 80 Port로 나가는 Packet만 netfilter_queue로 전달
$ sudo iptables -A OUTPUT -p tcp --dport 80 -j NFQUEUE

 

실행 화면

 

libnetfilter_queue Library Documents

 

Manpages of libnetfilter-queue-doc in Debian testing — Debian Manpages

 

manpages.debian.org

 

Tutorials

 

Modifying Network Traffic with NFQUEUE and ARP Spoofing

Learn if it's possible to intercept and modify network traffic with the help of NFQUEUE and ARP spoofing.

www.apriorit.com

 

반응형

댓글