nfqueue

package module
v0.0.0-...-d4fef8a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2018 License: Apache-2.0 Imports: 4 Imported by: 4

README

Build Status

nfqueue

nfqueue is a go binding to libnetfilter_queue.

It implements partially the libnetfilter_queue functionality. Currently, it provides:

  • Start a netfilter queue
  • Stop a netfilter queue
  • Handle a packet received by netfilter queue and accept, drop or modify it.
  • Configure the netfilter queue

See more information about libnetfilter_queue.

Using library

import "github.com/Telefonica/nfqueue"

Netfilter queue configuration

It is possible to pass a configuration object with optional settings to tune the netfilter queue.

Setting Description
MaxPackets Maximum amount of packets that can be enqueued in a netfilter queue
QueueFlags Slice of QueueFlag elements. See following table with the list of possible queue flags
BufferSize Modify the default nfnetlink buffer size
// QueueConfig contains optional configuration parameters to initialize a queue.
type QueueConfig struct {
	MaxPackets uint32
	QueueFlags []QueueFlag
	BufferSize uint32
}

The following table lists the queue flags. Note that some queue flags may be unavailable depending on the linux kernel version.

QueueFlag Description
FailOpen (requires Linux kernel >= 3.6) The kernel will accept the packets if the kernel queue gets full. If this flag is not set, the default action in this case is to drop packets.
Conntrack (requires Linux kernel >= 3.6) The kernel will include the Connection Tracking system information.
GSO (requires Linux kernel >= 3.10) The kernel will not normalize offload packets, i.e. your application will need to be able to handle packets larger than the mtu.
UIDGid It makes the kernel dump UID and GID of the socket to which each packet belongs.
Secctx It makes the kernel dump security context of the socket to which each packet belongs.

Packet and packet handler

Each packet that is processed by a netfilter queue is encapsulated in the type Packet that contains a byte slice with the packet buffer (starting with the IP layer). This buffer can be parsed with gopacket. It also provides an interface to accept, drop or modify the packet.

// Packet struct provides the packet data and methods to accept, drop or modify the packet.
type Packet struct {
	Buffer []byte
	id     uint32
	q      *Queue
}

// Accept the packet.
func (p *Packet) Accept() error {...}
// Drop the packet.
func (p *Packet) Drop() error {...}
// Modify the packet with a new buffer.
func (p *Packet) Modify(buffer []byte) error {...}

To receive these packets, the client needs to implement the PacketHandler interface.

// PacketHandler is an interface to handle a packet retrieved by netfilter.
type PacketHandler interface {
	Handle(p *Packet)
}

Example

The following example instantiates a netfilter queue (with 1 as queue identifier) and the packet handler accepts all the packets.

import (
	"github.com/Telefonica/nfqueue"
)

type Queue struct {
	id    uint16
	queue *nfqueue.Queue
}

func NewQueue(id uint16) *Queue {
	q := &Queue{
		id: id,
	}
	queueCfg := &nfqueue.QueueConfig{
		MaxPackets: 1000,
		BufferSize: 16 * 1024 * 1024,
		QueueFlags: []nfqueue.QueueFlag{nfqueue.FailOpen},
	}
	// Pass as packet handler the current instance because it implements nfqueue.PacketHandler interface
	q.queue = nfqueue.NewQueue(q.id, q, queueCfg)
	return q
}

// Start the queue.
func (q *Queue) Start() error {
	return q.queue.Start()
}

// Stop the queue.
func (q *Queue) Stop() error {
	return q.queue.Stop()
}

// Handle a nfqueue packet. It implements nfqueue.PacketHandler interface.
func (q *Queue) Handle(p *nfqueue.Packet) {
	// Accept the packet
	p.Accept()
}

func main() {
	q := NewQueue(1)
	go q.Start()
}

Performance

This library is inspired in other nfqueue go bindings. The main difference is that our design does not use go channels to process the packets to avoid introducing an overhead that degrades performance. Note that nfqueue cannot process multiple packets from the same queue concurrently.

The following table compares nfqueue with freki using a host with 4 CPU cores:

Library 2 queues 4 queues
freki 25000 req/s 22000 req/s
nfqueue 22000 req/s 38500 req/s

Tuning the amount of nfqueue queues with the amount of CPU cores, this library achieves a 75% improvement over freki.

License

Copyright 2018 Telefónica Investigación y Desarrollo, S.A.U

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Packet

type Packet struct {
	Buffer []byte
	// contains filtered or unexported fields
}

Packet struct provides the packet data and methods to accept, drop or modify the packet.

func (*Packet) Accept

func (p *Packet) Accept() error

Accept the packet.

func (*Packet) Drop

func (p *Packet) Drop() error

Drop the packet.

func (*Packet) Modify

func (p *Packet) Modify(buffer []byte) error

Modify the packet with a new buffer.

type PacketHandler

type PacketHandler interface {
	Handle(p *Packet)
}

PacketHandler is an interface to handle a packet retrieved by netfilter.

type Queue

type Queue struct {
	ID uint16
	// contains filtered or unexported fields
}

Queue represents a netfilter queue with methods to start processing the packets (Run) and to stop

func NewQueue

func NewQueue(queueID uint16, handler PacketHandler, cfg *QueueConfig) *Queue

NewQueue creates a Queue instance and registers it.

func (*Queue) Start

func (q *Queue) Start() error

Start the processing of packets from the netfilter queue. This method initializes the netfilter queue and configures it. The thread is blocked until the queue is stopped externally.

func (*Queue) Stop

func (q *Queue) Stop() error

Stop the netfilter queue.

type QueueConfig

type QueueConfig struct {
	MaxPackets uint32
	QueueFlags []QueueFlag
	BufferSize uint32
}

QueueConfig contains optional configuration parameters to initialize a queue.

type QueueFlag

type QueueFlag C.uint32_t

QueueFlag configures the kernel queue.

const (
	// FailOpen (requires Linux kernel >= 3.6): the kernel will accept the packets if the kernel queue gets full.
	// If this flag is not set, the default action in this case is to drop packets.
	FailOpen QueueFlag = (1 << 0)
	// Conntrack (requires Linux kernel >= 3.6): the kernel will include the Connection Tracking system information.
	Conntrack QueueFlag = (1 << 1)
	// GSO (requires Linux kernel >= 3.10): the kernel will not normalize offload packets,
	// i.e. your application will need to be able to handle packets larger than the mtu.
	GSO QueueFlag = (1 << 2)
	// UIDGid makes the kernel dump UID and GID of the socket to which each packet belongs.
	UIDGid QueueFlag = (1 << 3)
	// Secctx makes the kernel dump security context of the socket to which each packet belongs.
	Secctx QueueFlag = (1 << 4)
)

type QueueRegistry

type QueueRegistry struct {
	// contains filtered or unexported fields
}

QueueRegistry stores a list of the netfilter queues registered. It returns a Queue based on the queue ID so that it is possible to build up a singleton registry to interact with netfilter library. This registry is not thread-safe on purpose. Queues should be registered before started.

func NewQueueRegistry

func NewQueueRegistry() *QueueRegistry

NewQueueRegistry creates an instance of QueueRegistry.

func (*QueueRegistry) Get

func (r *QueueRegistry) Get(queueID uint16) *Queue

Get returns a queue from the registry based on the queueID.

func (*QueueRegistry) Register

func (r *QueueRegistry) Register(queueID uint16, queue *Queue)

Register adds a queue to the registry.

func (*QueueRegistry) Unregister

func (r *QueueRegistry) Unregister(queueID uint16)

Unregister removes a queue from the registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL