Skip to content

Commit 1e7e87f

Browse files
committed
fix: rework NFT rules for KubeSpan
Don't attach nft rules to the IPv6 KubeSpan addresses, as Linux can route these packets natively, they are directly assigned to the `kubespan` interface. Also fix the way MSS clamping is applied: previous implementation incorrectly triggered clamping to all addresses if the list of IPv4 or IPv6 addresses is empty. Previous rules: ``` table inet talos { chain kubespan_outgoing { type route hook output priority filter; policy accept; meta mark & 0x00000060 == 0x00000020 accept oifname "lo" accept ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } tcp flags & (syn | rst) == syn tcp option maxseg size > 1368 tcp option maxseg size set 1368 ip6 daddr { fd4e:cae:686b:1902:87f:e8ff:fe1e:b4e3, fd4e:cae:686b:1902:a44b:28ff:febf:e664, fd4e:cae:686b:1902:c049:f2ff:fe84:1785, fd4e:cae:686b:1902:c8c9:75ff:fe4c:5ba8 } tcp flags & (syn | rst) == syn tcp option maxseg size > 1348 tcp option maxseg size set 1348 ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept ip6 daddr { fd4e:cae:686b:1902:87f:e8ff:fe1e:b4e3, fd4e:cae:686b:1902:a44b:28ff:febf:e664, fd4e:cae:686b:1902:c049:f2ff:fe84:1785, fd4e:cae:686b:1902:c8c9:75ff:fe4c:5ba8 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept } chain kubespan_prerouting { type filter hook prerouting priority filter; policy accept; meta mark & 0x00000060 == 0x00000020 accept ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept ip6 daddr { fd4e:cae:686b:1902:87f:e8ff:fe1e:b4e3, fd4e:cae:686b:1902:a44b:28ff:febf:e664, fd4e:cae:686b:1902:c049:f2ff:fe84:1785, fd4e:cae:686b:1902:c8c9:75ff:fe4c:5ba8 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept } } ``` New rules: ``` table inet talos { chain kubespan_outgoing { type route hook output priority filter; policy accept; meta mark & 0x00000060 == 0x00000020 accept oifname "lo" accept ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } tcp flags & (syn | rst) == syn tcp option maxseg size > 1368 tcp option maxseg size set 1368 ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept } chain kubespan_prerouting { type filter hook prerouting priority filter; policy accept; meta mark & 0x00000060 == 0x00000020 accept ip daddr { 172.20.0.2, 172.20.0.4-172.20.0.6 } meta mark set meta mark & 0xffffffdf | 0x00000040 accept } } ``` Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
1 parent 51bcfb5 commit 1e7e87f

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

internal/app/machined/pkg/adapters/network/nftables_rule.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,13 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) {
655655
}
656656

657657
if a.NfTablesRule.ClampMSS != nil {
658-
rule4 = append(rule4, clampMSS(nftables.TableFamilyIPv4, a.NfTablesRule.ClampMSS.MTU)...)
659-
rule6 = append(rule6, clampMSS(nftables.TableFamilyIPv6, a.NfTablesRule.ClampMSS.MTU)...)
658+
if rule4 != nil {
659+
rule4 = append(rule4, clampMSS(nftables.TableFamilyIPv4, a.NfTablesRule.ClampMSS.MTU)...)
660+
}
661+
662+
if rule6 != nil {
663+
rule6 = append(rule6, clampMSS(nftables.TableFamilyIPv6, a.NfTablesRule.ClampMSS.MTU)...)
664+
}
660665
}
661666

662667
if a.NfTablesRule.SetMark != nil {

internal/app/machined/pkg/adapters/network/nftables_rule_test.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,15 +375,20 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
375375
},
376376
},
377377
},
378-
{
379-
name: "clamp MSS",
378+
{ //nolint:dupl
379+
name: "clamp MSS v4",
380380
spec: networkres.NfTablesRule{
381+
MatchDestinationAddress: &networkres.NfTablesAddressMatch{
382+
IncludeSubnets: []netip.Prefix{
383+
netip.MustParsePrefix("0.0.0.0/0"),
384+
},
385+
},
381386
ClampMSS: &networkres.NfTablesClampMSS{
382387
MTU: 1280,
383388
},
384389
},
385390
expectedRules: [][]expr.Any{
386-
{ //nolint:dupl
391+
{
387392
&expr.Meta{Key: expr.MetaKeyNFPROTO, Register: 1},
388393
&expr.Cmp{
389394
Op: expr.CmpOpEq,
@@ -441,7 +446,22 @@ func TestNfTablesRuleCompile(t *testing.T) { //nolint:tparallel
441446
Op: expr.ExthdrOpTcpopt,
442447
},
443448
},
444-
{ //nolint:dupl
449+
},
450+
},
451+
{ //nolint:dupl
452+
name: "clamp MSS v6",
453+
spec: networkres.NfTablesRule{
454+
MatchDestinationAddress: &networkres.NfTablesAddressMatch{
455+
IncludeSubnets: []netip.Prefix{
456+
netip.MustParsePrefix("::/0"),
457+
},
458+
},
459+
ClampMSS: &networkres.NfTablesClampMSS{
460+
MTU: 1280,
461+
},
462+
},
463+
expectedRules: [][]expr.Any{
464+
{
445465
&expr.Meta{Key: expr.MetaKeyNFPROTO, Register: 1},
446466
&expr.Cmp{
447467
Op: expr.CmpOpEq,

internal/app/machined/pkg/controllers/kubespan/manager.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
316316
})
317317
}
318318

319-
// build full allowedIPs set
320-
var allowedIPsBuilder netipx.IPSetBuilder
319+
// build a full set of routed over KubeSpan IPs,
320+
// note this doesn't include KubeSpan ULA addresses
321+
var routedIPsBuilder netipx.IPSetBuilder
321322

322323
for pubKey, peerSpec := range peerSpecs {
323324
// list of statuses and specs should be in sync at this point
@@ -327,12 +328,14 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
327328
// or if the peer connection state is up.
328329
if cfgSpec.ForceRouting || peerStatus.State == kubespan.PeerStateUp {
329330
for _, prefix := range peerSpec.AllowedIPs {
330-
allowedIPsBuilder.AddPrefix(prefix)
331+
if !network.IsULA(prefix.Addr(), network.ULAKubeSpan) {
332+
routedIPsBuilder.AddPrefix(prefix)
333+
}
331334
}
332335
}
333336
}
334337

335-
allowedIPsSet, err := allowedIPsBuilder.IPSet()
338+
routedIPsSet, err := routedIPsBuilder.IPSet()
336339
if err != nil {
337340
return fmt.Errorf("failed building allowed IPs set: %w", err)
338341
}
@@ -380,7 +383,7 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
380383
},
381384
{
382385
MatchDestinationAddress: &network.NfTablesAddressMatch{
383-
IncludeSubnets: allowedIPsSet.Prefixes(),
386+
IncludeSubnets: routedIPsSet.Prefixes(),
384387
},
385388
SetMark: &network.NfTablesMark{
386389
Mask: ^uint32(constants.KubeSpanDefaultFirewallMask),
@@ -425,15 +428,15 @@ func (ctrl *ManagerController) Run(ctx context.Context, r controller.Runtime, lo
425428
},
426429
{
427430
MatchDestinationAddress: &network.NfTablesAddressMatch{
428-
IncludeSubnets: allowedIPsSet.Prefixes(),
431+
IncludeSubnets: routedIPsSet.Prefixes(),
429432
},
430433
ClampMSS: &network.NfTablesClampMSS{
431434
MTU: uint16(mtu),
432435
},
433436
},
434437
{
435438
MatchDestinationAddress: &network.NfTablesAddressMatch{
436-
IncludeSubnets: allowedIPsSet.Prefixes(),
439+
IncludeSubnets: routedIPsSet.Prefixes(),
437440
},
438441
SetMark: &network.NfTablesMark{
439442
Mask: ^uint32(constants.KubeSpanDefaultFirewallMask),

internal/app/machined/pkg/controllers/network/nftables_chain_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@ func (s *NfTablesChainSuite) TestClampMSS() {
353353
chain.TypedSpec().Policy = nethelpers.VerdictAccept
354354
chain.TypedSpec().Rules = []network.NfTablesRule{
355355
{
356+
MatchDestinationAddress: &network.NfTablesAddressMatch{
357+
Invert: true, // match all addresses
358+
},
356359
ClampMSS: &network.NfTablesClampMSS{
357360
MTU: constants.KubeSpanLinkMTU,
358361
},

0 commit comments

Comments
 (0)