Example #1
0
def nfq_hook_cb(qh, nfmsg, nfad, data):
    """
    int nfq_callback(struct nfq_q_handle *qh,
                     struct nfgenmsg *nfmsg,
                     struct nfq_data *nfad, void *data);
    """
    packet_id = NFQ.cb_get_packet_id(nfad)
    ip_bytes = NFQ.cb_get_payload(nfad)
    this_id = data
    this = ctypes.cast(this_id, ctypes.py_object).value
    assert isinstance(this, NFQHook)
    this.send_ip_packet_to_inspector(packet_id, ip_bytes)
    return 1
Example #2
0
def cb(qh, nfmsg, nfad, data):
    """
    int nfq_callback(struct nfq_q_handle *qh,
                     struct nfgenmsg *nfmsg,
                     struct nfq_data *nfad, void *data);
    """
    payload = NFQ.cb_get_payload(nfad)
    packet_id = NFQ.cb_get_packet_id(nfad)
    ip = IP(payload)
    LOG.info("ID %d: %s", packet_id, ip.summary())
    sleep(SLEEP_SECS)
    NFQ.cb_set_verdict(qh, packet_id, NFQ.NF_ACCEPT)
    return 1
Example #3
0
 def __init__(self, nfq_number, zmq_addr):
     LOG.info('NFQ Number: %s', nfq_number)
     assert isinstance(nfq_number, int)
     self.self_id = id(self)
     self.nfq = NFQ(nfq_number,
                    nfq_hook_cb_c,
                    ctypes.c_void_p(self.self_id))
     self.zmq_client = NFQHookZMQC(zmq_addr, self.nfq)
Example #4
0
class NFQHook(object):
    NFQ_SOCKET_BUFFER_SIZE = 1024 * 4

    def __init__(self, nfq_number, zmq_addr):
        LOG.info('NFQ Number: %s', nfq_number)
        assert isinstance(nfq_number, int)
        self.self_id = id(self)
        self.nfq = NFQ(nfq_number,
                       nfq_hook_cb_c,
                       ctypes.c_void_p(self.self_id))
        self.zmq_client = NFQHookZMQC(zmq_addr, self.nfq)

    def start(self):
        zmq_worker_handle = self.zmq_client.start()
        nfq_worker_handle = eventlet.spawn(self._nfq_worker)
        nfq_worker_handle.wait()
        zmq_worker_handle.wait()
        raise RuntimeError('should not reach here')

    def _nfq_worker(self):
        s = socket.fromfd(self.nfq.fd, socket.AF_UNIX, socket.SOCK_STREAM)
        try:
            while True:
                LOG.debug('NFQ Recv')
                nfad = s.recv(self.NFQ_SOCKET_BUFFER_SIZE)
                self.nfq.handle_packet(nfad)
            LOG.error('NFQ Worker loop leave!')
        finally:
            LOG.error('NFQ Worker closing socket!')
            s.close()
            self.nfq.close()
            sys.exit(1)

    def send_ip_packet_to_inspector(self, packet_id, ip_bytes):
        LOG.debug('Sending packet %d to inspector', packet_id)

        # from hexdump import hexdump
        # for l in hexdump(ip_bytes, result='generator'):
        #     LOG.debug(l)

        # TODO: eliminate dummy eth header
        dummy_eth = '\xff\xff\xff\xff\xff\xff' + '\x00\x00\x00\x00\x00\x00' + '\x08\x00' + ip_bytes
        self.zmq_client.send(packet_id, dummy_eth)
Example #5
0
 def on_drop(self, packet_id, eth_bytes, metadata=None):
     NFQ.cb_set_verdict(self.nfq.qh, packet_id, NFQ.NF_DROP)
Example #6
0
 def on_accept(self, packet_id, eth_bytes, metadata=None):
     NFQ.cb_set_verdict(self.nfq.qh, packet_id, NFQ.NF_ACCEPT)
Example #7
0
def cb(qh, nfmsg, nfad, data):
    """
    int nfq_callback(struct nfq_q_handle *qh,
                     struct nfgenmsg *nfmsg,
                     struct nfq_data *nfad, void *data);
    """
    payload = NFQ.cb_get_payload(nfad)
    packet_id = NFQ.cb_get_packet_id(nfad)
    ip = IP(payload)
    LOG.info("ID %d: %s", packet_id, ip.summary())
    sleep(SLEEP_SECS)
    NFQ.cb_set_verdict(qh, packet_id, NFQ.NF_ACCEPT)
    return 1

cb_c = NFQ.CALLBACK_CFUNCTYPE(cb) # https://github.com/JohannesBuchner/PyMultiNest/issues/5


if __name__ == '__main__':
    LOG.info("Please run `iptables -A OUTPUT -p tcp -m owner --uid-owner $(id -u nfqhooked) -j NFQUEUE --queue-num 42` before running this hook.")
    LOG.info("and then run `sudo -u nfqhooked SOME_COMMAND`")

    nfq = NFQ(NFQ_NUMBER, cb_c)
    s = socket.fromfd(nfq.fd, socket.AF_UNIX, socket.SOCK_STREAM)
    while True:
        d = s.recv(SOCK_BUF_SIZE)
        assert d
        nfq.handle_packet(d)
    s.close()
    nfq.close()