Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions incus-osd/api/system_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ type SystemNetworkInterface struct {
Routes []SystemNetworkRoute `json:"routes,omitempty" yaml:"routes,omitempty"`
Hwaddr string `json:"hwaddr" yaml:"hwaddr"`
Roles []string `json:"roles,omitempty" yaml:"roles,omitempty"`
LLDP bool `json:"lldp" yaml:"lldp"`
LLDP bool `json:"lldp,omitempty" yaml:"lldp,omitempty"`
StrictHwaddr bool `json:"strict_hwaddr,omitempty" yaml:"strict_hwaddr,omitempty"`
}

// SystemNetworkBond contains information about a network bond.
Expand All @@ -61,7 +62,7 @@ type SystemNetworkBond struct {
Hwaddr string `json:"hwaddr,omitempty" yaml:"hwaddr,omitempty"`
Members []string `json:"members,omitempty" yaml:"members,omitempty"`
Roles []string `json:"roles,omitempty" yaml:"roles,omitempty"`
LLDP bool `json:"lldp" yaml:"lldp"`
LLDP bool `json:"lldp,omitempty" yaml:"lldp,omitempty"`
}

// SystemNetworkVLAN contains information about a network vlan.
Expand Down
6 changes: 6 additions & 0 deletions incus-osd/cmd/incus-osd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/lxc/incus-os/incus-osd/internal/applications"
"github.com/lxc/incus-os/incus-osd/internal/install"
"github.com/lxc/incus-os/incus-osd/internal/keyring"
"github.com/lxc/incus-os/incus-osd/internal/nftables"
"github.com/lxc/incus-os/incus-osd/internal/providers"
"github.com/lxc/incus-os/incus-osd/internal/recovery"
"github.com/lxc/incus-os/incus-osd/internal/rest"
Expand Down Expand Up @@ -359,6 +360,11 @@ func startup(ctx context.Context, s *state.State, t *tui.TUI) error { //nolint:r
// Perform network configuration.
slog.InfoContext(ctx, "Bringing up the network")

err = nftables.ApplyHwaddrFilters(ctx, s.System.Network.Config)
if err != nil {
return err
}

err = systemd.ApplyNetworkConfiguration(ctx, s, s.System.Network.Config, 30*time.Second, s.OS.SuccessfulBoot, providers.Refresh, delayInitialUpdateCheck)
if err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions incus-osd/internal/nftables/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package nftables offers functions to manage the nftables firewall.
package nftables
58 changes: 58 additions & 0 deletions incus-osd/internal/nftables/nft.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package nftables

import (
"context"
"strings"

"github.com/lxc/incus/v6/shared/subprocess"

"github.com/lxc/incus-os/incus-osd/api"
)

// SetupChains creates the initial system-wide chains.
func SetupChains(ctx context.Context) error {
// Ensure we have a bridge table.
_, err := subprocess.RunCommandContext(ctx, "nft", "add", "table", "bridge", "incus-osd")
if err != nil {
return err
}

// Ensure we have a MAC filtering chain.
_, err = subprocess.RunCommandContext(ctx, "nft", "add", "chain", "bridge", "incus-osd", "mac-filters", "{ type filter hook output priority 0 ; policy accept ; }")
if err != nil {
return err
}

return nil
}

// ApplyHwaddrFilters ensures that all interfaces with the StrictHwaddr flag set get a suitable MAC filter in place.
func ApplyHwaddrFilters(ctx context.Context, networkCfg *api.SystemNetworkConfig) error {
// Make sure we have the expected chains.
err := SetupChains(ctx)
if err != nil {
return err
}

// Empty the chain.
_, err = subprocess.RunCommandContext(ctx, "nft", "flush", "chain", "bridge", "incus-osd", "mac-filters")
if err != nil {
return err
}

// Apply the filters.
for _, iface := range networkCfg.Interfaces {
if !iface.StrictHwaddr {
continue
}

underlyingDevice := "_p" + strings.ToLower(strings.ReplaceAll(iface.Hwaddr, ":", ""))

_, err = subprocess.RunCommandContext(ctx, "nft", "add", "rule", "bridge", "incus-osd", "mac-filters", "oif", underlyingDevice, "ether", "saddr", "!=", iface.Hwaddr, "drop")
if err != nil {
return err
}
}

return nil
}
9 changes: 9 additions & 0 deletions incus-osd/internal/rest/api_system_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/lxc/incus-os/incus-osd/api"
"github.com/lxc/incus-os/incus-osd/internal/nftables"
"github.com/lxc/incus-os/incus-osd/internal/providers"
"github.com/lxc/incus-os/incus-osd/internal/rest/response"
"github.com/lxc/incus-os/incus-osd/internal/seed"
Expand Down Expand Up @@ -124,6 +125,14 @@ func (s *Server) apiSystemNetwork(w http.ResponseWriter, r *http.Request) {

slog.InfoContext(r.Context(), "Applying new network configuration")

err = nftables.ApplyHwaddrFilters(r.Context(), newConfig.Config)
if err != nil {
slog.ErrorContext(r.Context(), "Failed to update network configuration: "+err.Error())
_ = response.InternalError(err).Render(w)

return
}

err = systemd.ApplyNetworkConfiguration(r.Context(), s.state, newConfig.Config, 30*time.Second, false, providers.Refresh, false)
if err != nil {
slog.ErrorContext(r.Context(), "Failed to update network configuration: "+err.Error())
Expand Down
Loading