work on new packet
This commit is contained in:
parent
710d45737a
commit
b250f70e33
@ -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
|
||||
|
@ -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
127
nfq_test.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user