iptables

package
v1.11.0-cni-plu...-ddfc3b1 Latest Latest
Warning

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

Go to latest
Published: Nov 20, 2024 License: Apache-2.0, Apache-2.0 Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MaxChainNameLength = 28
)

Variables

View Source
var (
	Err14LockTimeout = errors.New("Timed out waiting for iptables 1.4 lock")
	Err16LockTimeout = errors.New("Timed out waiting for iptables 1.6 lock")
)
View Source
var Wildcard string = "+"

Functions

func Actions

func Actions() generictables.ActionFactory

func CalculateRuleHashes

func CalculateRuleHashes(chainName string, rules []generictables.Rule, features *environment.Features) []string

func GrabIptablesLocks

func GrabIptablesLocks(lockFilePath, socketName string, timeout, probeInterval time.Duration) (io.Closer, error)

func Match

func PortRangesToMultiport

func PortRangesToMultiport(ports []*proto.PortRange) string

func PortsToMultiport

func PortsToMultiport(ports []uint16) string

Types

type AcceptAction

type AcceptAction struct {
	TypeAccept struct{}
}

func (AcceptAction) String

func (g AcceptAction) String() string

func (AcceptAction) ToFragment

func (g AcceptAction) ToFragment(features *environment.Features) string

type ClearMarkAction

type ClearMarkAction struct {
	Mark          uint32
	TypeClearMark struct{}
}

func (ClearMarkAction) String

func (c ClearMarkAction) String() string

func (ClearMarkAction) ToFragment

func (c ClearMarkAction) ToFragment(features *environment.Features) string

type DNATAction

type DNATAction struct {
	DestAddr string
	DestPort uint16
	TypeDNAT struct{}
}

func (DNATAction) String

func (g DNATAction) String() string

func (DNATAction) ToFragment

func (g DNATAction) ToFragment(features *environment.Features) string

type DropAction

type DropAction struct {
	TypeDrop struct{}
}

func (DropAction) String

func (g DropAction) String() string

func (DropAction) ToFragment

func (g DropAction) ToFragment(features *environment.Features) string

type GotoAction

type GotoAction struct {
	Target   string
	TypeGoto struct{}
}

func (GotoAction) ReferencedChain

func (g GotoAction) ReferencedChain() string

func (GotoAction) String

func (g GotoAction) String() string

func (GotoAction) ToFragment

func (g GotoAction) ToFragment(features *environment.Features) string

type IptablesRenderer

type IptablesRenderer interface {
	generictables.RuleHasher
	RenderAppend(rule *generictables.Rule, chainName, hash string, features *environment.Features) string
	RenderInsert(rule *generictables.Rule, chainName, hash string, features *environment.Features) string
	RenderInsertAtRuleNumber(rule *generictables.Rule, chainName string, ruleNum int, hash string, features *environment.Features) string
	RenderReplace(rule *generictables.Rule, chainName string, ruleNum int, hash string, features *environment.Features) string
}

func NewIptablesRenderer

func NewIptablesRenderer(hashCommentPrefix string) IptablesRenderer

type JumpAction

type JumpAction struct {
	Target   string
	TypeJump struct{}
}

func (JumpAction) ReferencedChain

func (g JumpAction) ReferencedChain() string

func (JumpAction) String

func (g JumpAction) String() string

func (JumpAction) ToFragment

func (g JumpAction) ToFragment(features *environment.Features) string

type Locker

type Locker struct {
	Lock16 io.Closer
	Lock14 io.Closer
}

func (*Locker) Close

func (l *Locker) Close() error

type LogAction

type LogAction struct {
	Prefix  string
	TypeLog struct{}
}

func (LogAction) String

func (g LogAction) String() string

func (LogAction) ToFragment

func (g LogAction) ToFragment(features *environment.Features) string

type MasqAction

type MasqAction struct {
	ToPorts  string
	TypeMasq struct{}
}

func (MasqAction) String

func (g MasqAction) String() string

func (MasqAction) ToFragment

func (g MasqAction) ToFragment(features *environment.Features) string

type NoTrackAction

type NoTrackAction struct {
	TypeNoTrack struct{}
}

func (NoTrackAction) String

func (g NoTrackAction) String() string

func (NoTrackAction) ToFragment

func (g NoTrackAction) ToFragment(features *environment.Features) string

type Referrer

type Referrer interface {
	ReferencedChain() string
}

type RejectAction

type RejectAction struct {
	TypeReject struct{}
	With       generictables.RejectWith
}

func (RejectAction) String

func (g RejectAction) String() string

func (RejectAction) ToFragment

func (g RejectAction) ToFragment(features *environment.Features) string

type RestoreConnMarkAction

type RestoreConnMarkAction struct {
	RestoreMask  uint32
	TypeConnMark struct{}
}

func (RestoreConnMarkAction) String

func (c RestoreConnMarkAction) String() string

func (RestoreConnMarkAction) ToFragment

func (c RestoreConnMarkAction) ToFragment(features *environment.Features) string

type RestoreInputBuilder

type RestoreInputBuilder struct {
	NumLinesWritten counter
	// contains filtered or unexported fields
}

RestoreInputBuilder builds a byte slice for use as input to iptables-restore.

Operations must be done inside a per-table transaction.

Example:

buf.Reset() // Reset the buffer, if needed.
buf.StartTransaction("filter")
buf.WriteForwardReference("cali-chain-name")
buf.WriteLine("-A cali-chain-name ...")
buf.EndTransaction()
bytes = buf.GetBytesAndReset()
<write bytes to iptables-restore stdin>

Transactions are ignored completely if there are no writes between the StartTransaction() and EndTransaction() calls.

func (*RestoreInputBuilder) Empty

func (b *RestoreInputBuilder) Empty() bool

Empty returns true if there is nothing in the buffer (i.e. all the transactions stored in the buffer were no-ops).

func (*RestoreInputBuilder) EndTransaction

func (b *RestoreInputBuilder) EndTransaction()

EndTransaction ends the open transaction, if the transaction was non-empty, writes a COMMIT. Resets the transaction tracking state. Panics if there was no open transaction.

func (*RestoreInputBuilder) GetBytesAndReset

func (b *RestoreInputBuilder) GetBytesAndReset() []byte

GetBytesAndReset returns the contents of the buffer and, as a side effect, resets the buffer. For performance, this is a direct reference to the data rather than a copy. The returned slice is only valid until the next write operation on the builder. Should be called after EndTransaction; panics if there is a still-open transaction.

func (*RestoreInputBuilder) Reset

func (b *RestoreInputBuilder) Reset()

Reset the builder completely, any pending transaction is discarded.

func (*RestoreInputBuilder) StartTransaction

func (b *RestoreInputBuilder) StartTransaction(tableName string)

StartTransaction opens a new transaction context for the named table. Panics if there is already a transaction in progress.

func (*RestoreInputBuilder) WriteForwardReference

func (b *RestoreInputBuilder) WriteForwardReference(chainName string)

WriteForwardReference writes a "forward reference" for the given chain name. A forward reference is an instruction that tells iptables to ensure that the given chain exists and that it is empty. Panics if there is no open transaction.

func (*RestoreInputBuilder) WriteLine

func (b *RestoreInputBuilder) WriteLine(line string)

WriteLine writes a line of iptables instructions to the buffer. Intended for writing the actual rules. Panics if there is no open transaction.

type ReturnAction

type ReturnAction struct {
	TypeReturn struct{}
}

func (ReturnAction) IsReturnAction

func (r ReturnAction) IsReturnAction()

func (ReturnAction) String

func (r ReturnAction) String() string

func (ReturnAction) ToFragment

func (r ReturnAction) ToFragment(features *environment.Features) string

type SNATAction

type SNATAction struct {
	ToAddr   string
	TypeSNAT struct{}
}

func (SNATAction) String

func (g SNATAction) String() string

func (SNATAction) ToFragment

func (g SNATAction) ToFragment(features *environment.Features) string

type SaveConnMarkAction

type SaveConnMarkAction struct {
	SaveMask     uint32
	TypeConnMark struct{}
}

func (SaveConnMarkAction) String

func (c SaveConnMarkAction) String() string

func (SaveConnMarkAction) ToFragment

func (c SaveConnMarkAction) ToFragment(features *environment.Features) string

type SetConnMarkAction

type SetConnMarkAction struct {
	Mark         uint32
	Mask         uint32
	TypeConnMark struct{}
}

func (SetConnMarkAction) String

func (c SetConnMarkAction) String() string

func (SetConnMarkAction) ToFragment

func (c SetConnMarkAction) ToFragment(features *environment.Features) string

type SetMarkAction

type SetMarkAction struct {
	Mark        uint32
	TypeSetMark struct{}
}

func (SetMarkAction) String

func (c SetMarkAction) String() string

func (SetMarkAction) ToFragment

func (c SetMarkAction) ToFragment(features *environment.Features) string

type SetMaskedMarkAction

type SetMaskedMarkAction struct {
	Mark              uint32
	Mask              uint32
	TypeSetMaskedMark struct{}
}

func (SetMaskedMarkAction) String

func (c SetMaskedMarkAction) String() string

func (SetMaskedMarkAction) ToFragment

func (c SetMaskedMarkAction) ToFragment(features *environment.Features) string

type SharedLock

type SharedLock struct {
	GrabIptablesLocks func(lockFilePath, socketName string, timeout, probeInterval time.Duration) (io.Closer, error)
	// contains filtered or unexported fields
}

SharedLock allows for multiple goroutines to share the iptables lock without blocking on each other. That is safe because each of our goroutines is accessing a different iptables table, so they do not conflict.

func NewSharedLock

func NewSharedLock(lockFilePath string, lockTimeout, lockProbeInterval time.Duration) *SharedLock

func (*SharedLock) Lock

func (l *SharedLock) Lock()

func (*SharedLock) Unlock

func (l *SharedLock) Unlock()

type Table

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

Table represents a single one of the iptables tables i.e. "raw", "nat", "filter", etc. It caches the desired state of that table, then attempts to bring it into sync when Apply() is called.

API Model

Table supports two classes of operation: "rule insertions" and "full chain updates".

As the name suggests, rule insertions allow for inserting one or more rules into a preexisting chain. Rule insertions are intended to be used to hook kernel chains (such as "FORWARD") in order to direct them to a Felix-owned chain. It is important to minimise the use of rule insertions because the top-level chains are shared resources, which can be modified by other applications. In addition, rule insertions are harder to clean up after an upgrade to a new version of Felix (because we need a way to recognise our rules in a crowded chain).

Full chain updates replace the entire contents of a Felix-owned chain with a new set of rules. Limiting the operation to "replace whole chain" in this way significantly simplifies the API. Although the API operates on full chains, the dataplane write logic tries to avoid rewriting a whole chain if only part of it has changed (this was not the case in Felix 1.4). This prevents iptables counters from being reset unnecessarily.

In either case, the actual dataplane updates are deferred until the next call to Apply() so chain updates and insertions may occur in any order as long as they are consistent (i.e. there are no references to nonexistent chains) by the time Apply() is called.

Design

We had several goals in designing the iptables machinery in 2.0.0:

(1) High performance. Felix needs to handle high churn of endpoints and rules.

(2) Ability to restore rules, even if other applications accidentally break them: we found that other applications sometimes misuse iptables-save and iptables-restore to do a read, modify, write cycle. That behaviour is not safe under concurrent modification.

(3) Avoid rewriting rules that haven't changed so that we don't reset iptables counters.

(4) Avoid parsing iptables commands (for example, the output from iptables/iptables-save). This is very hard to do robustly because iptables rules do not necessarily round-trip through the kernel in the same form. In addition, the format could easily change due to changes or fixes in the iptables/iptables-save command.

(5) Support for graceful restart. I.e. deferring potentially incorrect updates until we're in-sync with the datastore. For example, if we have 100 endpoints on a host, after a restart we don't want to write a "dispatch" chain when we learn about the first endpoint (possibly replacing an existing one that had all 100 endpoints in place and causing traffic to glitch); instead, we want to defer until we've seen all 100 and then do the write.

(6) Improved handling of rule inserts vs Felix 1.4.x. Previous versions of Felix sometimes inserted special-case rules that were not marked as Calico rules in any sensible way making cleanup of those rules after an upgrade difficult.

Implementation

For high performance (goal 1), we use iptables-restore to do bulk updates to iptables. This is much faster than individual iptables calls.

To allow us to restore rules after they are clobbered by another process (goal 2), we cache them at this layer. This means that we don't need a mechanism to ask the other layers of Felix to do a resync. Note: Table doesn't start a thread of its own so it relies on the main event loop to trigger any dataplane resync polls.

There is tension between goals 3 and 4. In order to avoid full rewrites (goal 3), we need to know what rules are in place, but we also don't want to parse them to find out (goal 4)! As a compromise, we deterministically calculate an ID for each rule and store it in an iptables comment. Then, when we want to know what rules are in place, we _do_ parse the output from iptables-save, but only to read back the rule IDs. That limits the amount of parsing we need to do and keeps it manageable/robust.

To support graceful restart (goal 5), we defer updates to the dataplane until Apply() is called, then we do an atomic update using iptables-restore. As long as the first Apply() call is after we're in sync, the dataplane won't be touched until the right time. Felix 1.4.x had a more complex mechanism to support partial updates during the graceful restart period but Felix 2.0.0 resyncs so quickly that the added complexity is not justified.

To make it easier to manage rule insertions (goal 6), we add rule IDs to those too. With rule IDs in place, we can easily distinguish Calico rules from non-Calico rules without needing to know exactly which rules to expect. To deal with cleanup after upgrade from older versions that did not write rule IDs, we support special-case regexes to detect our old rules.

Thread safety

Table doesn't do any internal synchronization, its methods should only be called from one thread. To avoid conflicts in the dataplane itself, there should only be one instance of Table for each iptable table in an application.

func NewTable

func NewTable(
	name string,
	ipVersion uint8,
	hashPrefix string,
	iptablesWriteLock sync.Locker,
	featureDetector environment.FeatureDetectorIface,
	options TableOptions,
) *Table

func (*Table) AppendRules

func (t *Table) AppendRules(chainName string, rules []generictables.Rule)

AppendRules sets the rules to be appended to a given non-Calico chain. These rules are always appended, even if chain insert mode is "insert". If chain insert mode is "append", these rules are appended after any rules added with InsertOrAppendRules.

func (*Table) Apply

func (t *Table) Apply() (rescheduleAfter time.Duration)

func (*Table) CheckRulesPresent

func (t *Table) CheckRulesPresent(chain string, rules []generictables.Rule) []generictables.Rule

CheckRulesPresent returns list of rules with the hashes that are already programmed. Return value of nil means that none of the rules are present.

func (*Table) IPVersion

func (t *Table) IPVersion() uint8

func (*Table) InsertOrAppendRules

func (t *Table) InsertOrAppendRules(chainName string, rules []generictables.Rule)

InsertOrAppendRules sets the rules that should be inserted into or appended to the given non-Calico chain (depending on the chain insert mode). See also AppendRules, which can be used to record additional rules that are always appended.

func (*Table) InsertRulesNow

func (t *Table) InsertRulesNow(chain string, rules []generictables.Rule) error

InsertRulesNow insets the given rules immediately without removing or syncing other rules. This is primarily useful when bootstrapping and we cannot wait until we have the full state.

func (*Table) InvalidateDataplaneCache

func (t *Table) InvalidateDataplaneCache(reason string)

func (*Table) Name

func (t *Table) Name() string

func (*Table) RemoveChainByName

func (t *Table) RemoveChainByName(name string)

func (*Table) RemoveChains

func (t *Table) RemoveChains(chains []*generictables.Chain)

func (*Table) UnexpectedInsertsSeen

func (t *Table) UnexpectedInsertsSeen() int

func (*Table) UpdateChain

func (t *Table) UpdateChain(chain *generictables.Chain)

func (*Table) UpdateChains

func (t *Table) UpdateChains(chains []*generictables.Chain)

type TableOptions

type TableOptions struct {
	HistoricChainPrefixes    []string
	ExtraCleanupRegexPattern string
	BackendMode              string
	InsertMode               string
	RefreshInterval          time.Duration
	PostWriteInterval        time.Duration

	// LockTimeout is the timeout to use for iptables-restore's native xtables lock.
	LockTimeout time.Duration
	// LockProbeInterval is the probe interval to use for iptables-restore's native xtables lock.
	LockProbeInterval time.Duration

	// NewCmdOverride for tests, if non-nil, factory to use instead of the real exec.Command()
	NewCmdOverride cmdshim.CmdFactory
	// SleepOverride for tests, if non-nil, replacement for time.Sleep()
	SleepOverride func(d time.Duration)
	// NowOverride for tests, if non-nil, replacement for time.Now()
	NowOverride func() time.Time
	// LookPathOverride for tests, if non-nil, replacement for exec.LookPath()
	LookPathOverride func(file string) (string, error)
	// Thunk to call periodically when doing a long-running operation.
	OnStillAlive func()
	// OpRecorder to tell when we do resyncs etc.
	OpRecorder logutils.OpRecorder
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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