Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Python bindings for libnetfilter_queue

License

NotificationsYou must be signed in to change notification settings

oremanj/python-netfilterqueue

Repository files navigation

Latest PyPI versionAutomated test status

NetfilterQueue

NetfilterQueue provides access to packets matched by an iptables rule inLinux. Packets so matched can be accepted, dropped, altered, reordered,or given a mark.

libnetfilter_queue (the netfilter library, not this module) is part of theNetfilter project.

The current version of NetfilterQueue requires Python 3.6 or later.The last version with support for Python 2.7 was 0.9.0.

Example

The following script prints a short description of each packet before acceptingit.

from netfilterqueue import NetfilterQueuedef print_and_accept(pkt):    print(pkt)    pkt.accept()nfqueue = NetfilterQueue()nfqueue.bind(1, print_and_accept)try:    nfqueue.run()except KeyboardInterrupt:    print('')nfqueue.unbind()

You can also make your own socket so that it can be used with gevent, for example.

from netfilterqueue import NetfilterQueueimport socketdef print_and_accept(pkt):    print(pkt)    pkt.accept()nfqueue = NetfilterQueue()nfqueue.bind(1, print_and_accept)s = socket.fromfd(nfqueue.get_fd(), socket.AF_UNIX, socket.SOCK_STREAM)try:    nfqueue.run_socket(s)except KeyboardInterrupt:    print('')s.close()nfqueue.unbind()

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

NetfilterQueue is a C extention module that links against libnetfilter_queue.Before installing, ensure you have:

  1. A C compiler
  2. Python development files
  3. Libnetfilter_queue development files and associated dependencies

On Debian or Ubuntu, install these files with:

apt-get install build-essential python3-dev libnetfilter-queue-dev

From PyPI

To install from PyPI by pip:

pip install NetfilterQueue

From source

To install from source:

pip install cythongit clone https://github.com/oremanj/python-netfilterqueuecd python-netfilterqueuepip install .

API

NetfilterQueue.COPY_NONE,NetfilterQueue.COPY_META,NetfilterQueue.COPY_PACKET
These constants specify how much of the packet should be given to thescript: nothing, metadata, or the whole packet.

NetfilterQueue objects

A NetfilterQueue object represents a single queue. Configure your queue witha call tobind, then start receiving packets with a call torun.

NetfilterQueue.bind(queue_num, callback, max_len=1024, mode=COPY_PACKET, range=65535, sock_len=...)
Create and bind to the queue.queue_num uniquely identifies thisqueue for the kernel. It must match the--queue-num in your iptablesrule, but there is no ordering requirement: it's fine to eitherbind()first or set up the iptables rule first.callback is a function or method that takes oneargument, a Packet object (see below).max_len sets the largest numberof packets that can be in the queue; new packets are dropped if the size ofthe queue reaches this number.mode determines how much of the packetdata is provided to your script. Use the constants above.range defineshow many bytes of the packet you want to get. For example, if you only wantthe source and destination IPs of a IPv4 packet,range could be 20.sock_len sets the receive socket buffer size.
NetfilterQueue.unbind()
Remove the queue. Packets matched by your iptables rule will be dropped.
NetfilterQueue.get_fd()
Get the file descriptor of the socket used to receive queuedpackets and send verdicts. If you're using an async event loop,you can poll this FD for readability and callrun(False) everytime data appears on it.
NetfilterQueue.run(block=True)
Send packets to your callback. By default, this method blocks, runninguntil an exception is raised (such as by Ctrl+C). Setblock=False to process the pending messages without waiting for more;in conjunction with theget_fd method, you can use this to integratewith async event loops.
NetfilterQueue.run_socket(socket)
Send packets to your callback, but use the supplied socket instead ofrecv, so that, for example, gevent can monkeypatch it. You can make asocket withsocket.fromfd(nfqueue.get_fd(), socket.AF_NETLINK, socket.SOCK_RAW)and optionally make it non-blocking withsocket.setblocking(False).

Packet objects

Objects of this type are passed to your callback.

Packet.get_payload()
Return the packet's payload as a bytes object. The returned valuestarts with the IP header. You must callretain() if you wantto be able toget_payload() after your callback has returned.If you have already calledset_payload(), thenget_payload()returns what you passed toset_payload().
Packet.set_payload(payload)
Set the packet payload. Call this beforeaccept() if you want tochange the contents of the packet before allowing it to be released.Don't forget to update the transport-layer checksum (or clear it,if you're using UDP), or else the recipient is likely to drop thepacket. If you're changing the length of the packet, you'll also needto update the IP length, IP header checksum, and probably sometransport-level fields (such as UDP length for UDP).
Packet.get_payload_len()
Return the size of the payload.
Packet.set_mark(mark)
Give the packet a kernel mark, which can be used in future iptablesrules.mark is a 32-bit number.
Packet.get_mark()
Get the mark on the packet (either the one you set usingset_mark(), or the one it arrived with if you haven't calledset_mark()).
Packet.get_hw()
Return the source hardware address of the packet as a Pythonbytestring, orNone if the source hardware address was notcaptured (packets captured by theOUTPUT orPREROUTINGhooks). For example, on Ethernet the result will be a six-byteMAC address. The destination hardware address is not availablebecause it is determined in the kernel only after packet filteringis complete.
Packet.get_timestamp()
Return the time at which this packet was received by the kernel,as a floating-point Unix timestamp with microsecond precision(comparable to the result oftime.time(), for example).Packets captured by theOUTPUT orPOSTROUTING hooksdo not have a timestamp, andget_timestamp() will return 0.0for them.
Packet.id
The identifier assigned to this packet by the kernel. Typicallythe first packet received by your queue starts at 1 and later onescount up from there.
Packet.hw_protocol
The link-layer protocol for this packet. For example, IPv4 packetson Ethernet would have this set to the EtherType for IPv4, which is0x0800.
Packet.mark
The mark that had been assigned to this packet when it was enqueued.Unlike the result ofget_mark(), this does not change if you callset_mark().
Packet.hook
The netfilter hook (iptables chain, roughly) that diverted this packetinto our queue. Values 0 through 4 correspond to PREROUTING, INPUT,FORWARD, OUTPUT, and POSTROUTING respectively.
Packet.indev,Packet.outdev,Packet.physindev,Packet.physoutdev
The interface indices on which the packet arrived (indev) or is slatedto depart (outdev). These are integers, which can be converted tonames like "eth0" by usingsocket.if_indextoname(). Zero meansno interface is applicable, either because the packet was locally generatedor locally received, or because the interface information wasn't availablewhen the packet was queued (for example,PREROUTING rules don't yetknow theoutdev). If theindev oroutdev refers to a bridgedevice, then the correspondingphysindev orphysoutdev will namethe bridge member on which the actual traffic occurred; otherwisephysindev andphysoutdev will be zero.
Packet.retain()
Allocate a copy of the packet payload for use after the callbackhas returned.get_payload() will raise an exception at thatpoint if you didn't callretain().
Packet.accept()
Accept the packet. You can reorder packets by accepting themin a different order than the order in which they were passedto your callback.
Packet.drop()
Drop the packet.
Packet.repeat()
Restart processing of this packet from the beginning of itsNetfilter hook (iptables chain, roughly). Any changes madeusingset_payload() orset_mark() are preserved; in theabsence of such changes, the packet will probably come rightback to the same queue.

Callback objects

Your callback can be any one-argument callable and will be invoked withaPacket object as argument. You must callretain() within thecallback if you want to be able toget_payload() after the callbackhas returned. You can hang ontoPacket objects and resolve them later,but note that packets continue to count against the queue size limituntil they've been given a verdict (accept, drop, or repeat). Also, thekernel stores the enqueued packets in a linked list, so keeping lots of packetsoutstanding is likely to adversely impact performance.

Monitoring a different network namespace

If you are using Linux network namespaces (man 7network_namespaces) in some kind of containerization system, all ofthe Netfilter queue state is kept per-namespace; queue 1 in namespaceX is not the same as queue 1 in namespace Y. NetfilterQueue willordinarily pass you the traffic for the network namespace you're apart of. If you want to monitor a different one, you can do so with abit of trickery and cooperation from a process in thatnamespace; this section describes how.

You'll need to arrange for a process in the network namespace you wantto monitor to callsocket(AF_NETLINK, SOCK_RAW, 12) and pass youthe resulting file descriptor using something likesocket.send_fds() over a Unix domain socket. (12 isNETLINK_NETFILTER, a constant which is not exposed by the Pythonsocket module.) Once you've received that file descriptor in yourprocess, you can create a NetfilterQueue object using the specialconstructorNetfilterQueue(sockfd=N) where N is the filedescriptor you received. Because the socket was originally createdin the other network namespace, the kernel treats it as part of thatnamespace, and you can use it to access that namespace even though it'snot the namespace you're in yourself.

Usage

To send 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 andcan be added to any table or chain.

Valid queue numbers are integers from 0 to 65,535 inclusive.

To view libnetfilter_queue stats, refer to /proc/net/netfilter/nfnetlink_queue:

cat /proc/net/netfilter/nfnetlink_queue1  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. Something for libnetfilter_queue's internal use

Limitations

  • We use a fixed-size 4096-byte buffer for packets, so you are likelyto see truncation on loopback and on Ethernet with jumbo packets.If this is a problem, either lower the MTU on your loopback, disablejumbo packets, or get Cython, changeDEF BufferSize = 4096 innetfilterqueue.pyx, and rebuild.
  • Not all information available from libnetfilter_queue is exposed:missing pieces include packet input/output network interface names,checksum offload flags, UID/GID and security context dataassociated with the packet (if any).
  • Not all information available from the kernel is even processed bylibnetfilter_queue: missing pieces include additional link-layerheader data for some packets (including VLAN tags), connection-trackingstate, and incoming packet length (if truncated for queueing).
  • We do not expose the libnetfilter_queue interface for changing queue flags.Most of these pertain to other features we don't support (listed above),but there's one that could set the queue to accept (rather than dropping)packets received when it's full.

Source

https://github.com/oremanj/python-netfilterqueue

Authorship

python-netfilterqueue was originally written by Matthew Fox ofKerkhoff Technologies, Inc. Since 2022 it has been maintained byJoshua Oreman of Hudson River Trading LLC. Both authors wish tothank their employers for their support of open source.

License

Copyright (c) 2011, Kerkhoff Technologies, Inc, and contributors.

MIT licensed

About

Python bindings for libnetfilter_queue

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors12


[8]ページ先頭

©2009-2025 Movatter.jp