work on new packet

This commit is contained in:
dowright 2021-08-27 12:33:39 -07:00 committed by DOWRIGHT
parent 710d45737a
commit b250f70e33
3 changed files with 158 additions and 54 deletions

View File

@ -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

View File

@ -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(<char*>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(),
)

127
nfq_test.py Normal file
View File

@ -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)