diff --git a/new_packet.pxd b/new_packet.pxd index 7204354..f00fcbd 100644 --- a/new_packet.pxd +++ b/new_packet.pxd @@ -199,7 +199,7 @@ cdef class CPacket: cdef Py_ssize_t data_len cdef readonly unsigned char *data cdef timeval timestamp - cdef u_int8_t hw_addr[8] + cdef u_int8_t hw_addr[6] cdef u_int32_t parse(self, nfq_q_handle *qh, nfq_data *nfa) nogil cdef void _parse(self) nogil diff --git a/new_packet.pyx b/new_packet.pyx index 00ca8e7..0482b3a 100644 --- a/new_packet.pyx +++ b/new_packet.pyx @@ -26,7 +26,7 @@ def set_user_callback(ref): user_callback = ref -cdef int nf_callback(nfq_q_handle *qh, nfgenmsg *nfmsg, nfq_data *nfa, void *data) with gil: +cdef int nf_callback(nfq_q_handle *qh, nfgenmsg *nfmsg, nfq_data *nfa, void *data): cdef u_int32_t mark @@ -145,52 +145,6 @@ cdef class CPacket: return self.timestamp.tv_sec + (self.timestamp.tv_usec / 1000000.0) - cdef u_int8_t get_inint(self, bint name=False): - '''Returns index of inbound interface of packet. If the packet sourced from localhost or the input - interface is not known, 0 will be returned. - ''' - # if name=True, socket.if_indextoname() will be returned. - # ''' - - # cdef object in_interface_name - - cdef u_int8_t in_interface - - in_interface = nfq_get_indev(self._nfa) - - return in_interface - - # try: - # in_interface_name = socket.if_indextoname(in_interface) - # except OSError: - # in_interface_name = 'unknown' - - # return in_interface_name - - # NOTE: keeping these funtions separate instead of making an argument option to adjust which interface to return. - # this will keep it explicit for which interface is returning to minimize chance of confusion/bugs. - cdef u_int8_t get_outint(self, bint name=False): - '''Returns index of outbound interface of packet. If the packet is destined for localhost or the output - interface is not yet known, 0 will be returned. - ''' - # if name=True, socket.if_indextoname() will be returned. - # ''' - - # cdef object out_interface_name - - cdef u_int8_t out_interface - - out_interface = nfq_get_outdev(self._nfa) - - return out_interface - - # try: - # out_interface_name = socket.if_indextoname(out_interface) - # except OSError: - # out_interface_name = 'unknown' - - # return out_interface_name - cpdef update_mark(self, u_int32_t mark): '''Modifies the running mark of the packet.''' @@ -220,16 +174,37 @@ cdef class CPacket: self.verdict(NF_REPEAT) + def get_inint_name(self): + + # cdef object *int_name + # + # nfq_get_indev_name(self) + + pass + + def get_outint_name(self): + + # cdef object *int_name + # + # nfq_get_outdev_name(self) + + pass + def get_hw(self): '''Return hardware information of the packet. hw_info = ( - self.get_inint(), self.get_outint(), mac_addr, self.get_timestamp() + in_interface, out_interface, mac_addr, self.get_timestamp() ) ''' cdef object mac_addr cdef tuple hw_info + cdef int in_interface + cdef int out_interface + + in_interface = nfq_get_indev(self._nfa) + out_interface = nfq_get_outdev(self._nfa) self._hw = nfq_get_packet_hw(self._nfa) if self._hw == NULL: @@ -238,14 +213,16 @@ cdef class CPacket: # parsing process and forcing error handling will ensure it is dealt with [properly]. raise OSError('MAC address not available in OUTPUT and PREROUTING chains') - # NOTE: can this not just be directly referenced below? - # self.hw_addr = self._hw.hw_addr + cdef char* hw_addr = self._hw.hw_addr - mac_addr = PyBytes_FromStringAndSize(self._hw.hw_addr, 8) + # NOTE: this is 8 bytes in source and lib_netfilter_queue, but unsure why since mac addresses are only 6 + # bytes. the last two bytes may be padding, but either way removing here so it will not need to be done + # on the python side. + mac_addr = PyBytes_FromStringAndSize(hw_addr, 6) hw_info = ( - self.get_inint(), - self.get_outint(), + in_interface, + out_interface, mac_addr, self.get_timestamp(), ) diff --git a/nfq_test.py b/nfq_test.py new file mode 100644 index 0000000..3bde4ea --- /dev/null +++ b/nfq_test.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 + +import threading + +from time import perf_counter_ns +from ipaddress import IPv4Address + +from new_packet import set_user_callback, NetfilterQueue + +TEST_FORWARD = 0 + +def print_and_accept(pkt, pkt_mark): + print('+'*30) + + start = perf_counter_ns() + +# print(pkt_mark) + + hw_info = pkt.get_hw() + +# print(hw_info) + +# print(hw_info[2].hex()) + +# print('-'*30) + +# data = pkt.get_raw_packet() + +# print(data[0], (data[0] & 15) * 4) + +# print('-'*30) + + ip_header = pkt.get_ip_header() + +# print(ip_header) +# print(ip_header[6], IPv4Address(ip_header[8]), IPv4Address(ip_header[9])) + +# print('-'*30) + + proto_header = pkt.get_proto_header() + +# print(pkt.get_proto_header()) + +# print('-'*30) + + payload = pkt.get_payload() +# print(pkt.get_payload()) + +# t, s, d = pkt.get_ip_header() + +# print(array('i', pkt.get_ip_header())) +# print(pkt, pkt.get_timestamp()) + +# print(f'[IN] {pkt.get_inint()} {pkt.get_inint(name=True)}') +# print(f'[OUT] {pkt.get_outint()} {pkt.get_outint(name=True)}') + +# pkt.update_mark(69) + +# print(f'[MARK] {pkt.get_initial_mark()} {pkt.get_modified_mark()} ') + +# print(pkt.payload_test) + + total = perf_counter_ns() - start + + pkt.accept() + + print(f'GRABBED IN: {total} ns') + + print('='*30) + +def q_one(pkt): + print('+'*30) + + print('[Q1/rcvd]') +# print(f'[IN] {pkt.get_inint()} {pkt.get_inint(name=True)}') +# print(f'[OUT] {pkt.get_outint()} {pkt.get_outint(name=True)}') + +# pkt.update_mark(69) + +# print(f'[MARK] {pkt.get_initial_mark()} {pkt.get_modified_mark()}') + +# pkt.forward(2) +# print('[Q1/forward] > 2') + + print('-'*30) + +def q_two(pkt): + print('+'*30) + + print('[Q2/rcvd]') + print(f'[IN] {pkt.get_inint()} {pkt.get_inint(name=True)}') + print(f'[OUT] {pkt.get_outint()} {pkt.get_outint(name=True)}') + + pkt.update_mark(70) + + print(f'[MARK] {pkt.get_initial_mark()} {pkt.get_modified_mark()}') + + pkt.accept() + + print('[Q2/accept]') + + print('-'*30) + +def queue(callback, queue_num): + set_user_callback(print_and_accept) + + nfqueue = NetfilterQueue() + nfqueue.bind(queue_num) + + print(f'[START] QUEUE-{queue_num}') + + try: + nfqueue.run() + except KeyboardInterrupt: + print('') + + finally: + nfqueue.unbind() + +if __name__ == '__main__': + + if (TEST_FORWARD): + threading.Thread(target=queue, args=(q_one, 1)).start() + threading.Thread(target=queue, args=(q_two, 2)).start() + + else: + queue(print_and_accept, 1)