Skip to content

Commit

Permalink
aggiunti test nfqueue_netfilter
Browse files Browse the repository at this point in the history
  • Loading branch information
ilsergente1993 committed Feb 2, 2020
1 parent 3fe347f commit 3ec8dc6
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 116 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
craftberry
main.o
captures/*.pcapng
*.o
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp"
"typeinfo": "cpp",
"ctime": "cpp",
"functional": "cpp",
"chrono": "cpp"
}
}
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ clear:
rm main.o
rm craftberry

test2:
rm test.o
rm test
g++ $(PCAPPP_BUILD_FLAGS) $(PCAPPP_INCLUDES) -c -o test.o test.cpp -lnetfilter_queue
g++ $(PCAPPP_LIBS_DIR) -static-libstdc++ -o test test.o $(PCAPPP_LIBS) -lnetfilter_queue

nfqueue:
# rm nfqueue_test.o
# rm nfqueue_test
g++ $(PCAPPP_BUILD_FLAGS) $(PCAPPP_INCLUDES) -c -o nfqueue_test.o nfqueue_test.cpp -lnetfilter_queue
g++ $(PCAPPP_LIBS_DIR) -static-libstdc++ -o nfqueue_test nfqueue_test.o $(PCAPPP_LIBS) -lnetfilter_queue
g++ $(PCAPPP_LIBS_DIR) -static-libstdc++ -o nfqueue_test nfqueue_test.o $(PCAPPP_LIBS) -lnetfilter_queue

nfqueue2:
#rm nfqueue_test2.o
#rm nfqueue_test2
g++ $(PCAPPP_BUILD_FLAGS) $(PCAPPP_INCLUDES) -c -o nf_queue_test2.o nf_queue_test2.cpp -lnetfilter_queue
g++ $(PCAPPP_LIBS_DIR) -static-libstdc++ -o nf_queue_test2 nf_queue_test2.o $(PCAPPP_LIBS) -lnetfilter_queue
91 changes: 91 additions & 0 deletions nf_queue_test2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <array>
#include <functional>
#include <linux/netfilter.h>
#include <memory>
//#include <netinet/in.h>
//#include <netinet/ip.h>
//#include <netinet/tcp.h>
#include <unistd.h>

extern "C" {
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
#include <libnetfilter_queue/pktbuff.h>
}

#define THROW_IF_TRUE(x, m) \
do { \
if ((x)) { \
throw std::runtime_error(m); \
} \
} while (false)

#define CONCAT_0(pre, post) pre##post
#define CONCAT_1(pre, post) CONCAT_0(pre, post)
#define GENERATE_IDENTIFICATOR(pre) CONCAT_1(pre, __LINE__)

using ScopedGuard = std::unique_ptr<void, std::function<void(void *)>>;
#define SCOPED_GUARD_NAMED(name, code) \
ScopedGuard name(reinterpret_cast<void *>(-1), [&](void *) -> void { code }); \
(void)name
#define SCOPED_GUARD(code) SCOPED_GUARD_NAMED(GENERATE_IDENTIFICATOR(genScopedGuard), code)

static int netfilterCallback(struct nfq_q_handle *queue, struct nfgenmsg *nfmsg, struct nfq_data *nfad, void *data) {
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfad);
ASSERT(ph == nullptr, "Issue while packet header");

unsigned char *rawData = nullptr;
int len = nfq_get_payload(nfad, &rawData);
ASSERT(len < 0, "Can\'t get payload data");

struct pkt_buff *pkBuff = pktb_alloc(AF_INET, rawData, len, 0x1000);
ASSERT(pkBuff == nullptr, "Issue while pktb allocate");
SCOPED_GUARD(pktb_free(pkBuff);); // Don't forget to clean up

struct iphdr *ip = nfq_ip_get_hdr(pkBuff);
ASSERT(ip == nullptr, "Issue while ipv4 header parse.");

ASSERT(nfq_ip_set_transport_header(pkBuff, ip) < 0, "Can\'t set transport header.");

if (ip->protocol == IPPROTO_TCP) {
struct tcphdr *tcp = nfq_tcp_get_hdr(pkBuff);
ASSERT(tcp == nullptr, "Issue while tcp header.");

void *payload = nfq_tcp_get_payload(tcp, pkBuff);
unsigned int payloadLen = nfq_tcp_get_payload_len(tcp, pkBuff);
payloadLen -= 4 * tcp->th_off;
ASSERT(payload == nullptr, "Issue while payload.");

for (unsigned int i = 0; i < payloadLen / 2; ++i) {
char tmp = (static_cast<char *>(payload))[i];
(static_cast<char *>(payload))[i] = (static_cast<char *>(payload))[payloadLen - 1 - i];
(static_cast<char *>(payload))[payloadLen - 1 - i] = tmp;
}

nfq_tcp_compute_checksum_ipv4(tcp, ip);
return nfq_set_verdict(queue, ntohl(ph->packet_id), NF_ACCEPT, pktb_len(pkBuff), pktb_data(pkBuff));
}
return nfq_set_verdict(queue, ntohl(ph->packet_id), NF_ACCEPT, 0, nullptr);
}

int main() {
struct nfq_handle *handler = nfq_open();
ASSERT(handler == nullptr, "Can\'t open hfqueue handler.");
SCOPED_GUARD(nfq_close(handler);); // Don’t forget to clean up

struct nfq_q_handle *queue = nfq_create_queue(handler, 0, netfilterCallback, nullptr);
ASSERT(queue == nullptr, "Can\'t create queue handler.");
SCOPED_GUARD(nfq_destroy_queue(queue);); // Do not forget to clean up

ASSERT(nfq_set_mode(queue, NFQNL_COPY_PACKET, 0xffff) < 0, "Can\'t set queue copy mode.");

int fd = nfq_fd(handler);
std::array<char, 0x10000> buffer;
for (;;) {
int len = read(fd, buffer.data(), buffer.size());
ASSERT(len < 0, "Issue while read");
nfq_handle_packet(handler, buffer.data(), len);
}
return 0;
}
File renamed without changes.
Binary file added nfqueue_test
Binary file not shown.
231 changes: 124 additions & 107 deletions nfqueue_test.cpp
Original file line number Diff line number Diff line change
@@ -1,133 +1,150 @@
#include <arpa/inet.h>
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
//#include <libmnl/libmnl.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <functional>
#include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_queue.h>
#include <linux/types.h>

// 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;
// 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);
// //processPacketData (data, 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);
u_int32_t id;

struct nfqnl_msg_packet_hdr *ph;
ph = nfq_get_msg_packet_hdr(nfa);
id = ntohl(ph->packet_id);
printf("entering callback\n");
return nfq_set_verdict(qh, id, 1 /*NF_ACCEPT*/, 0, NULL);
#include <memory>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

#include "pcapplusplus/DnsLayer.h"
#include "pcapplusplus/EthLayer.h"
#include "pcapplusplus/HttpLayer.h"
#include "pcapplusplus/IPv4Layer.h"
#include "pcapplusplus/IcmpLayer.h"
#include "pcapplusplus/Packet.h"
#include "pcapplusplus/PcapFileDevice.h"
#include "pcapplusplus/PcapLiveDeviceList.h"
#include "pcapplusplus/PlatformSpecificUtils.h"
#include "pcapplusplus/TcpLayer.h"
#include "pcapplusplus/UdpLayer.h"

extern "C" {
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
#include <libnetfilter_queue/pktbuff.h>
}

int main(int argc, char **argv) {
struct nfq_handle *h;
struct nfq_q_handle *qh;
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);
#define ASSERT(x, m, f) \
do { \
if ((x)) { \
cerr << m << endl; \
f; \
} \
} while (false);

#define CHECK(x, m) \
ASSERT(x, m, nullptr)

#define IPTABLES(proto, isdel) \
system(( \
"\n#/bin/bash\n\n"s + \
"sudo iptables "s + \
(!isdel ? "-A"s : "-D"s) + \
" INPUT -p "s + \
#proto + \
" -j NFQUEUE"s) \
.c_str());

using namespace std;

static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) {
cout << "entering callback" << endl;

//DOC: ottengo il payload del pacchetto
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa);
CHECK(ph == nullptr, "Issue while packet header");
unsigned char *rawData = nullptr;
int len = nfq_get_payload(nfa, &rawData);
CHECK(len < 0, "Can\'t get payload data");

struct timeval timestamp;
nfq_get_timestamp(nfa, &timestamp);

//DOC: creo il pacchetto pcapPlusPlus
pcpp::RawPacket inPacketRaw(static_cast<uint8_t *>(rawData), len, timestamp, false, pcpp::LINKTYPE_RAW);

pcpp::Packet inPacket(&inPacketRaw);
pcpp::EthLayer newEthernetLayer(pcpp::MacAddress("f0:4b:3a:4f:80:30"), pcpp::MacAddress("a2:ee:e9:dd:4c:14"));
inPacket.insertLayer(NULL, &newEthernetLayer, true);
inPacket.computeCalculateFields();

//DOC: scrorro i pacchetti per inspezione
pcpp::Layer *L = inPacket.getFirstLayer();
cout << "Pacchetto In" << endl;
while (L != nullptr) {
cout << "\t" << L->getOsiModelLayer() << " => " << L->toString() << endl;
L = L->getNextLayer();
}

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);
}
cout << "Invio il pacchetto" << endl;

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);
}
//DOC: apro il dispositivo di destinazione
string dstAddr = inPacket.getLayerOfType<pcpp::IPv4Layer>()->getDstIpAddress().toString();
pcpp::PcapLiveDevice *dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(dstAddr.c_str());
ASSERT(dev == NULL, "Cannot find interface with IPv4 address of "s + dstAddr, exit(1));
ASSERT(!dev->open(), "Cannot open device", 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);
}
//DOC: creo ed invio una secondo pacchetto identico
pcpp::RawPacket outPacketRaw(*inPacket.getRawPacketReadOnly());
pcpp::Packet outPacket(&outPacketRaw);

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);
pcpp::Layer *LL = outPacket.getFirstLayer();
cout << "Pacchetto Out" << endl;
while (LL != nullptr) {
cout << "\t" << LL->getOsiModelLayer() << " => " << LL->toString() << endl;
LL = LL->getNextLayer();
}

fd = nfq_fd(h);
CHECK(!dev->pcpp::PcapLiveDevice::sendPacket(outPacketRaw), "packet not sent");
dev->close();

// para el tema del loss: while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0)
//DOC: invio il verdetto
return nfq_set_verdict(qh, ntohl(ph->packet_id), NF_ACCEPT, 0, NULL);
}

while ((rv = recv(fd, buf, sizeof(buf), 0))) {
printf("pkt received\n");
nfq_handle_packet(h, buf, rv);
int main(/*int argc, char **argv*/) {
// cout << "adding iptables rule" << endl;
// IPTABLES("udp", false);

struct nfq_handle *handler = nfq_open();
ASSERT(handler == nullptr, "Can\'t open hfqueue handler.", exit(1));

// cout << "unbinding existing nf_queue handler for AF_INET (if any)\n";
// ASSERT(nfq_unbind_pf(handler, AF_INET) < 0, "error during nfq_unbind_pf()\n", exit(1));
// cout << "binding nfnetlink_queue as nf_queue handler for AF_INET\n";
// ASSERT(nfq_bind_pf(handler, AF_INET) < 0, "error during nfq_bind_pf()\n", exit(1));

struct nfq_q_handle *queue = nfq_create_queue(handler, 0, &callback, nullptr);
ASSERT(queue == nullptr, "Can\'t create queue handler.", exit(1));
ASSERT(nfq_set_mode(queue, NFQNL_COPY_PACKET, 0xffff) < 0, "Can\'t set queue copy mode.", exit(1));
int fd = nfq_fd(handler);
std::array<char, 0x10000> buffer;
cout << "gonna be into run" << endl;

while (true) {
int len = read(fd, buffer.data(), buffer.size());
CHECK(len < 0, "Issue while read");
nfq_handle_packet(handler, buffer.data(), len);
}

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
cout << "exiting from craftberry" << endl;
nfq_destroy_queue(queue);
nfq_close(handler);

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

exit(0);
}
// cout << "removing iptables rule" << endl;
// IPTABLES("icmp", true);
return 0;
}

0 comments on commit 3ec8dc6

Please sign in to comment.