Documentation ¶
Overview ¶
Package conntrack implements the Conntrack subsystem of the Netfilter (Netlink) protocol family. The package is intended to be clear, user-friendly, thoroughly tested and easy to understand.
It is purely written in Go, without any dependency on Cgo or any C library, kernel headers or userspace tools. It uses a native Netlink implementation (https://github.com/mdlayher/netlink) and does not parse or scrape any output of the `conntrack` command.
It is designed in a way that makes the user acquainted with the structure of the protocol, with a clean separation between the Conntrack types/attributes and the Netfilter layer (implemented in https://github.com/ti-mo/netfilter).
All Conntrack attributes known to the kernel up until version 4.17 are implemented. There is experimental support for manipulating Conntrack 'expectations', beside listening and dumping. The original focus of the package was receiving Conntrack events over Netlink multicast sockets, but was since expanded to be a full implementation supporting queries.
Index ¶
- Constants
- type Conn
- func (c *Conn) Close() error
- func (c *Conn) Create(f Flow) error
- func (c *Conn) CreateExpect(ex Expect) error
- func (c *Conn) Delete(f Flow) error
- func (c *Conn) Dump(opts *DumpOptions) ([]Flow, error)
- func (c *Conn) DumpExpect() ([]Expect, error)
- func (c *Conn) DumpFilter(f Filter, opts *DumpOptions) ([]Flow, error)
- func (c *Conn) Flush() error
- func (c *Conn) FlushFilter(f Filter) error
- func (c *Conn) Get(f Flow) (Flow, error)
- func (c *Conn) Listen(evChan chan<- Event, numWorkers uint8, groups []netfilter.NetlinkGroup) (chan error, error)
- func (c *Conn) SetOption(option netlink.ConnOption, enable bool) error
- func (c *Conn) SetReadBuffer(bytes int) error
- func (c *Conn) SetWriteBuffer(bytes int) error
- func (c *Conn) Stats() ([]Stats, error)
- func (c *Conn) StatsExpect() ([]StatsExpect, error)
- func (c *Conn) StatsGlobal() (StatsGlobal, error)
- func (c *Conn) Update(f Flow) error
- type Counter
- type DumpOptions
- type Event
- type Expect
- type ExpectNAT
- type Filter
- type Flow
- type Helper
- type IPTuple
- type ProtoInfo
- type ProtoInfoDCCP
- type ProtoInfoSCTP
- type ProtoInfoTCP
- type ProtoTuple
- type Security
- type SequenceAdjust
- type Stats
- type StatsExpect
- type StatsGlobal
- type Status
- func (s Status) Assured() bool
- func (s Status) Confirmed() bool
- func (s Status) DstNAT() bool
- func (s Status) DstNATDone() bool
- func (s Status) Dying() bool
- func (s Status) Expected() bool
- func (s Status) FixedTimeout() bool
- func (s Status) Helper() bool
- func (s Status) Offload() bool
- func (s Status) SeenReply() bool
- func (s Status) SeqAdjust() bool
- func (s Status) SrcNAT() bool
- func (s Status) SrcNATDone() bool
- func (s Status) String() string
- func (s Status) Template() bool
- type StatusFlag
- type SynProxy
- type Timestamp
- type Tuple
Examples ¶
Constants ¶
const ( EventUnknown eventType = iota EventNew EventUpdate EventDestroy EventExpNew EventExpDestroy )
List of all types of Conntrack events. This is an internal representation unrelated to any message types in the kernel source.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Conn ¶
type Conn struct {
// contains filtered or unexported fields
}
Conn represents a Netlink connection to the Netfilter subsystem and implements all Conntrack actions.
Example (CreateUpdateFlow) ¶
package main import ( "log" "net/netip" "github.com/ti-mo/conntrack" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } // Set up a new Flow object using a given set of attributes. f := conntrack.NewFlow( 17, 0, netip.MustParseAddr("2a00:1450:400e:804::200e"), netip.MustParseAddr("2a00:1450:400e:804::200f"), 1234, 80, 120, 0, ) // Send the Flow to the kernel. err = c.Create(f) if err != nil { log.Fatal(err) } f.Timeout = 240 // Update the Flow's timeout to 240 seconds. err = c.Update(f) if err != nil { log.Fatal(err) } // Query the kernel based on the Flow's source/destination tuples. // Returns a new Flow object with its connection ID assigned by the kernel. qf, err := c.Get(f) if err != nil { log.Fatal(err) } // Print the result. The Flow has a timeout greater than 120 seconds. log.Print(qf) }
Output:
Example (Delete) ¶
package main import ( "log" "net/netip" "github.com/ti-mo/conntrack" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } f := conntrack.NewFlow( 6, 0, netip.MustParseAddr("1.2.3.4"), netip.MustParseAddr("5.6.7.8"), 1234, 80, 120, 0, ) // Create the Flow, will return err if unsuccessful. err = c.Create(f) if err != nil { log.Fatal(err) } // Delete the Flow based on its IP/port tuple, will return err if unsuccessful. err = c.Delete(f) if err != nil { log.Fatal(err) } }
Output:
Example (DumpFilter) ¶
package main import ( "log" "net/netip" "github.com/ti-mo/conntrack" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } f1 := conntrack.NewFlow( 6, 0, netip.MustParseAddr("1.2.3.4"), netip.MustParseAddr("5.6.7.8"), 1234, 80, 120, 0x00ff, // Set a connection mark ) f2 := conntrack.NewFlow( 17, 0, netip.MustParseAddr("2a00:1450:400e:804::200e"), netip.MustParseAddr("2a00:1450:400e:804::200f"), 1234, 80, 120, 0xff00, // Set a connection mark ) _ = c.Create(f1) _ = c.Create(f2) // Dump all records in the Conntrack table that match the filter's mark/mask. df, err := c.DumpFilter(conntrack.Filter{Mark: 0xff00, Mask: 0xff00}, nil) if err != nil { log.Fatal(err) } // Print the result. Only f2 is displayed. log.Print(df) }
Output:
Example (Flush) ¶
package main import ( "log" "github.com/ti-mo/conntrack" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } // Evict all entries from the conntrack table in the current network namespace. err = c.Flush() if err != nil { log.Fatal(err) } }
Output:
Example (FlushFilter) ¶
package main import ( "log" "net/netip" "github.com/ti-mo/conntrack" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } f1 := conntrack.NewFlow( 6, 0, netip.MustParseAddr("1.2.3.4"), netip.MustParseAddr("5.6.7.8"), 1234, 80, 120, 0x00ff, // Set a connection mark ) f2 := conntrack.NewFlow( 17, 0, netip.MustParseAddr("2a00:1450:400e:804::200e"), netip.MustParseAddr("2a00:1450:400e:804::200f"), 1234, 80, 120, 0xff00, // Set a connection mark ) _ = c.Create(f1) _ = c.Create(f2) // Flush only the second flow matching the filter's mark/mask. err = c.FlushFilter(conntrack.Filter{Mark: 0xff00, Mask: 0xff00}) if err != nil { log.Fatal(err) } // Getting f1 succeeds. _, err = c.Get(f1) if err != nil { log.Fatal(err) } // Getting f2 will fail, since it was flushed. _, err = c.Get(f2) if err != nil { log.Println("Flow f2 missing, as expected", err) } }
Output:
Example (Listen) ¶
package main import ( "fmt" "log" "github.com/mdlayher/netlink" "github.com/ti-mo/conntrack" "github.com/ti-mo/netfilter" ) func main() { // Open a Conntrack connection. c, err := conntrack.Dial(nil) if err != nil { log.Fatal(err) } // Make a buffered channel to receive event updates on. evCh := make(chan conntrack.Event, 1024) // Listen for all Conntrack and Conntrack-Expect events with 4 decoder goroutines. // All errors caught in the decoders are passed on channel errCh. errCh, err := c.Listen(evCh, 4, append(netfilter.GroupsCT, netfilter.GroupsCTExp...)) if err != nil { log.Fatal(err) } // Listen to Conntrack events from all network namespaces on the system. err = c.SetOption(netlink.ListenAllNSID, true) if err != nil { log.Fatal(err) } // Start a goroutine to print all incoming messages on the event channel. go func() { for { fmt.Println(<-evCh) } }() // Stop the program as soon as an error is caught in a decoder goroutine. log.Print(<-errCh) }
Output:
func Dial ¶
Dial opens a new Netfilter Netlink connection and returns it wrapped in a Conn structure that implements the Conntrack API.
func (*Conn) Close ¶
Close closes a Conn.
If any workers were started using Conn.Listen, blocks until all have terminated.
func (*Conn) CreateExpect ¶
CreateExpect creates a new Conntrack Expect entry. Warning: Experimental, haven't got this to create an Expect correctly. Best-effort implementation based on kernel source.
func (*Conn) Delete ¶
Delete removes a Conntrack entry given a Flow. Flows are looked up in the conntrack table based on the original and reply tuple. When the Flow's ID field is filled, it must match the ID on the connection returned from the tuple lookup, or the delete will fail.
func (*Conn) Dump ¶
func (c *Conn) Dump(opts *DumpOptions) ([]Flow, error)
Dump gets all Conntrack connections from the kernel in the form of a list of Flow objects.
func (*Conn) DumpExpect ¶
DumpExpect gets all expected Conntrack expectations from the kernel in the form of a list of Expect objects.
func (*Conn) DumpFilter ¶
func (c *Conn) DumpFilter(f Filter, opts *DumpOptions) ([]Flow, error)
DumpFilter gets all Conntrack connections from the kernel in the form of a list of Flow objects, but only returns Flows matching the connmark specified in the Filter parameter.
func (*Conn) FlushFilter ¶
FlushFilter deletes all entries from the Conntrack table matching a given Filter. Both IPv4 and IPv6 entries are considered for deletion.
func (*Conn) Get ¶
Get queries the conntrack table for a connection matching some attributes of a given Flow. The following attributes are considered in the query: TupleOrig or TupleReply, in that order, and Zone. One of TupleOrig or TupleReply is required for a successful query.
func (*Conn) Listen ¶
func (c *Conn) Listen(evChan chan<- Event, numWorkers uint8, groups []netfilter.NetlinkGroup) (chan error, error)
Listen joins the Netfilter connection to a multicast group and starts a given amount of Flow decoders from the Conn to the Flow channel. Returns an error channel the workers will return any errors on. Any error during Flow decoding is fatal and will halt the worker it occurs on. When numWorkers amount of errors have been received on the error channel, no more events will be produced on evChan.
The Conn will be marked as having listeners active, which will prevent Listen from being called again. For listening on other groups, open another socket.
evChan consumers need to be able to keep up with the Event producers. When the channel is full, messages will pile up in the Netlink socket's buffer, putting the socket at risk of being closed by the kernel when it eventually fills up.
Closing the Conn makes all workers terminate silently.
func (*Conn) SetOption ¶
func (c *Conn) SetOption(option netlink.ConnOption, enable bool) error
SetOption enables or disables a netlink socket option for the Conn.
func (*Conn) SetReadBuffer ¶
SetReadBuffer sets the size of the operating system's receive buffer associated with the Conn.
The default read buffer size of a socket is configured with `sysctl net.core.rmem_default`. The maximum buffer size that can be set without elevated privileges is `sysctl net.core.rmem_max`.
func (*Conn) SetWriteBuffer ¶
SetWriteBuffer sets the size of the operating system's transmit buffer associated with the Conn.
The default write buffer size of a socket is configured with `sysctl net.core.wmem_default`. The maximum buffer size that can be set without elevated privileges is `sysctl net.core.wmem_max`.
func (*Conn) Stats ¶
Stats returns a list of Stats structures, one per CPU present in the machine. Each Stats structure contains performance counters of all Conntrack actions performed on that specific CPU.
func (*Conn) StatsExpect ¶
func (c *Conn) StatsExpect() ([]StatsExpect, error)
StatsExpect returns a list of StatsExpect structures, one per CPU present in the machine. Each StatsExpect structure indicates how many Expect entries were initialized, created or deleted on each CPU.
func (*Conn) StatsGlobal ¶
func (c *Conn) StatsGlobal() (StatsGlobal, error)
StatsGlobal queries Conntrack for an internal global counter that describes the total amount of Flow entries currently in the Conntrack table. Only the main Conntrack table has this fast query available. To get the amount of Expect entries, execute DumpExpect() and count the amount of entries returned.
Starting from kernels 4.18 and higher, MaxEntries is returned, describing the maximum size of the Conntrack table.
func (*Conn) Update ¶
Update updates a Conntrack entry. Only the following attributes are considered when sending a Flow update: Helper, Timeout, Status, ProtoInfo, Mark, SeqAdj (orig/reply), SynProxy, Labels. All other attributes are immutable past the point of creation. See the ctnetlink_change_conntrack() kernel function for exact behaviour.
type Counter ¶
type Counter struct { // true means it's a reply counter, // false is the original direction Direction bool Packets uint64 Bytes uint64 }
A Counter holds a pair of counters that represent packets and bytes sent over a Conntrack connection. Direction is true when it's a reply counter. This attribute cannot be changed on a connection and thus cannot be marshaled.
type DumpOptions ¶ added in v0.4.1
type DumpOptions struct { // ZeroCounters resets all flows' counters to zero after the dump operation. ZeroCounters bool }
DumpOptions is passed as an option to `Dump`-related methods to modify their behaviour.
type Expect ¶
type Expect struct {
ID, Timeout uint32
TupleMaster, Tuple, Mask Tuple
Zone uint16
HelpName, Function string
Flags, Class uint32
NAT ExpectNAT
}
Expect represents an 'expected' connection, created by Conntrack/IPTables helpers. Active connections created by helpers are shown by the conntrack tooling as 'RELATED'.
type Filter ¶
type Filter struct {
Mark, Mask uint32
}
Filter is a structure used in dump operations to filter the response based on a given connmark and mask. The mask is applied to the Mark field of all flows in the conntrack table, the result is compared to the filter's Mark. Each flow that matches will be returned by the kernel.
type Flow ¶
type Flow struct { ID uint32 Timeout uint32 Timestamp Timestamp Status Status ProtoInfo ProtoInfo Helper Helper Zone uint16 CountersOrig, CountersReply Counter SecurityContext Security TupleOrig, TupleReply, TupleMaster Tuple SeqAdjOrig, SeqAdjReply SequenceAdjust Labels, LabelsMask []byte Mark, Use uint32 SynProxy SynProxy }
Flow represents a snapshot of a Conntrack connection.
func NewFlow ¶
func NewFlow(proto uint8, status StatusFlag, srcAddr, destAddr netip.Addr, srcPort, destPort uint16, timeout, mark uint32) Flow
NewFlow returns a new Flow object with the minimum necessary attributes to create a Conntrack entry. Writes values into the Status, Timeout, TupleOrig and TupleReply fields of the Flow.
proto is the layer 4 protocol number of the connection. status is a StatusFlag value, or an ORed combination thereof. srcAddr and dstAddr are the source and destination addresses. srcPort and dstPort are the source and destination ports. timeout is the non-zero time-to-live of a connection in seconds.
type ProtoInfo ¶
type ProtoInfo struct { TCP *ProtoInfoTCP DCCP *ProtoInfoDCCP SCTP *ProtoInfoSCTP }
The ProtoInfo structure holds a pointer to one of ProtoInfoTCP, ProtoInfoDCCP or ProtoInfoSCTP.
type ProtoInfoDCCP ¶
ProtoInfoDCCP describes the state of a DCCP connection.
type ProtoInfoSCTP ¶
ProtoInfoSCTP describes the state of an SCTP connection.
type ProtoInfoTCP ¶
type ProtoInfoTCP struct { State uint8 OriginalWindowScale uint8 ReplyWindowScale uint8 OriginalFlags uint16 ReplyFlags uint16 }
A ProtoInfoTCP describes the state of a TCP session in both directions. It contains state, window scale and TCP flags.
type ProtoTuple ¶
type ProtoTuple struct { Protocol uint8 SourcePort uint16 DestinationPort uint16 ICMPv4 bool ICMPv6 bool ICMPID uint16 ICMPType uint8 ICMPCode uint8 }
A ProtoTuple encodes a protocol number, source port and destination port.
type Security ¶
type Security string
A Security structure holds the security info belonging to a connection. Kernel uses this to store and match SELinux context name. This attribute cannot be changed on a connection and thus cannot be marshaled.
type SequenceAdjust ¶
type SequenceAdjust struct { // true means it's a reply adjustment, // false is the original direction Direction bool Position uint32 OffsetBefore uint32 OffsetAfter uint32 }
SequenceAdjust represents a TCP sequence number adjustment event. Direction is true when it's a reply adjustment.
func (SequenceAdjust) String ¶
func (seq SequenceAdjust) String() string
type Stats ¶
type Stats struct { CPUID uint16 Found uint32 Invalid uint32 Ignore uint32 Insert uint32 InsertFailed uint32 Drop uint32 EarlyDrop uint32 Error uint32 SearchRestart uint32 }
Stats represents the Conntrack performance counters of a single CPU (core). It indicates which and how many Flow operations took place on each CPU.
type StatsExpect ¶
StatsExpect represents the Conntrack Expect performance counters of a single CPU (core). It indicates how many Expect entries were initialized, created or deleted on each CPU.
type StatsGlobal ¶
type StatsGlobal struct {
Entries, MaxEntries uint32
}
StatsGlobal represents global statistics about the conntrack subsystem.
type Status ¶
type Status struct {
Value StatusFlag
}
Status represents a snapshot of a conntrack connection's state.
func (Status) DstNATDone ¶
DstNATDone is set when destination NAT was applied onto the connection.
func (Status) Expected ¶
Expected indicates that this connection is an expected connection, created by Conntrack helpers based on the state of another, related connection.
func (Status) FixedTimeout ¶
FixedTimeout means the connection's timeout value cannot be changed.
func (Status) Helper ¶
Helper is set when a helper was explicitly attached using a Conntrack target.
func (Status) SrcNATDone ¶
SrcNATDone is set when source NAT was applied onto the connection.
type StatusFlag ¶
type StatusFlag uint32
StatusFlag describes a status bit in a Status structure.
const ( StatusExpected StatusFlag = 1 // IPS_EXPECTED StatusSeenReply StatusFlag = 1 << 1 // IPS_SEEN_REPLY StatusAssured StatusFlag = 1 << 2 // IPS_ASSURED StatusConfirmed StatusFlag = 1 << 3 // IPS_CONFIRMED StatusSrcNAT StatusFlag = 1 << 4 // IPS_SRC_NAT StatusDstNAT StatusFlag = 1 << 5 // IPS_DST_NAT StatusNATMask = StatusDstNAT | StatusSrcNAT // IPS_NAT_MASK StatusSeqAdjust StatusFlag = 1 << 6 // IPS_SEQ_ADJUST StatusSrcNATDone StatusFlag = 1 << 7 // IPS_SRC_NAT_DONE StatusDstNATDone StatusFlag = 1 << 8 // IPS_DST_NAT_DONE StatusNATDoneMask = StatusDstNATDone | StatusSrcNATDone // IPS_NAT_DONE_MASK StatusDying StatusFlag = 1 << 9 StatusFixedTimeout StatusFlag = 1 << 10 // IPS_FIXED_TIMEOUT StatusTemplate StatusFlag = 1 << 11 // IPS_TEMPLATE StatusUntracked StatusFlag = 1 << 12 // IPS_UNTRACKED StatusHelper StatusFlag = 1 << 13 // IPS_HELPER StatusOffload StatusFlag = 1 << 14 // IPS_OFFLOAD )
Conntrack connection's status flags, from enum ip_conntrack_status. uapi/linux/netfilter/nf_conntrack_common.h