Skip to content

Commit

Permalink
Use Go net ns switcher instead of nsenter
Browse files Browse the repository at this point in the history
This commit swaps out the previous implementation of using the
command `nsenter` to switch networking namespaces. By using the
Go impl of network namespace switching, read-only filesystems and
OSs without the `nsenter` command (such as Talos) should still
work.
  • Loading branch information
nicholascioli committed Jul 17, 2023
1 parent 15d573f commit 1ab66a5
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 15 deletions.
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ require (
)

require (
github.com/containernetworking/plugins v1.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
Expand All @@ -36,7 +37,7 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.2.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/time v0.2.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM=
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -36,6 +38,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8=
Expand Down Expand Up @@ -210,6 +214,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
Expand Down
58 changes: 45 additions & 13 deletions internal/iptables/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"time"

ns "github.com/containernetworking/plugins/pkg/ns"
log "github.com/sirupsen/logrus"

util "github.com/linkerd/linkerd2-proxy-init/internal/util"
Expand Down Expand Up @@ -229,28 +230,59 @@ func makeMultiportDestinations(portsToIgnore []string) [][]string {
}

func executeCommand(firewallConfiguration FirewallConfiguration, cmd *exec.Cmd) ([]byte, error) {
if firewallConfiguration.NetNs != "" {
// BusyBox's `nsenter` needs `--` to separate nsenter arguments from the
// command.
//
// See https://github.com/rancher/k3s/issues/1434#issuecomment-629315909
nsArgs := fmt.Sprintf("--net=%s", firewallConfiguration.NetNs)
args := append([]string{nsArgs, "--"}, cmd.Args...)
cmd = exec.Command("nsenter", args...)
}
// Always log the command to apply for tracing purposes
log.Info(cmd.String())

// Short out early if we are just simulating the network
if firewallConfiguration.SimulateOnly {
return nil, nil
}

out, err := cmd.CombinedOutput()
// Helper for reusing code when actually calling out to the command
doCommand := func() ([]byte, error) {
out, err := cmd.CombinedOutput()

if len(out) > 0 {
log.Infof("%s", out)
// Log out the output, if any
if len(out) > 0 {
log.Infof("%s", out)
}

return out, err
}

return out, err
// If we need to run within a target network namespace, then wrap the command
// in that namespace.
//
// Note: Network namespace switching is very volatile in Go. Care should be taken
// to ensure that all namespaced commands be wrapped in `targetNamespace.Do`, as explained in
// the link below.
//
// See: https://pkg.go.dev/github.com/containernetworking/plugins/pkg/ns#readme-do-the-recommended-thing
if firewallConfiguration.NetNs != "" {
// Fetch the target net namespace, ensuring that it exists
netNs, err := ns.GetNS(firewallConfiguration.NetNs)
if err != nil {
log.Errorf("could not switch to target network namespace \"%s\": %s", firewallConfiguration.NetNs, err.Error())
return nil, err
}

// Actually run the command in the namespace
// Note: Try to keep this code short! Goroutine switches might cause the
// namespace to change...
//
// Note: Result needs to be defined here since `netNs.Do` only returns
// an error.
result := make([]byte, 0)
err = netNs.Do(func(_ ns.NetNS) error {
result, err = doCommand()

return err
})

return result, err
} else {
return doCommand()
}
}

func (fc FirewallConfiguration) makeIgnoreUserID(chainName string, uid int, comment string) *exec.Cmd {
Expand Down

0 comments on commit 1ab66a5

Please sign in to comment.