Add details to README.
This commit is contained in:
parent
f5e0ad83ad
commit
a3676c4394
58
README.rst
58
README.rst
|
@ -10,7 +10,22 @@ Libnetfilter_queue (the netfilter library, not this module) is part of the `Netf
|
|||
Example
|
||||
=======
|
||||
|
||||
Coming soon...
|
||||
The following script prints a short description of each packet before accepting it::
|
||||
|
||||
from netfilterqueue import NetfilterQueue
|
||||
|
||||
class PacketPrinter(NetfilterQueue):
|
||||
def handle(self, packet):
|
||||
print packet
|
||||
packet.accept()
|
||||
|
||||
p = PacketPrinter()
|
||||
p.bind(1)
|
||||
p.run()
|
||||
|
||||
To send packets destined for your LAN to the script, type something like::
|
||||
|
||||
iptables -I INPUT -d 192.168.0.0/24 -j NFQUEUE --queue-num 1
|
||||
|
||||
Installation
|
||||
============
|
||||
|
@ -46,20 +61,53 @@ To install from source::
|
|||
|
||||
Setup will use Cython if it is installed, regenerating the .c source from the .pyx before compiling the .so.
|
||||
|
||||
Usage
|
||||
=====
|
||||
API
|
||||
===
|
||||
|
||||
Coming soon...
|
||||
|
||||
Now route packets to the queue::
|
||||
Usage
|
||||
=====
|
||||
|
||||
# iptables -I INPUT -p tcp --dport 80 -j NFQUEUE --queue-num 1
|
||||
To route packets to the queue::
|
||||
|
||||
iptables -I <table or chain> <match specification> -j NFQUEUE --queue-num <queue number>
|
||||
|
||||
For example::
|
||||
|
||||
iptables -I INPUT -d 192.168.0.0/24 -j NFQUEUE --queue-num 1
|
||||
|
||||
The only special part of the rule is the target. Rules can have any match and
|
||||
can be added to any table or chain.
|
||||
|
||||
Valid queue numbers are integers from 0 to 65,536 inclusive.
|
||||
|
||||
To view libnetfilter_queue stats, refer to /proc/net/netfilter/nfnetlink_queue::
|
||||
|
||||
cat /proc/net/netfilter/nfnetlink_queue
|
||||
1 31621 0 2 4016 0 0 2 1
|
||||
|
||||
The fields are:
|
||||
|
||||
1. Queue ID
|
||||
|
||||
2. Bound process ID
|
||||
|
||||
3. Number of currently queued packets
|
||||
|
||||
4. Copy mode
|
||||
|
||||
5. Copy size
|
||||
|
||||
6. Number of packets dropped due to reaching max queue size
|
||||
|
||||
7. Number of packets dropped due to netlink socket failure
|
||||
|
||||
8. Total number of packets sent to queue
|
||||
|
||||
9. Libnetfilter_queue internal use
|
||||
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
|
|
2969
netfilterqueue.c
2969
netfilterqueue.c
File diff suppressed because it is too large
Load Diff
|
@ -148,7 +148,7 @@ cdef enum:
|
|||
NF_STOP
|
||||
NF_MAX_VERDICT = NF_STOP
|
||||
|
||||
cdef class NFPacket:
|
||||
cdef class Packet:
|
||||
cdef nfq_q_handle *_qh
|
||||
cdef nfq_data *_nfa
|
||||
cdef nfqnl_msg_packet_hdr *_hdr
|
||||
|
@ -183,7 +183,7 @@ cdef class NFPacket:
|
|||
cpdef accept(self)
|
||||
cpdef drop(self)
|
||||
|
||||
cdef class NFQueue:
|
||||
cdef class NetfilterQueue:
|
||||
cdef nfq_handle *h # Handle to NFQueue library
|
||||
cdef nfq_q_handle *qh # A handle to the queue
|
||||
cdef u_int16_t af # Address family
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
## cython: profile=True
|
||||
import socket
|
||||
|
||||
# Constants for module users
|
||||
COPY_NONE = 1
|
||||
COPY_META = 2
|
||||
COPY_PACKET = 3
|
||||
|
||||
DEFAULT_MAX_QUEUELEN = 1024
|
||||
|
||||
# Packet copying defaults
|
||||
DEF MaxPacketSize = 0xFFFF
|
||||
DEF BufferSize = 4096
|
||||
|
@ -14,28 +14,14 @@ DEF MaxCopySize = BufferSize - MetadataSize
|
|||
|
||||
cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
|
||||
nfq_data *nfa, void *data) with gil:
|
||||
"""
|
||||
Create an NFPacket and pass it to appropriate Python/Cython callback.
|
||||
|
||||
Working in a Python or Cython callback, rather than directly in this
|
||||
callback, results in a ~7% performance hit.
|
||||
"""
|
||||
# cdef nfqnl_msg_packet_hdr *_hdr = nfq_get_msg_packet_hdr(nfa)
|
||||
# cdef u_int32_t id = ntohl(_hdr.packet_id)
|
||||
# nfq_set_verdict(
|
||||
# qh,
|
||||
# id,
|
||||
# NF_ACCEPT,
|
||||
# 0, # TODO: adapt to use self._given_payload
|
||||
# NULL # TODO: adapt to use self._given_payload
|
||||
# )
|
||||
packet = NFPacket()
|
||||
"""Create an Packet and pass it to appropriate Python/Cython callback."""
|
||||
packet = Packet()
|
||||
packet.set_nfq_data(qh, nfa)
|
||||
(<NFQueue>data).handle(packet)
|
||||
(<NetfilterQueue>data).handle(packet)
|
||||
return 1
|
||||
|
||||
cdef class NFPacket:
|
||||
"""A packet received from NFQueue."""
|
||||
cdef class Packet:
|
||||
"""A packet received from NetfilterQueue."""
|
||||
def __cinit__(self):
|
||||
self._verdict_is_set = False
|
||||
self._mark_is_set = False
|
||||
|
@ -43,10 +29,7 @@ cdef class NFPacket:
|
|||
|
||||
def __str__(self):
|
||||
cdef iphdr *hdr = <iphdr*>self.payload
|
||||
protocol = "Unknown protocol"
|
||||
for name in filter(lambda x: x.startswith("IPPROTO"), dir(socket)):
|
||||
if getattr(socket, name) == hdr.protocol:
|
||||
protocol = name[8:]
|
||||
protocol = PROTOCOLS.get(hdr.protocol, "Unknown protocol")
|
||||
return "%s packet, %s bytes" % (protocol, self.payload_len)
|
||||
|
||||
cdef set_nfq_data(self, nfq_q_handle *qh, nfq_data *nfa):
|
||||
|
@ -70,9 +53,9 @@ cdef class NFPacket:
|
|||
|
||||
cdef void verdict(self, u_int8_t verdict):
|
||||
"""Call appropriate set_verdict... function on packet."""
|
||||
#if self._verdict_is_set:
|
||||
# raise RuntimeWarning("Verdict already given for this packet.")
|
||||
|
||||
if self._verdict_is_set:
|
||||
raise RuntimeWarning("Verdict already given for this packet.")
|
||||
|
||||
if self._mark_is_set:
|
||||
nfq_set_verdict_mark( # TODO: make this use nfq_set_verdict2 if available on system
|
||||
self._qh,
|
||||
|
@ -91,9 +74,10 @@ cdef class NFPacket:
|
|||
NULL # TODO: adapt to use self._given_payload
|
||||
)
|
||||
|
||||
#self._verdict_is_set = True
|
||||
self._verdict_is_set = True
|
||||
|
||||
def get_payload(self):
|
||||
"""Return payload as Python string."""
|
||||
cdef object py_string = PyString_FromStringAndSize(self.payload, self.payload_len)
|
||||
return py_string
|
||||
|
||||
|
@ -120,13 +104,10 @@ cdef class NFPacket:
|
|||
"""Drop the packet."""
|
||||
self.verdict(NF_DROP)
|
||||
|
||||
cdef class NFQueue:
|
||||
cdef class NetfilterQueue:
|
||||
"""Handle a single numbered queue."""
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
if "af" in kwargs:
|
||||
self.af = kwargs["af"]
|
||||
else:
|
||||
self.af = socket.AF_INET
|
||||
self.af = kwargs.get("af", PF_INET)
|
||||
|
||||
self.h = nfq_open()
|
||||
if self.h == NULL:
|
||||
|
@ -134,7 +115,7 @@ cdef class NFQueue:
|
|||
nfq_unbind_pf(self.h, self.af) # This does NOT kick out previous
|
||||
# running queues
|
||||
if nfq_bind_pf(self.h, self.af) < 0:
|
||||
raise OSError("Failed to bind family %s." % self.af)
|
||||
raise OSError("Failed to bind family %s. Are you root?" % self.af)
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.qh != NULL:
|
||||
|
@ -143,9 +124,9 @@ cdef class NFQueue:
|
|||
# processes using this libnetfilter_queue on this protocol family!
|
||||
nfq_close(self.h)
|
||||
|
||||
def bind(self, object handler, int queue_num, u_int32_t maxlen, u_int8_t mode=NFQNL_COPY_PACKET, u_int32_t range=MaxPacketSize):
|
||||
"""Create a new queue with the given callback function."""
|
||||
self.qh = nfq_create_queue(self.h, queue_num, <nfq_callback*>global_callback, <void*>handler)
|
||||
def bind(self, int queue_num, u_int32_t maxlen=DEFAULT_MAX_QUEUELEN, u_int8_t mode=NFQNL_COPY_PACKET, u_int32_t range=MaxPacketSize):
|
||||
"""Create and bind to a new queue."""
|
||||
self.qh = nfq_create_queue(self.h, queue_num, <nfq_callback*>global_callback, <void*>self)
|
||||
if self.qh == NULL:
|
||||
raise OSError("Failed to create queue %s." % queue_num)
|
||||
|
||||
|
@ -174,6 +155,151 @@ cdef class NFQueue:
|
|||
with nogil:
|
||||
rv = recv(fd, buf, sizeof(buf), 0)
|
||||
|
||||
def handle(self, NFPacket packet):
|
||||
def handle(self, Packet packet):
|
||||
"""Handle a single packet. User-defined classes should override this."""
|
||||
packet.accept()
|
||||
|
||||
PROTOCOLS = {
|
||||
0: "HOPOPT",
|
||||
1: "ICMP",
|
||||
2: "IGMP",
|
||||
3: "GGP",
|
||||
4: "IP",
|
||||
5: "ST",
|
||||
6: "TCP",
|
||||
7: "CBT",
|
||||
8: "EGP",
|
||||
9: "IGP",
|
||||
10: "BBN-RCC-MON",
|
||||
11: "NVP-II",
|
||||
12: "PUP",
|
||||
13: "ARGUS",
|
||||
14: "EMCON",
|
||||
15: "XNET",
|
||||
16: "CHAOS",
|
||||
17: "UDP",
|
||||
18: "MUX",
|
||||
19: "DCN-MEAS",
|
||||
20: "HMP",
|
||||
21: "PRM",
|
||||
22: "XNS-IDP",
|
||||
23: "TRUNK-1",
|
||||
24: "TRUNK-2",
|
||||
25: "LEAF-1",
|
||||
26: "LEAF-2",
|
||||
27: "RDP",
|
||||
28: "IRTP",
|
||||
29: "ISO-TP4",
|
||||
30: "NETBLT",
|
||||
31: "MFE-NSP",
|
||||
32: "MERIT-INP",
|
||||
33: "DCCP",
|
||||
34: "3PC",
|
||||
35: "IDPR",
|
||||
36: "XTP",
|
||||
37: "DDP",
|
||||
38: "IDPR-CMTP",
|
||||
39: "TP++",
|
||||
40: "IL",
|
||||
41: "IPv6",
|
||||
42: "SDRP",
|
||||
43: "IPv6-Route",
|
||||
44: "IPv6-Frag",
|
||||
45: "IDRP",
|
||||
46: "RSVP",
|
||||
47: "GRE",
|
||||
48: "DSR",
|
||||
49: "BNA",
|
||||
50: "ESP",
|
||||
51: "AH",
|
||||
52: "I-NLSP",
|
||||
53: "SWIPE",
|
||||
54: "NARP",
|
||||
55: "MOBILE",
|
||||
56: "TLSP",
|
||||
57: "SKIP",
|
||||
58: "IPv6-ICMP",
|
||||
59: "IPv6-NoNxt",
|
||||
60: "IPv6-Opts",
|
||||
61: "any host internal protocol",
|
||||
62: "CFTP",
|
||||
63: "any local network",
|
||||
64: "SAT-EXPAK",
|
||||
65: "KRYPTOLAN",
|
||||
66: "RVD",
|
||||
67: "IPPC",
|
||||
68: "any distributed file system",
|
||||
69: "SAT-MON",
|
||||
70: "VISA",
|
||||
71: "IPCV",
|
||||
72: "CPNX",
|
||||
73: "CPHB",
|
||||
74: "WSN",
|
||||
75: "PVP",
|
||||
76: "BR-SAT-MON",
|
||||
77: "SUN-ND",
|
||||
78: "WB-MON",
|
||||
79: "WB-EXPAK",
|
||||
80: "ISO-IP",
|
||||
81: "VMTP",
|
||||
82: "SECURE-VMTP",
|
||||
83: "VINES",
|
||||
84: "TTP",
|
||||
85: "NSFNET-IGP",
|
||||
86: "DGP",
|
||||
87: "TCF",
|
||||
88: "EIGRP",
|
||||
89: "OSPFIGP",
|
||||
90: "Sprite-RPC",
|
||||
91: "LARP",
|
||||
92: "MTP",
|
||||
93: "AX.25",
|
||||
94: "IPIP",
|
||||
95: "MICP",
|
||||
96: "SCC-SP",
|
||||
97: "ETHERIP",
|
||||
98: "ENCAP",
|
||||
99: "any private encryption scheme",
|
||||
100: "GMTP",
|
||||
101: "IFMP",
|
||||
102: "PNNI",
|
||||
103: "PIM",
|
||||
104: "ARIS",
|
||||
105: "SCPS",
|
||||
106: "QNX",
|
||||
107: "A/N",
|
||||
108: "IPComp",
|
||||
109: "SNP",
|
||||
110: "Compaq-Peer",
|
||||
111: "IPX-in-IP",
|
||||
112: "VRRP",
|
||||
113: "PGM",
|
||||
114: "any 0-hop protocol",
|
||||
115: "L2TP",
|
||||
116: "DDX",
|
||||
117: "IATP",
|
||||
118: "STP",
|
||||
119: "SRP",
|
||||
120: "UTI",
|
||||
121: "SMP",
|
||||
122: "SM",
|
||||
123: "PTP",
|
||||
124: "ISIS",
|
||||
125: "FIRE",
|
||||
126: "CRTP",
|
||||
127: "CRUDP",
|
||||
128: "SSCOPMCE",
|
||||
129: "IPLT",
|
||||
130: "SPS",
|
||||
131: "PIPE",
|
||||
132: "SCTP",
|
||||
133: "FC",
|
||||
134: "RSVP-E2E-IGNORE",
|
||||
135: "Mobility",
|
||||
136: "UDPLite",
|
||||
137: "MPLS-in-IP",
|
||||
138: "manet",
|
||||
139: "HIP",
|
||||
140: "Shim6",
|
||||
255: "Reserved",
|
||||
}
|
Loading…
Reference in New Issue