feat: improve nftables backend

Many changes to the nftables backend which will be used in the follow-up
PR with #4421.

1. Add support for chain policy: drop/accept.
2. Properly handle match on all IPs in the set (`0.0.0.0/0` like).
3. Implement conntrack state matching.
4. Implement multiple ifname matching in a single rule.
5. Implement anonymous counters.

Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
Andrey Smirnov 2023-11-29 21:07:56 +04:00
parent db4e2539d4
commit 9a85217412
No known key found for this signature in database
GPG Key ID: FE042E3D4085A811
21 changed files with 2719 additions and 1178 deletions

Binary file not shown.

View File

@ -77,6 +77,15 @@ enum NethelpersBondXmitHashPolicy {
BOND_XMIT_POLICY_ENCAP34 = 4;
}
// NethelpersConntrackState is a conntrack state.
enum NethelpersConntrackState {
NETHELPERS_CONNTRACKSTATE_UNSPECIFIED = 0;
CONNTRACK_STATE_NEW = 8;
CONNTRACK_STATE_RELATED = 4;
CONNTRACK_STATE_ESTABLISHED = 2;
CONNTRACK_STATE_INVALID = 1;
}
// NethelpersDuplex wraps ethtool.Duplex for YAML marshaling.
enum NethelpersDuplex {
HALF = 0;
@ -259,8 +268,10 @@ enum NethelpersPrimaryReselect {
// NethelpersProtocol is a inet protocol.
enum NethelpersProtocol {
NETHELPERS_PROTOCOL_UNSPECIFIED = 0;
PROTOCOL_ICMP = 1;
PROTOCOL_TCP = 6;
PROTOCOL_UDP = 17;
PROTOCOL_ICM_PV6 = 58;
}
// NethelpersRouteFlag wraps RTM_F_* constants.

View File

@ -179,6 +179,7 @@ message NfTablesChainSpec {
talos.resource.definitions.enums.NethelpersNfTablesChainHook hook = 2;
talos.resource.definitions.enums.NethelpersNfTablesChainPriority priority = 3;
repeated NfTablesRule rules = 4;
talos.resource.definitions.enums.NethelpersNfTablesVerdict policy = 5;
}
// NfTablesClampMSS describes the TCP MSS clamping operation.
@ -190,10 +191,15 @@ message NfTablesClampMSS {
fixed32 mtu = 1;
}
// NfTablesConntrackStateMatch describes the match on the connection tracking state.
message NfTablesConntrackStateMatch {
repeated uint32 states = 1;
}
// NfTablesIfNameMatch describes the match on the interface name.
message NfTablesIfNameMatch {
string interface_name = 1;
talos.resource.definitions.enums.NethelpersMatchOperator operator = 2;
repeated string interface_names = 3;
}
// NfTablesLayer4Match describes the match on the transport layer protocol.
@ -203,6 +209,11 @@ message NfTablesLayer4Match {
NfTablesPortMatch match_destination_port = 3;
}
// NfTablesLimitMatch describes the match on the packet rate.
message NfTablesLimitMatch {
uint64 packet_rate_per_second = 1;
}
// NfTablesMark encodes packet mark match/update operation.
//
// When used as a match computes the following condition:
@ -232,6 +243,9 @@ message NfTablesRule {
NfTablesLayer4Match match_layer4 = 7;
NfTablesIfNameMatch match_i_if_name = 8;
NfTablesClampMSS clamp_mss = 9;
NfTablesLimitMatch match_limit = 10;
NfTablesConntrackStateMatch match_conntrack_state = 11;
bool anon_counter = 12;
}
// NodeAddressFilterSpec describes a filter for NodeAddresses.

View File

@ -6,6 +6,7 @@ package network
import (
"fmt"
"net/netip"
"os"
"slices"
@ -16,6 +17,7 @@ import (
"go4.org/netipx"
"golang.org/x/sys/unix"
"github.com/siderolabs/talos/pkg/machinery/nethelpers"
"github.com/siderolabs/talos/pkg/machinery/resources/network"
)
@ -40,13 +42,29 @@ const (
SetKindIPv4 SetKind = iota
SetKindIPv6
SetKindPort
SetKindIfName
SetKindConntrackState
)
// NfTablesSet is a compiled representation of the set.
type NfTablesSet struct {
Kind SetKind
Addresses []netipx.IPRange
Ports [][2]uint16
Kind SetKind
Addresses []netipx.IPRange
Ports [][2]uint16
Strings [][]byte
ConntrackStates []nethelpers.ConntrackState
}
// IsInterval returns true if the set is an interval set.
func (set NfTablesSet) IsInterval() bool {
switch set.Kind {
case SetKindIPv4, SetKindIPv6, SetKindPort:
return true
case SetKindIfName, SetKindConntrackState:
return false
default:
panic(fmt.Sprintf("unknown set kind: %d", set.Kind))
}
}
// KeyType returns the type of the set.
@ -58,6 +76,10 @@ func (set NfTablesSet) KeyType() nftables.SetDatatype {
return nftables.TypeIP6Addr
case SetKindPort:
return nftables.TypeInetService
case SetKindIfName:
return nftables.TypeIFName
case SetKindConntrackState:
return nftables.TypeCTState
default:
panic(fmt.Sprintf("unknown set kind: %d", set.Kind))
}
@ -91,7 +113,7 @@ func (set NfTablesSet) SetElements() []nftables.SetElement {
for _, p := range set.Ports {
from := binaryutil.BigEndian.PutUint16(p[0])
to := binaryutil.BigEndian.PutUint16(p[1])
to := binaryutil.BigEndian.PutUint16(p[1] + 1)
elements = append(elements,
nftables.SetElement{
@ -105,6 +127,30 @@ func (set NfTablesSet) SetElements() []nftables.SetElement {
)
}
return elements
case SetKindIfName:
elements := make([]nftables.SetElement, 0, len(set.Strings))
for _, s := range set.Strings {
elements = append(elements,
nftables.SetElement{
Key: s,
},
)
}
return elements
case SetKindConntrackState:
elements := make([]nftables.SetElement, 0, len(set.ConntrackStates))
for _, s := range set.ConntrackStates {
elements = append(elements,
nftables.SetElement{
Key: binaryutil.NativeEndian.PutUint32(uint32(s)),
},
)
}
return elements
default:
panic(fmt.Sprintf("unknown set kind: %d", set.Kind))
@ -145,6 +191,12 @@ var (
Data: []byte{byte(nftables.TableFamilyIPv6)},
},
}
firstIPv4 = netip.MustParseAddr("0.0.0.0")
lastIPv4 = netip.MustParseAddr("255.255.255.255")
firstIPv6 = netip.MustParseAddr("::")
lastIPv6 = netip.MustParseAddr("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")
)
// Compile translates the rule into the set of nftables instructions.
@ -161,6 +213,34 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
result NfTablesCompiled
)
matchIfNames := func(operator nethelpers.MatchOperator, ifnames []string) {
if len(ifnames) == 1 {
rulePre = append(rulePre,
// [ cmp eq/neq reg 1 <ifname> ]
&expr.Cmp{
Op: expr.CmpOp(operator),
Register: 1,
Data: ifname(ifnames[0]),
},
)
} else {
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindIfName,
Strings: xslices.Map(ifnames, ifname),
})
rulePre = append(rulePre,
// Match from target set
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
Invert: operator == nethelpers.OperatorNotEqual,
},
)
}
}
if a.NfTablesRule.MatchIIfName != nil {
match := a.NfTablesRule.MatchIIfName
@ -170,13 +250,9 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
Key: expr.MetaKeyIIFNAME,
Register: 1,
},
// [ cmp eq/neq reg 1 <ifname> ]
&expr.Cmp{
Op: expr.CmpOp(match.Operator),
Register: 1,
Data: ifname(match.InterfaceName),
},
)
matchIfNames(match.Operator, match.InterfaceNames)
}
if a.NfTablesRule.MatchOIfName != nil {
@ -188,13 +264,9 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
Key: expr.MetaKeyOIFNAME,
Register: 1,
},
// [ cmp eq/neq reg 1 <ifname> ]
&expr.Cmp{
Op: expr.CmpOp(match.Operator),
Register: 1,
Data: ifname(match.InterfaceName),
},
)
matchIfNames(match.Operator, match.InterfaceNames)
}
if a.NfTablesRule.MatchMark != nil {
@ -224,6 +296,53 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
)
}
if a.NfTablesRule.MatchConntrackState != nil {
match := a.NfTablesRule.MatchConntrackState
if len(match.States) == 1 {
rulePre = append(rulePre,
// [ ct load state => reg 1 ]
&expr.Ct{
Key: expr.CtKeySTATE,
Register: 1,
},
// [ bitwise reg 1 = ( reg 1 & state ) ^ 0x00000000 ]
&expr.Bitwise{
SourceRegister: 1,
DestRegister: 1,
Len: 4,
Mask: binaryutil.NativeEndian.PutUint32(match.States[0]),
Xor: []byte{0x0, 0x0, 0x0, 0x0},
},
// [ cmp neq reg 1 0x00000000 ]
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: []byte{0x0, 0x0, 0x0, 0x0},
},
)
} else {
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindConntrackState,
ConntrackStates: xslices.Map(match.States, func(s uint32) nethelpers.ConntrackState { return nethelpers.ConntrackState(s) }),
})
rulePre = append(rulePre,
// [ ct load state => reg 1 ]
&expr.Ct{
Key: expr.CtKeySTATE,
Register: 1,
},
// [ lookup reg 1 set <set> ]
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
},
)
}
}
addressMatchExpression := func(match *network.NfTablesAddressMatch, label string, offV4, offV6 uint32) error {
ipSet, err := BuildIPSet(match.IncludeSubnets, match.ExcludeSubnets)
if err != nil {
@ -237,71 +356,77 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
return os.ErrNotExist
}
// skip v4 rule if there are not IPs to match for and not inverted
if v4Set != nil || match.Invert {
if v4Set == nil && match.Invert {
// match any v4 IP
if rule4 == nil {
rule4 = []expr.Any{}
}
} else {
// match specific v4 IPs
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindIPv4,
Addresses: v4Set,
},
)
v4SetCoversAll := len(v4Set) == 1 && v4Set[0].From() == firstIPv4 && v4Set[0].To() == lastIPv4
v6SetCoversAll := len(v6Set) == 1 && v6Set[0].From() == firstIPv6 && v6Set[0].To() == lastIPv6
rule4 = append(rule4,
// Store the destination IP address to register 1
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseNetworkHeader,
Offset: offV4,
Len: 4,
},
// Match from target set
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
Invert: match.Invert,
},
)
}
if v4SetCoversAll && v6SetCoversAll && match.Invert {
// this rule doesn't match anything
return os.ErrNotExist
}
// skip v6 rule if there are not IPs to match for and not inverted
if v6Set != nil || match.Invert {
if v6Set == nil && match.Invert {
// match any v6 IP
if rule6 == nil {
rule6 = []expr.Any{}
}
} else {
// match specific v6 IPs
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindIPv6,
Addresses: v6Set,
})
rule6 = append(rule6,
// Store the destination IP address to register 1
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseNetworkHeader,
Offset: offV6,
Len: 16,
},
// Match from target set
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
Invert: match.Invert,
},
)
switch { //nolint:dupl
case v4SetCoversAll && !match.Invert, match.Invert && v4Set == nil:
// match any v4 IP
if rule4 == nil {
rule4 = []expr.Any{}
}
case !v4SetCoversAll && match.Invert, !match.Invert && v4Set != nil:
// match specific v4 IPs
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindIPv4,
Addresses: v4Set,
},
)
rule4 = append(rule4,
// Store the destination IP address to register 1
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseNetworkHeader,
Offset: offV4,
Len: 4,
},
// Match from target set
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
Invert: match.Invert,
},
)
default: // otherwise skip generating v4 rule, as it doesn't match anything
}
switch { //nolint:dupl
case v6SetCoversAll && !match.Invert, match.Invert && v6Set == nil:
// match any v6 IP
if rule6 == nil {
rule6 = []expr.Any{}
}
case !v6SetCoversAll && match.Invert, !match.Invert && v6Set != nil:
// match specific v6 IPs
result.Sets = append(result.Sets,
NfTablesSet{
Kind: SetKindIPv6,
Addresses: v6Set,
})
rule6 = append(rule6,
// Store the destination IP address to register 1
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseNetworkHeader,
Offset: offV6,
Len: 16,
},
// Match from target set
&expr.Lookup{
SourceRegister: 1,
SetID: uint32(len(result.Sets) - 1), // reference will be fixed up by the controller
Invert: match.Invert,
},
)
default: // otherwise skip generating v6 rule, as it doesn't match anything
}
return nil
@ -381,6 +506,20 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
}
}
if a.NfTablesRule.MatchLimit != nil {
match := a.NfTablesRule.MatchLimit
rulePost = append(rulePost,
// [ limit rate <rate> ]
&expr.Limit{
Type: expr.LimitTypePkts,
Rate: match.PacketRatePerSecond,
Burst: uint32(match.PacketRatePerSecond),
Unit: expr.LimitTimeSecond,
},
)
}
clampMSS := func(family nftables.TableFamily, mtu uint16) []expr.Any {
var mss uint16
@ -487,6 +626,13 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
)
}
if a.NfTablesRule.AnonCounter {
rulePost = append(rulePost,
// [ counter ]
&expr.Counter{},
)
}
if a.NfTablesRule.Verdict != nil {
rulePost = append(rulePost,
// [ verdict accept|drop ]

View File

@ -38,8 +38,8 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
name: "match oifname",
spec: networkres.NfTablesRule{
MatchOIfName: &networkres.NfTablesIfNameMatch{
InterfaceName: "eth0",
Operator: nethelpers.OperatorEqual,
InterfaceNames: []string{"eth0"},
Operator: nethelpers.OperatorEqual,
},
},
expectedRules: [][]expr.Any{
@ -57,8 +57,8 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
name: "match iifname",
spec: networkres.NfTablesRule{
MatchIIfName: &networkres.NfTablesIfNameMatch{
InterfaceName: "lo",
Operator: nethelpers.OperatorNotEqual,
InterfaceNames: []string{"lo"},
Operator: nethelpers.OperatorNotEqual,
},
},
expectedRules: [][]expr.Any{
@ -72,12 +72,39 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
},
},
},
{
name: "match multiple iifname",
spec: networkres.NfTablesRule{
MatchIIfName: &networkres.NfTablesIfNameMatch{
InterfaceNames: []string{"siderolink", "kubespan"},
Operator: nethelpers.OperatorEqual,
},
},
expectedRules: [][]expr.Any{
{
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
&expr.Lookup{
SourceRegister: 1,
SetID: 0,
},
},
},
expectedSets: []network.NfTablesSet{
{
Kind: network.SetKindIfName,
Strings: [][]byte{
[]byte("siderolink\000\000\000\000\000\000"),
[]byte("kubespan\000\000\000\000\000\000\000\000"),
},
},
},
},
{
name: "verdict accept",
spec: networkres.NfTablesRule{
MatchOIfName: &networkres.NfTablesIfNameMatch{
InterfaceName: "eth0",
Operator: nethelpers.OperatorNotEqual,
InterfaceNames: []string{"eth0"},
Operator: nethelpers.OperatorNotEqual,
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
@ -585,6 +612,97 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
},
},
},
{
name: "limit",
spec: networkres.NfTablesRule{
MatchLimit: &networkres.NfTablesLimitMatch{
PacketRatePerSecond: 5,
},
},
expectedRules: [][]expr.Any{
{
&expr.Limit{
Type: expr.LimitTypePkts,
Rate: 5,
Burst: 5,
Unit: expr.LimitTimeSecond,
},
},
},
},
{
name: "counter",
spec: networkres.NfTablesRule{
AnonCounter: true,
},
expectedRules: [][]expr.Any{
{
&expr.Counter{},
},
},
},
{
name: "ct state",
spec: networkres.NfTablesRule{
MatchConntrackState: &networkres.NfTablesConntrackStateMatch{
States: []uint32{
uint32(nethelpers.ConntrackStateInvalid),
},
},
},
expectedRules: [][]expr.Any{
{
&expr.Ct{
Key: expr.CtKeySTATE,
Register: 1,
},
&expr.Bitwise{
DestRegister: 1,
SourceRegister: 1,
Len: 4,
Mask: []byte{0x01, 0x00, 0x00, 0x00},
Xor: []byte{0x00, 0x00, 0x00, 0x00},
},
&expr.Cmp{
Op: expr.CmpOpNeq,
Register: 1,
Data: []byte{0x00, 0x00, 0x00, 0x00},
},
},
},
},
{
name: "ct states",
spec: networkres.NfTablesRule{
MatchConntrackState: &networkres.NfTablesConntrackStateMatch{
States: []uint32{
uint32(nethelpers.ConntrackStateRelated),
uint32(nethelpers.ConntrackStateEstablished),
},
},
},
expectedRules: [][]expr.Any{
{
&expr.Ct{
Key: expr.CtKeySTATE,
Register: 1,
},
&expr.Lookup{
SourceRegister: 1,
SetID: 0,
},
},
},
expectedSets: []network.NfTablesSet{
{
Kind: network.SetKindConntrackState,
ConntrackStates: []nethelpers.ConntrackState{
nethelpers.ConntrackStateRelated,
nethelpers.ConntrackStateEstablished,
},
},
},
},
} {
t.Run(test.name, func(t *testing.T) {
result, err := network.NfTablesRule(&test.spec).Compile()

View File

@ -476,6 +476,7 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
spec.Type = nethelpers.ChainTypeFilter
spec.Hook = nethelpers.ChainHookPrerouting
spec.Priority = nethelpers.ChainPriorityFilter
spec.Policy = nethelpers.VerdictAccept
spec.Rules = []network.NfTablesRule{
{
@ -514,6 +515,7 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
spec.Type = nethelpers.ChainTypeRoute
spec.Hook = nethelpers.ChainHookOutput
spec.Priority = nethelpers.ChainPriorityFilter
spec.Policy = nethelpers.VerdictAccept
spec.Rules = []network.NfTablesRule{
{
@ -525,7 +527,7 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
},
{
MatchOIfName: &network.NfTablesIfNameMatch{
InterfaceName: "lo",
InterfaceNames: []string{"lo"},
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},

View File

@ -241,6 +241,7 @@ func (suite *ManagerSuite) TestReconcile() {
asrt.Equal(nethelpers.ChainTypeFilter, spec.Type)
asrt.Equal(nethelpers.ChainHookPrerouting, spec.Hook)
asrt.Equal(nethelpers.ChainPriorityFilter, spec.Priority)
asrt.Equal(nethelpers.VerdictAccept, spec.Policy)
asrt.Len(spec.Rules, 2)
if len(spec.Rules) != 2 {

View File

@ -115,6 +115,7 @@ func (ctrl *NfTablesChainController) Run(ctx context.Context, r controller.Runti
Hooknum: pointer.To(nftables.ChainHook(chain.TypedSpec().Hook)),
Priority: pointer.To(nftables.ChainPriority(chain.TypedSpec().Priority)),
Type: nftables.ChainType(chain.TypedSpec().Type),
Policy: pointer.To(nftables.ChainPolicy(chain.TypedSpec().Policy)),
})
for _, rule := range chain.TypedSpec().Rules {
@ -127,14 +128,12 @@ func (ctrl *NfTablesChainController) Run(ctx context.Context, r controller.Runti
// check for lookup rules and add/fix up the set ID if needed
for i := range compiledRule {
if lookup, ok := compiledRule[i].(*expr.Lookup); ok {
setID++
if lookup.SetID >= uint32(len(compiled.Sets)) {
return fmt.Errorf("invalid set ID %d in lookup", lookup.SetID)
}
set := compiled.Sets[lookup.SetID]
setName := "_set" + strconv.Itoa(int(setID))
setName := "__set" + strconv.Itoa(int(setID))
if err = conn.AddSet(&nftables.Set{
Table: talosTable,
@ -142,14 +141,19 @@ func (ctrl *NfTablesChainController) Run(ctx context.Context, r controller.Runti
Name: setName,
Anonymous: true,
Constant: true,
Interval: true,
Interval: set.IsInterval(),
KeyType: set.KeyType(),
}, set.SetElements()); err != nil {
return fmt.Errorf("error adding nftables set for chain %s: %w", nfChain.Name, err)
}
lookup.SetID = setID
lookup.SetName = setName
lookupOp := *lookup
lookupOp.SetID = setID
lookupOp.SetName = setName
compiledRule[i] = &lookupOp
setID++
}
}

View File

@ -63,10 +63,11 @@ func (s *NfTablesChainSuite) TestAcceptLo() {
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPrioritySecurity
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchOIfName: &network.NfTablesIfNameMatch{
InterfaceName: "lo",
InterfaceNames: []string{"lo"},
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
@ -82,11 +83,127 @@ func (s *NfTablesChainSuite) TestAcceptLo() {
}`)
}
func (s *NfTablesChainSuite) TestAcceptMultipleIfnames() {
chain := network.NewNfTablesChain(network.NamespaceName, "test1")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPrioritySecurity
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchIIfName: &network.NfTablesIfNameMatch{
InterfaceNames: []string{"eth0", "eth1"},
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
// this seems to be a bug in the nft cli, it doesn't decoded the ifname anonymous set correctly
// it might be that google/nftables doesn't set some magic on the anonymous set for the nft CLI to pick it up (?)
s.checkNftOutput(`table inet talos-test {
chain test1 {
type filter hook input priority security; policy accept;
iifname { "", "" } accept
}
}`)
}
func (s *NfTablesChainSuite) TestPolicyDrop() {
chain := network.NewNfTablesChain(network.NamespaceName, "test1")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPrioritySecurity
chain.TypedSpec().Policy = nethelpers.VerdictDrop
chain.TypedSpec().Rules = []network.NfTablesRule{
{
Verdict: pointer.To(nethelpers.VerdictAccept),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
s.checkNftOutput(`table inet talos-test {
chain test1 {
type filter hook input priority security; policy drop;
accept
}
}`)
}
func (s *NfTablesChainSuite) TestICMPLimit() {
chain := network.NewNfTablesChain(network.NamespaceName, "test1")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPrioritySecurity
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchLayer4: &network.NfTablesLayer4Match{
Protocol: nethelpers.ProtocolICMP,
},
MatchLimit: &network.NfTablesLimitMatch{
PacketRatePerSecond: 5,
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
s.checkNftOutput(`table inet talos-test {
chain test1 {
type filter hook input priority security; policy accept;
meta l4proto icmp limit rate 5/second accept
}
}`)
}
func (s *NfTablesChainSuite) TestConntrackCounter() {
chain := network.NewNfTablesChain(network.NamespaceName, "test1")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPrioritySecurity
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchConntrackState: &network.NfTablesConntrackStateMatch{
States: []uint32{
uint32(nethelpers.ConntrackStateEstablished),
uint32(nethelpers.ConntrackStateRelated),
},
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
{
MatchConntrackState: &network.NfTablesConntrackStateMatch{
States: []uint32{
uint32(nethelpers.ConntrackStateInvalid),
},
},
AnonCounter: true,
Verdict: pointer.To(nethelpers.VerdictDrop),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
s.checkNftOutput(`table inet talos-test {
chain test1 {
type filter hook input priority security; policy accept;
ct state { established, related } accept
ct state invalid counter packets 0 bytes 0 drop
}
}`)
}
func (s *NfTablesChainSuite) TestMatchMarksSubnets() {
chain1 := network.NewNfTablesChain(network.NamespaceName, "test1")
chain1.TypedSpec().Type = nethelpers.ChainTypeFilter
chain1.TypedSpec().Hook = nethelpers.ChainHookInput
chain1.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain1.TypedSpec().Policy = nethelpers.VerdictAccept
chain1.TypedSpec().Rules = []network.NfTablesRule{
{
MatchMark: &network.NfTablesMark{
@ -96,6 +213,7 @@ func (s *NfTablesChainSuite) TestMatchMarksSubnets() {
MatchSourceAddress: &network.NfTablesAddressMatch{
IncludeSubnets: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/8"),
netip.MustParsePrefix("0::/0"),
},
ExcludeSubnets: []netip.Prefix{
netip.MustParsePrefix("10.3.0.0/16"),
@ -117,6 +235,7 @@ func (s *NfTablesChainSuite) TestMatchMarksSubnets() {
chain2.TypedSpec().Type = nethelpers.ChainTypeFilter
chain2.TypedSpec().Hook = nethelpers.ChainHookInput
chain2.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain2.TypedSpec().Policy = nethelpers.VerdictAccept
chain2.TypedSpec().Rules = []network.NfTablesRule{
{
MatchDestinationAddress: &network.NfTablesAddressMatch{
@ -137,7 +256,6 @@ func (s *NfTablesChainSuite) TestMatchMarksSubnets() {
chain test1 {
type filter hook input priority filter; policy accept;
meta mark & 0x00000060 == 0x00000020 ip saddr != { 10.0.0.0-10.2.255.255, 10.4.0.0-10.255.255.255 } ip daddr { 192.168.0.0/24 } accept
meta mark & 0x00000060 == 0x00000020 meta nfproto ipv6 accept
}
chain test2 {
@ -152,6 +270,7 @@ func (s *NfTablesChainSuite) TestUpdateChains() {
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchSourceAddress: &network.NfTablesAddressMatch{
@ -221,6 +340,7 @@ func (s *NfTablesChainSuite) TestClampMSS() {
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
ClampMSS: &network.NfTablesClampMSS{
@ -245,6 +365,7 @@ func (s *NfTablesChainSuite) TestL4Match() {
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchDestinationAddress: &network.NfTablesAddressMatch{
@ -277,8 +398,90 @@ func (s *NfTablesChainSuite) TestL4Match() {
s.checkNftOutput(`table inet talos-test {
chain test-tcp {
type filter hook input priority filter; policy accept;
ip daddr { 10.0.0.0/8 } tcp dport { 1023-1024, 1027-1028 } drop
ip6 daddr { 2001::/16 } tcp dport { 1023-1024, 1027-1028 } drop
ip daddr { 10.0.0.0/8 } tcp dport { 1023-1025, 1027-1029 } drop
ip6 daddr { 2001::/16 } tcp dport { 1023-1025, 1027-1029 } drop
}
}`)
}
func (s *NfTablesChainSuite) TestL4Match2() {
chain := network.NewNfTablesChain(network.NamespaceName, "test-tcp")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchSourceAddress: &network.NfTablesAddressMatch{
IncludeSubnets: []netip.Prefix{
netip.MustParsePrefix("10.0.0.0/8"),
},
Invert: true,
},
MatchLayer4: &network.NfTablesLayer4Match{
Protocol: nethelpers.ProtocolTCP,
MatchDestinationPort: &network.NfTablesPortMatch{
Ranges: []network.PortRange{
{
Lo: 1023,
Hi: 1023,
},
{
Lo: 1024,
Hi: 1024,
},
},
},
},
Verdict: pointer.To(nethelpers.VerdictDrop),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
s.checkNftOutput(`table inet talos-test {
chain test-tcp {
type filter hook input priority filter; policy accept;
ip saddr != { 10.0.0.0/8 } tcp dport { 1023, 1024 } drop
meta nfproto ipv6 tcp dport { 1023, 1024 } drop
}
}`)
}
func (s *NfTablesChainSuite) TestL4MatchAny() {
chain := network.NewNfTablesChain(network.NamespaceName, "test-tcp")
chain.TypedSpec().Type = nethelpers.ChainTypeFilter
chain.TypedSpec().Hook = nethelpers.ChainHookInput
chain.TypedSpec().Priority = nethelpers.ChainPriorityFilter
chain.TypedSpec().Policy = nethelpers.VerdictAccept
chain.TypedSpec().Rules = []network.NfTablesRule{
{
MatchSourceAddress: &network.NfTablesAddressMatch{
IncludeSubnets: []netip.Prefix{
netip.MustParsePrefix("0.0.0.0/0"),
},
},
MatchLayer4: &network.NfTablesLayer4Match{
Protocol: nethelpers.ProtocolTCP,
MatchDestinationPort: &network.NfTablesPortMatch{
Ranges: []network.PortRange{
{
Lo: 1023,
Hi: 1023,
},
},
},
},
Verdict: pointer.To(nethelpers.VerdictAccept),
},
}
s.Require().NoError(s.State().Create(s.Ctx(), chain))
s.checkNftOutput(`table inet talos-test {
chain test-tcp {
type filter hook input priority filter; policy accept;
meta nfproto ipv4 tcp dport { 1023 } accept
}
}`)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1421,6 +1421,11 @@ func (m *NfTablesChainSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if m.Policy != 0 {
i = encodeVarint(dAtA, i, uint64(m.Policy))
i--
dAtA[i] = 0x28
}
if len(m.Rules) > 0 {
for iNdEx := len(m.Rules) - 1; iNdEx >= 0; iNdEx-- {
size, err := m.Rules[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
@ -1492,6 +1497,59 @@ func (m *NfTablesClampMSS) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *NfTablesConntrackStateMatch) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
}
size := m.SizeVT()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *NfTablesConntrackStateMatch) MarshalToVT(dAtA []byte) (int, error) {
size := m.SizeVT()
return m.MarshalToSizedBufferVT(dAtA[:size])
}
func (m *NfTablesConntrackStateMatch) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
if m == nil {
return 0, nil
}
i := len(dAtA)
_ = i
var l int
_ = l
if m.unknownFields != nil {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.States) > 0 {
var pksize2 int
for _, num := range m.States {
pksize2 += sov(uint64(num))
}
i -= pksize2
j1 := i
for _, num := range m.States {
for num >= 1<<7 {
dAtA[j1] = uint8(uint64(num)&0x7f | 0x80)
num >>= 7
j1++
}
dAtA[j1] = uint8(num)
j1++
}
i = encodeVarint(dAtA, i, uint64(pksize2))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *NfTablesIfNameMatch) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
@ -1522,18 +1580,20 @@ func (m *NfTablesIfNameMatch) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if len(m.InterfaceNames) > 0 {
for iNdEx := len(m.InterfaceNames) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.InterfaceNames[iNdEx])
copy(dAtA[i:], m.InterfaceNames[iNdEx])
i = encodeVarint(dAtA, i, uint64(len(m.InterfaceNames[iNdEx])))
i--
dAtA[i] = 0x1a
}
}
if m.Operator != 0 {
i = encodeVarint(dAtA, i, uint64(m.Operator))
i--
dAtA[i] = 0x10
}
if len(m.InterfaceName) > 0 {
i -= len(m.InterfaceName)
copy(dAtA[i:], m.InterfaceName)
i = encodeVarint(dAtA, i, uint64(len(m.InterfaceName)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
@ -1595,6 +1655,44 @@ func (m *NfTablesLayer4Match) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *NfTablesLimitMatch) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
}
size := m.SizeVT()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *NfTablesLimitMatch) MarshalToVT(dAtA []byte) (int, error) {
size := m.SizeVT()
return m.MarshalToSizedBufferVT(dAtA[:size])
}
func (m *NfTablesLimitMatch) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
if m == nil {
return 0, nil
}
i := len(dAtA)
_ = i
var l int
_ = l
if m.unknownFields != nil {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if m.PacketRatePerSecond != 0 {
i = encodeVarint(dAtA, i, uint64(m.PacketRatePerSecond))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func (m *NfTablesMark) MarshalVT() (dAtA []byte, err error) {
if m == nil {
return nil, nil
@ -1718,6 +1816,36 @@ func (m *NfTablesRule) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields)
}
if m.AnonCounter {
i--
if m.AnonCounter {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x60
}
if m.MatchConntrackState != nil {
size, err := m.MatchConntrackState.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarint(dAtA, i, uint64(size))
i--
dAtA[i] = 0x5a
}
if m.MatchLimit != nil {
size, err := m.MatchLimit.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarint(dAtA, i, uint64(size))
i--
dAtA[i] = 0x52
}
if m.ClampMss != nil {
size, err := m.ClampMss.MarshalToSizedBufferVT(dAtA[:i])
if err != nil {
@ -3892,6 +4020,9 @@ func (m *NfTablesChainSpec) SizeVT() (n int) {
n += 1 + l + sov(uint64(l))
}
}
if m.Policy != 0 {
n += 1 + sov(uint64(m.Policy))
}
n += len(m.unknownFields)
return n
}
@ -3909,19 +4040,38 @@ func (m *NfTablesClampMSS) SizeVT() (n int) {
return n
}
func (m *NfTablesConntrackStateMatch) SizeVT() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.States) > 0 {
l = 0
for _, e := range m.States {
l += sov(uint64(e))
}
n += 1 + sov(uint64(l)) + l
}
n += len(m.unknownFields)
return n
}
func (m *NfTablesIfNameMatch) SizeVT() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.InterfaceName)
if l > 0 {
n += 1 + l + sov(uint64(l))
}
if m.Operator != 0 {
n += 1 + sov(uint64(m.Operator))
}
if len(m.InterfaceNames) > 0 {
for _, s := range m.InterfaceNames {
l = len(s)
n += 1 + l + sov(uint64(l))
}
}
n += len(m.unknownFields)
return n
}
@ -3947,6 +4097,19 @@ func (m *NfTablesLayer4Match) SizeVT() (n int) {
return n
}
func (m *NfTablesLimitMatch) SizeVT() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.PacketRatePerSecond != 0 {
n += 1 + sov(uint64(m.PacketRatePerSecond))
}
n += len(m.unknownFields)
return n
}
func (m *NfTablesMark) SizeVT() (n int) {
if m == nil {
return 0
@ -4023,6 +4186,17 @@ func (m *NfTablesRule) SizeVT() (n int) {
l = m.ClampMss.SizeVT()
n += 1 + l + sov(uint64(l))
}
if m.MatchLimit != nil {
l = m.MatchLimit.SizeVT()
n += 1 + l + sov(uint64(l))
}
if m.MatchConntrackState != nil {
l = m.MatchConntrackState.SizeVT()
n += 1 + l + sov(uint64(l))
}
if m.AnonCounter {
n += 2
}
n += len(m.unknownFields)
return n
}
@ -8257,6 +8431,25 @@ func (m *NfTablesChainSpec) UnmarshalVT(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Policy", wireType)
}
m.Policy = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Policy |= enums.NethelpersNfTablesVerdict(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])
@ -8340,6 +8533,133 @@ func (m *NfTablesClampMSS) UnmarshalVT(dAtA []byte) error {
}
return nil
}
func (m *NfTablesConntrackStateMatch) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: NfTablesConntrackStateMatch: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: NfTablesConntrackStateMatch: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType == 0 {
var v uint32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.States = append(m.States, v)
} else if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
packedLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if packedLen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + packedLen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
var elementCount int
var count int
for _, integer := range dAtA[iNdEx:postIndex] {
if integer < 128 {
count++
}
}
elementCount = count
if elementCount != 0 && len(m.States) == 0 {
m.States = make([]uint32, 0, elementCount)
}
for iNdEx < postIndex {
var v uint32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.States = append(m.States, v)
}
} else {
return fmt.Errorf("proto: wrong wireType = %d for field States", wireType)
}
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLength
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *NfTablesIfNameMatch) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@ -8369,9 +8689,28 @@ func (m *NfTablesIfNameMatch) UnmarshalVT(dAtA []byte) error {
return fmt.Errorf("proto: NfTablesIfNameMatch: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType)
}
m.Operator = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Operator |= enums.NethelpersMatchOperator(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceName", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field InterfaceNames", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@ -8399,27 +8738,8 @@ func (m *NfTablesIfNameMatch) UnmarshalVT(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.InterfaceName = string(dAtA[iNdEx:postIndex])
m.InterfaceNames = append(m.InterfaceNames, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Operator", wireType)
}
m.Operator = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Operator |= enums.NethelpersMatchOperator(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])
@ -8584,6 +8904,76 @@ func (m *NfTablesLayer4Match) UnmarshalVT(dAtA []byte) error {
}
return nil
}
func (m *NfTablesLimitMatch) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: NfTablesLimitMatch: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: NfTablesLimitMatch: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field PacketRatePerSecond", wireType)
}
m.PacketRatePerSecond = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.PacketRatePerSecond |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLength
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *NfTablesMark) UnmarshalVT(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@ -9113,6 +9503,98 @@ func (m *NfTablesRule) UnmarshalVT(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 10:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MatchLimit", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.MatchLimit == nil {
m.MatchLimit = &NfTablesLimitMatch{}
}
if err := m.MatchLimit.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 11:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MatchConntrackState", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLength
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.MatchConntrackState == nil {
m.MatchConntrackState = &NfTablesConntrackStateMatch{}
}
if err := m.MatchConntrackState.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 12:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AnonCounter", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.AnonCounter = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skip(dAtA[iNdEx:])

View File

@ -0,0 +1,20 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package nethelpers
//go:generate enumer -type=ConntrackState -linecomment -text
// ConntrackState is a conntrack state.
type ConntrackState uint32
// ConntrackState constants.
//
//structprotogen:gen_enum
const (
ConntrackStateNew ConntrackState = 0x08 // new
ConntrackStateRelated ConntrackState = 0x04 // related
ConntrackStateEstablished ConntrackState = 0x02 // established
ConntrackStateInvalid ConntrackState = 0x01 // invalid
)

View File

@ -0,0 +1,78 @@
// Code generated by "enumer -type=ConntrackState -linecomment -text"; DO NOT EDIT.
package nethelpers
import (
"fmt"
)
const (
_ConntrackStateName_0 = "invalidestablished"
_ConntrackStateName_1 = "related"
_ConntrackStateName_2 = "new"
)
var (
_ConntrackStateIndex_0 = [...]uint8{0, 7, 18}
_ConntrackStateIndex_1 = [...]uint8{0, 7}
_ConntrackStateIndex_2 = [...]uint8{0, 3}
)
func (i ConntrackState) String() string {
switch {
case 1 <= i && i <= 2:
i -= 1
return _ConntrackStateName_0[_ConntrackStateIndex_0[i]:_ConntrackStateIndex_0[i+1]]
case i == 4:
return _ConntrackStateName_1
case i == 8:
return _ConntrackStateName_2
default:
return fmt.Sprintf("ConntrackState(%d)", i)
}
}
var _ConntrackStateValues = []ConntrackState{1, 2, 4, 8}
var _ConntrackStateNameToValueMap = map[string]ConntrackState{
_ConntrackStateName_0[0:7]: 1,
_ConntrackStateName_0[7:18]: 2,
_ConntrackStateName_1[0:7]: 4,
_ConntrackStateName_2[0:3]: 8,
}
// ConntrackStateString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func ConntrackStateString(s string) (ConntrackState, error) {
if val, ok := _ConntrackStateNameToValueMap[s]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to ConntrackState values", s)
}
// ConntrackStateValues returns all values of the enum
func ConntrackStateValues() []ConntrackState {
return _ConntrackStateValues
}
// IsAConntrackState returns "true" if the value is listed in the enum definition. "false" otherwise
func (i ConntrackState) IsAConntrackState() bool {
for _, v := range _ConntrackStateValues {
if i == v {
return true
}
}
return false
}
// MarshalText implements the encoding.TextMarshaler interface for ConntrackState
func (i ConntrackState) MarshalText() ([]byte, error) {
return []byte(i.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface for ConntrackState
func (i *ConntrackState) UnmarshalText(text []byte) error {
var err error
*i, err = ConntrackStateString(string(text))
return err
}

View File

@ -0,0 +1,16 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package nethelpers
//go:generate enumer -type=DefaultAction -linecomment -text
// DefaultAction is a default firewall action.
type DefaultAction int
// DefaultAction constants.
const (
DefaultActionAccept DefaultAction = iota // accept
DefaultActionBlock // block
)

View File

@ -0,0 +1,61 @@
// Code generated by "enumer -type=DefaultAction -linecomment -text"; DO NOT EDIT.
package nethelpers
import (
"fmt"
)
const _DefaultActionName = "acceptblock"
var _DefaultActionIndex = [...]uint8{0, 6, 11}
func (i DefaultAction) String() string {
if i < 0 || i >= DefaultAction(len(_DefaultActionIndex)-1) {
return fmt.Sprintf("DefaultAction(%d)", i)
}
return _DefaultActionName[_DefaultActionIndex[i]:_DefaultActionIndex[i+1]]
}
var _DefaultActionValues = []DefaultAction{0, 1}
var _DefaultActionNameToValueMap = map[string]DefaultAction{
_DefaultActionName[0:6]: 0,
_DefaultActionName[6:11]: 1,
}
// DefaultActionString retrieves an enum value from the enum constants string name.
// Throws an error if the param is not part of the enum.
func DefaultActionString(s string) (DefaultAction, error) {
if val, ok := _DefaultActionNameToValueMap[s]; ok {
return val, nil
}
return 0, fmt.Errorf("%s does not belong to DefaultAction values", s)
}
// DefaultActionValues returns all values of the enum
func DefaultActionValues() []DefaultAction {
return _DefaultActionValues
}
// IsADefaultAction returns "true" if the value is listed in the enum definition. "false" otherwise
func (i DefaultAction) IsADefaultAction() bool {
for _, v := range _DefaultActionValues {
if i == v {
return true
}
}
return false
}
// MarshalText implements the encoding.TextMarshaler interface for DefaultAction
func (i DefaultAction) MarshalText() ([]byte, error) {
return []byte(i.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface for DefaultAction
func (i *DefaultAction) UnmarshalText(text []byte) error {
var err error
*i, err = DefaultActionString(string(text))
return err
}

View File

@ -13,6 +13,8 @@ type Protocol uint8
//
//structprotogen:gen_enum
const (
ProtocolTCP Protocol = 0x6 // tcp
ProtocolUDP Protocol = 0x11 // udp
ProtocolICMP Protocol = 0x1 // icmp
ProtocolTCP Protocol = 0x6 // tcp
ProtocolUDP Protocol = 0x11 // udp
ProtocolICMPv6 Protocol = 0x3a // icmpv6
)

View File

@ -7,31 +7,41 @@ import (
)
const (
_ProtocolName_0 = "tcp"
_ProtocolName_1 = "udp"
_ProtocolName_0 = "icmp"
_ProtocolName_1 = "tcp"
_ProtocolName_2 = "udp"
_ProtocolName_3 = "icmpv6"
)
var (
_ProtocolIndex_0 = [...]uint8{0, 3}
_ProtocolIndex_0 = [...]uint8{0, 4}
_ProtocolIndex_1 = [...]uint8{0, 3}
_ProtocolIndex_2 = [...]uint8{0, 3}
_ProtocolIndex_3 = [...]uint8{0, 6}
)
func (i Protocol) String() string {
switch {
case i == 6:
case i == 1:
return _ProtocolName_0
case i == 17:
case i == 6:
return _ProtocolName_1
case i == 17:
return _ProtocolName_2
case i == 58:
return _ProtocolName_3
default:
return fmt.Sprintf("Protocol(%d)", i)
}
}
var _ProtocolValues = []Protocol{6, 17}
var _ProtocolValues = []Protocol{1, 6, 17, 58}
var _ProtocolNameToValueMap = map[string]Protocol{
_ProtocolName_0[0:3]: 6,
_ProtocolName_1[0:3]: 17,
_ProtocolName_0[0:4]: 1,
_ProtocolName_1[0:3]: 6,
_ProtocolName_2[0:3]: 17,
_ProtocolName_3[0:6]: 58,
}
// ProtocolString retrieves an enum value from the enum constants string name.

View File

@ -106,15 +106,31 @@ func (o NfTablesChainSpec) DeepCopy() NfTablesChainSpec {
if o.Rules[i2].MatchIIfName != nil {
cp.Rules[i2].MatchIIfName = new(NfTablesIfNameMatch)
*cp.Rules[i2].MatchIIfName = *o.Rules[i2].MatchIIfName
if o.Rules[i2].MatchIIfName.InterfaceNames != nil {
cp.Rules[i2].MatchIIfName.InterfaceNames = make([]string, len(o.Rules[i2].MatchIIfName.InterfaceNames))
copy(cp.Rules[i2].MatchIIfName.InterfaceNames, o.Rules[i2].MatchIIfName.InterfaceNames)
}
}
if o.Rules[i2].MatchOIfName != nil {
cp.Rules[i2].MatchOIfName = new(NfTablesIfNameMatch)
*cp.Rules[i2].MatchOIfName = *o.Rules[i2].MatchOIfName
if o.Rules[i2].MatchOIfName.InterfaceNames != nil {
cp.Rules[i2].MatchOIfName.InterfaceNames = make([]string, len(o.Rules[i2].MatchOIfName.InterfaceNames))
copy(cp.Rules[i2].MatchOIfName.InterfaceNames, o.Rules[i2].MatchOIfName.InterfaceNames)
}
}
if o.Rules[i2].MatchMark != nil {
cp.Rules[i2].MatchMark = new(NfTablesMark)
*cp.Rules[i2].MatchMark = *o.Rules[i2].MatchMark
}
if o.Rules[i2].MatchConntrackState != nil {
cp.Rules[i2].MatchConntrackState = new(NfTablesConntrackStateMatch)
*cp.Rules[i2].MatchConntrackState = *o.Rules[i2].MatchConntrackState
if o.Rules[i2].MatchConntrackState.States != nil {
cp.Rules[i2].MatchConntrackState.States = make([]uint32, len(o.Rules[i2].MatchConntrackState.States))
copy(cp.Rules[i2].MatchConntrackState.States, o.Rules[i2].MatchConntrackState.States)
}
}
if o.Rules[i2].MatchSourceAddress != nil {
cp.Rules[i2].MatchSourceAddress = new(NfTablesAddressMatch)
*cp.Rules[i2].MatchSourceAddress = *o.Rules[i2].MatchSourceAddress
@ -159,6 +175,10 @@ func (o NfTablesChainSpec) DeepCopy() NfTablesChainSpec {
}
}
}
if o.Rules[i2].MatchLimit != nil {
cp.Rules[i2].MatchLimit = new(NfTablesLimitMatch)
*cp.Rules[i2].MatchLimit = *o.Rules[i2].MatchLimit
}
if o.Rules[i2].ClampMSS != nil {
cp.Rules[i2].ClampMSS = new(NfTablesClampMSS)
*cp.Rules[i2].ClampMSS = *o.Rules[i2].ClampMSS

View File

@ -29,6 +29,7 @@ type NfTablesChainSpec struct {
Type nethelpers.NfTablesChainType `yaml:"type" protobuf:"1"`
Hook nethelpers.NfTablesChainHook `yaml:"hook" protobuf:"2"`
Priority nethelpers.NfTablesChainPriority `yaml:"priority" protobuf:"3"`
Policy nethelpers.NfTablesVerdict `yaml:"policy" protobuf:"5"`
Rules []NfTablesRule `yaml:"rules" protobuf:"4"`
}
@ -37,24 +38,27 @@ type NfTablesChainSpec struct {
//
//gotagsrewrite:gen
type NfTablesRule struct {
MatchIIfName *NfTablesIfNameMatch `yaml:"matchIIfName,omitempty" protobuf:"8"`
MatchOIfName *NfTablesIfNameMatch `yaml:"matchOIfName,omitempty" protobuf:"1"`
MatchMark *NfTablesMark `yaml:"matchMark,omitempty" protobuf:"3"`
MatchSourceAddress *NfTablesAddressMatch `yaml:"matchSourceAddress,omitempty" protobuf:"5"`
MatchDestinationAddress *NfTablesAddressMatch `yaml:"matchDestinationAddress,omitempty" protobuf:"6"`
MatchLayer4 *NfTablesLayer4Match `yaml:"matchLayer4,omitempty" protobuf:"7"`
MatchIIfName *NfTablesIfNameMatch `yaml:"matchIIfName,omitempty" protobuf:"8"`
MatchOIfName *NfTablesIfNameMatch `yaml:"matchOIfName,omitempty" protobuf:"1"`
MatchMark *NfTablesMark `yaml:"matchMark,omitempty" protobuf:"3"`
MatchConntrackState *NfTablesConntrackStateMatch `yaml:"matchConntrackState,omitempty" protobuf:"11"`
MatchSourceAddress *NfTablesAddressMatch `yaml:"matchSourceAddress,omitempty" protobuf:"5"`
MatchDestinationAddress *NfTablesAddressMatch `yaml:"matchDestinationAddress,omitempty" protobuf:"6"`
MatchLayer4 *NfTablesLayer4Match `yaml:"matchLayer4,omitempty" protobuf:"7"`
MatchLimit *NfTablesLimitMatch `yaml:"matchLimit,omitempty" protobuf:"10"`
ClampMSS *NfTablesClampMSS `yaml:"clampMSS,omitempty" protobuf:"9"`
SetMark *NfTablesMark `yaml:"setMark,omitempty" protobuf:"4"`
Verdict *nethelpers.NfTablesVerdict `yaml:"verdict,omitempty" protobuf:"2"`
ClampMSS *NfTablesClampMSS `yaml:"clampMSS,omitempty" protobuf:"9"`
SetMark *NfTablesMark `yaml:"setMark,omitempty" protobuf:"4"`
AnonCounter bool `yaml:"anonymousCounter,omitempty" protobuf:"12"`
Verdict *nethelpers.NfTablesVerdict `yaml:"verdict,omitempty" protobuf:"2"`
}
// NfTablesIfNameMatch describes the match on the interface name.
//
//gotagsrewrite:gen
type NfTablesIfNameMatch struct {
InterfaceName string `yaml:"interfaceName" protobuf:"1"`
Operator nethelpers.MatchOperator `yaml:"operator" protobuf:"2"`
InterfaceNames []string `yaml:"interfaceName" protobuf:"3"`
Operator nethelpers.MatchOperator `yaml:"operator" protobuf:"2"`
}
// NfTablesMark encodes packet mark match/update operation.
@ -118,6 +122,21 @@ type NfTablesClampMSS struct {
MTU uint16 `yaml:"mtu" protobuf:"1"`
}
// NfTablesLimitMatch describes the match on the packet rate.
//
//gotagsrewrite:gen
type NfTablesLimitMatch struct {
PacketRatePerSecond uint64 `yaml:"packetRatePerSecond" protobuf:"1"`
}
// NfTablesConntrackStateMatch describes the match on the connection tracking state.
//
//gotagsrewrite:gen
type NfTablesConntrackStateMatch struct {
// TODO: should be []nethelpers.ConntrackState, but structprotogen needs to be fixed to support it.
States []uint32 `yaml:"states" protobuf:"1"`
}
// NewNfTablesChain initializes a NfTablesChain resource.
func NewNfTablesChain(namespace resource.Namespace, id resource.ID) *NfTablesChain {
return typed.NewResource[NfTablesChainSpec, NfTablesChainExtension](
@ -135,8 +154,25 @@ func (NfTablesChainExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
Type: NfTablesChainType,
Aliases: []resource.Type{"chain", "chains"},
DefaultNamespace: NamespaceName,
PrintColumns: []meta.PrintColumn{},
Sensitivity: meta.NonSensitive,
PrintColumns: []meta.PrintColumn{
{
Name: "Type",
JSONPath: `{.type}`,
},
{
Name: "Hook",
JSONPath: `{.hook}`,
},
{
Name: "Priority",
JSONPath: `{.priority}`,
},
{
Name: "Policy",
JSONPath: `{.policy}`,
},
},
Sensitivity: meta.NonSensitive,
}
}

View File

@ -46,6 +46,7 @@ description: Talos gRPC API reference.
- [NethelpersAddressFlag](#talos.resource.definitions.enums.NethelpersAddressFlag)
- [NethelpersBondMode](#talos.resource.definitions.enums.NethelpersBondMode)
- [NethelpersBondXmitHashPolicy](#talos.resource.definitions.enums.NethelpersBondXmitHashPolicy)
- [NethelpersConntrackState](#talos.resource.definitions.enums.NethelpersConntrackState)
- [NethelpersDuplex](#talos.resource.definitions.enums.NethelpersDuplex)
- [NethelpersFailOverMAC](#talos.resource.definitions.enums.NethelpersFailOverMAC)
- [NethelpersFamily](#talos.resource.definitions.enums.NethelpersFamily)
@ -166,8 +167,10 @@ description: Talos gRPC API reference.
- [NfTablesAddressMatch](#talos.resource.definitions.network.NfTablesAddressMatch)
- [NfTablesChainSpec](#talos.resource.definitions.network.NfTablesChainSpec)
- [NfTablesClampMSS](#talos.resource.definitions.network.NfTablesClampMSS)
- [NfTablesConntrackStateMatch](#talos.resource.definitions.network.NfTablesConntrackStateMatch)
- [NfTablesIfNameMatch](#talos.resource.definitions.network.NfTablesIfNameMatch)
- [NfTablesLayer4Match](#talos.resource.definitions.network.NfTablesLayer4Match)
- [NfTablesLimitMatch](#talos.resource.definitions.network.NfTablesLimitMatch)
- [NfTablesMark](#talos.resource.definitions.network.NfTablesMark)
- [NfTablesPortMatch](#talos.resource.definitions.network.NfTablesPortMatch)
- [NfTablesRule](#talos.resource.definitions.network.NfTablesRule)
@ -1028,6 +1031,21 @@ NethelpersBondXmitHashPolicy is a bond hash policy.
<a name="talos.resource.definitions.enums.NethelpersConntrackState"></a>
### NethelpersConntrackState
NethelpersConntrackState is a conntrack state.
| Name | Number | Description |
| ---- | ------ | ----------- |
| NETHELPERS_CONNTRACKSTATE_UNSPECIFIED | 0 | |
| CONNTRACK_STATE_NEW | 8 | |
| CONNTRACK_STATE_RELATED | 4 | |
| CONNTRACK_STATE_ESTABLISHED | 2 | |
| CONNTRACK_STATE_INVALID | 1 | |
<a name="talos.resource.definitions.enums.NethelpersDuplex"></a>
### NethelpersDuplex
@ -1285,8 +1303,10 @@ NethelpersProtocol is a inet protocol.
| Name | Number | Description |
| ---- | ------ | ----------- |
| NETHELPERS_PROTOCOL_UNSPECIFIED | 0 | |
| PROTOCOL_ICMP | 1 | |
| PROTOCOL_TCP | 6 | |
| PROTOCOL_UDP | 17 | |
| PROTOCOL_ICM_PV6 | 58 | |
@ -3041,6 +3061,7 @@ NfTablesChainSpec describes status of rendered secrets.
| hook | [talos.resource.definitions.enums.NethelpersNfTablesChainHook](#talos.resource.definitions.enums.NethelpersNfTablesChainHook) | | |
| priority | [talos.resource.definitions.enums.NethelpersNfTablesChainPriority](#talos.resource.definitions.enums.NethelpersNfTablesChainPriority) | | |
| rules | [NfTablesRule](#talos.resource.definitions.network.NfTablesRule) | repeated | |
| policy | [talos.resource.definitions.enums.NethelpersNfTablesVerdict](#talos.resource.definitions.enums.NethelpersNfTablesVerdict) | | |
@ -3066,6 +3087,21 @@ MSS is limited by the `MaxMTU` so that:
<a name="talos.resource.definitions.network.NfTablesConntrackStateMatch"></a>
### NfTablesConntrackStateMatch
NfTablesConntrackStateMatch describes the match on the connection tracking state.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| states | [uint32](#uint32) | repeated | |
<a name="talos.resource.definitions.network.NfTablesIfNameMatch"></a>
### NfTablesIfNameMatch
@ -3074,8 +3110,8 @@ NfTablesIfNameMatch describes the match on the interface name.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| interface_name | [string](#string) | | |
| operator | [talos.resource.definitions.enums.NethelpersMatchOperator](#talos.resource.definitions.enums.NethelpersMatchOperator) | | |
| interface_names | [string](#string) | repeated | |
@ -3099,6 +3135,21 @@ NfTablesLayer4Match describes the match on the transport layer protocol.
<a name="talos.resource.definitions.network.NfTablesLimitMatch"></a>
### NfTablesLimitMatch
NfTablesLimitMatch describes the match on the packet rate.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| packet_rate_per_second | [uint64](#uint64) | | |
<a name="talos.resource.definitions.network.NfTablesMark"></a>
### NfTablesMark
@ -3154,6 +3205,9 @@ NfTablesRule describes a single rule in the nftables chain.
| match_layer4 | [NfTablesLayer4Match](#talos.resource.definitions.network.NfTablesLayer4Match) | | |
| match_i_if_name | [NfTablesIfNameMatch](#talos.resource.definitions.network.NfTablesIfNameMatch) | | |
| clamp_mss | [NfTablesClampMSS](#talos.resource.definitions.network.NfTablesClampMSS) | | |
| match_limit | [NfTablesLimitMatch](#talos.resource.definitions.network.NfTablesLimitMatch) | | |
| match_conntrack_state | [NfTablesConntrackStateMatch](#talos.resource.definitions.network.NfTablesConntrackStateMatch) | | |
| anon_counter | [bool](#bool) | | |