Skip to content

Commit

Permalink
chore: allow bridge traffic with DHCP broadcast traffic
Browse files Browse the repository at this point in the history
This is required for siderolabs/sidero#1070, as
we need to allow DHCP traffic from Sidero controller running in a VM
through the bridge to other VMs.

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira committed Aug 23, 2023
1 parent c993164 commit 9608ef5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
4 changes: 2 additions & 2 deletions internal/integration/api/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/safe"
"github.com/cosi-project/runtime/pkg/state"
"github.com/siderolabs/go-pointer"
corev1 "k8s.io/api/core/v1"
nodev1 "k8s.io/api/node/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"

"github.com/siderolabs/talos/cmd/talosctl/pkg/talos/helpers"
"github.com/siderolabs/talos/internal/integration/base"
Expand Down Expand Up @@ -386,7 +386,7 @@ func (suite *ExtensionsSuite) TestExtensionsZFS() {
"/dev/null",
},
SecurityContext: &corev1.SecurityContext{
Privileged: pointer.Bool(true),
Privileged: pointer.To(true),
},
},
},
Expand Down
16 changes: 16 additions & 0 deletions pkg/provision/providers/qemu/launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/containernetworking/plugins/pkg/utils"
"github.com/coreos/go-iptables/iptables"
"github.com/google/uuid"
"github.com/siderolabs/gen/slices"
"github.com/siderolabs/go-blockdevice/blockdevice/partition/gpt"
Expand Down Expand Up @@ -161,6 +163,20 @@ func withCNI(ctx context.Context, config *LaunchConfig, f func(config *LaunchCon
)
}

cniChain := utils.FormatChainName(config.NetworkConfig.Name, containerID)

ipt, err := iptables.New()
if err != nil {
return fmt.Errorf("failed to initialize iptables: %w", err)
}

// don't masquerade traffic with "broadcast" destination from the VM
//
// no need to clean up the rule, as CNI drops the whole chain
if err = ipt.InsertUnique("nat", cniChain, 1, "--destination", "255.255.255.255/32", "-j", "ACCEPT"); err != nil {
return fmt.Errorf("failed to insert iptables rule to allow broadcast traffic: %w", err)
}

config.tapName = tapIface.Name
config.vmMAC = vmIface.Mac
config.ns = ns
Expand Down
60 changes: 60 additions & 0 deletions pkg/provision/providers/vm/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/containernetworking/cni/libcni"
"github.com/containernetworking/plugins/pkg/testutils"
"github.com/coreos/go-iptables/iptables"
"github.com/google/uuid"
"github.com/jsimonetti/rtnetlink"
"github.com/siderolabs/gen/slices"
Expand Down Expand Up @@ -130,6 +131,15 @@ func (p *Provisioner) CreateNetwork(ctx context.Context, state *State, network p
return fmt.Errorf("error parsing VM CNI config: %w", err)
}

// allow traffic on the bridge via `DOCKER-USER` chain
// Docker enables br-netfilter which causes layer2 packets to be filtered with iptables, but we'd like to skip that
// if Docker is not running, this will be no-op
//
// See https://serverfault.com/questions/963759/docker-breaks-libvirt-bridge-network for more details
if err = p.allowBridgeTraffic(state.BridgeName); err != nil {
return fmt.Errorf("error configuring DOCKER-USER chain: %w", err)
}

// configure bridge interface with network chaos if flag is set
if network.NetworkChaos {
if err = p.configureNetworkChaos(network, state, options); err != nil {
Expand All @@ -140,6 +150,52 @@ func (p *Provisioner) CreateNetwork(ctx context.Context, state *State, network p
return nil
}

func (p *Provisioner) allowBridgeTraffic(bridgeName string) error {
ipt, err := iptables.New()
if err != nil {
return fmt.Errorf("error initializing iptables: %w", err)
}

chainExists, err := ipt.ChainExists("filter", "DOCKER-USER")
if err != nil {
return fmt.Errorf("error checking chain existence: %w", err)
}

if !chainExists {
if err = ipt.NewChain("filter", "DOCKER-USER"); err != nil {
return fmt.Errorf("error creating DOCKER-USER chain: %w", err)
}
}

if err := ipt.InsertUnique("filter", "DOCKER-USER", 1, "-i", bridgeName, "-o", bridgeName, "-j", "ACCEPT"); err != nil {
return fmt.Errorf("error inserting rule into DOCKER-USER chain: %w", err)
}

return nil
}

func (p *Provisioner) dropBridgeTrafficRule(bridgeName string) error {
ipt, err := iptables.New()
if err != nil {
return fmt.Errorf("error initializing iptables: %w", err)
}

chainExists, err := ipt.ChainExists("filter", "DOCKER-USER")
if err != nil {
return fmt.Errorf("error checking chain existence: %w", err)
}

if !chainExists {
return nil
}

if err := ipt.DeleteIfExists("filter", "DOCKER-USER", "-i", bridgeName, "-o", bridgeName, "-j", "ACCEPT"); err != nil {
return fmt.Errorf("error deleting rule in DOCKER-USER chain: %w", err)
}

return nil
}

//nolint:gocyclo
func (p *Provisioner) configureNetworkChaos(network provision.NetworkRequest, state *State, options provision.Options) error {
if (network.Bandwidth != 0) && (network.Latency != 0 || network.Jitter != 0 || network.PacketLoss != 0 || network.PacketReorder != 0 || network.PacketCorrupt != 0) {
Expand Down Expand Up @@ -225,6 +281,10 @@ func (p *Provisioner) DestroyNetwork(state *State) error {
return fmt.Errorf("error deleting bridge interface: %w", err)
}

if err = p.dropBridgeTrafficRule(state.BridgeName); err != nil {
return fmt.Errorf("error dropping bridge traffic rule: %w", err)
}

return nil
}

Expand Down

0 comments on commit 9608ef5

Please sign in to comment.