From a75a860174ca0c8a8f8c6adecf496094215b5dd4 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 13 Jul 2021 09:05:48 -0700 Subject: [PATCH] cli/sdk: Allow applying redirect-traffic rules in a provided Linux namespace (#10564) --- .changelog/10564.txt | 6 ++++++ .../connect/redirecttraffic/redirect_traffic.go | 4 ++++ sdk/iptables/iptables.go | 15 ++++++++++----- sdk/iptables/iptables_executor_linux.go | 11 ++++++++++- sdk/iptables/iptables_executor_unsupported.go | 4 +++- .../content/commands/connect/redirect-traffic.mdx | 3 +++ 6 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 .changelog/10564.txt diff --git a/.changelog/10564.txt b/.changelog/10564.txt new file mode 100644 index 000000000..dcdb3c8e0 --- /dev/null +++ b/.changelog/10564.txt @@ -0,0 +1,6 @@ +```release-note:feature +cli: allow running `redirect-traffic` command in a provided Linux namespace. +``` +```release-note:feature +sdk: allow applying `iptables` rules in a provided Linux namespace. +``` diff --git a/command/connect/redirecttraffic/redirect_traffic.go b/command/connect/redirecttraffic/redirect_traffic.go index f368bf4c2..a6084ea19 100644 --- a/command/connect/redirecttraffic/redirect_traffic.go +++ b/command/connect/redirecttraffic/redirect_traffic.go @@ -44,6 +44,7 @@ type cmd struct { excludeOutboundPorts []string excludeOutboundCIDRs []string excludeUIDs []string + netNS string } func (c *cmd) init() { @@ -62,6 +63,8 @@ func (c *cmd) init() { "Outbound CIDR to exclude from traffic redirection. May be provided multiple times.") c.flags.Var((*flags.AppendSliceValue)(&c.excludeUIDs), "exclude-uid", "Additional user ID to exclude from traffic redirection. May be provided multiple times.") + c.flags.StringVar(&c.netNS, "netns", "", "The network namespace where traffic redirection rules should apply."+ + "This must be a path to the network namespace, e.g. /var/run/netns/foo.") c.http = &flags.HTTPFlags{} flags.Merge(c.flags, c.http.ClientFlags()) @@ -130,6 +133,7 @@ func (c *cmd) generateConfigFromFlags() (iptables.Config, error) { ProxyUserID: c.proxyUID, ProxyInboundPort: c.proxyInboundPort, ProxyOutboundPort: c.proxyOutboundPort, + NetNS: c.netNS, } // When proxyID is provided, we set up cfg with values diff --git a/sdk/iptables/iptables.go b/sdk/iptables/iptables.go index f2531c15a..c80776833 100644 --- a/sdk/iptables/iptables.go +++ b/sdk/iptables/iptables.go @@ -6,16 +6,16 @@ import ( ) const ( - // Chain to intercept inbound traffic + // ProxyInboundChain is the chain to intercept inbound traffic. ProxyInboundChain = "CONSUL_PROXY_INBOUND" - // Chain to redirect inbound traffic to the proxy + // ProxyInboundRedirectChain is the chain to redirect inbound traffic to the proxy. ProxyInboundRedirectChain = "CONSUL_PROXY_IN_REDIRECT" - // Chain to intercept outbound traffic + // ProxyOutputChain is the chain to intercept outbound traffic. ProxyOutputChain = "CONSUL_PROXY_OUTPUT" - // Chain to redirect outbound traffic to the proxy + // ProxyOutputRedirectChain is the chain to redirect outbound traffic to the proxy ProxyOutputRedirectChain = "CONSUL_PROXY_REDIRECT" DefaultTProxyOutboundPort = 15001 @@ -49,6 +49,11 @@ type Config struct { // from traffic redirection. ExcludeUIDs []string + // NetNS is the network namespace where the traffic redirection rules + // should be applied. This must be a path to the network namespace, + // e.g. /var/run/netns/foo. + NetNS string + // IptablesProvider is the Provider that will apply iptables rules. IptablesProvider Provider } @@ -71,7 +76,7 @@ type Provider interface { // https://github.com/openservicemesh/osm/blob/650a1a1dcf081ae90825f3b5dba6f30a0e532725/pkg/injector/iptables.go func Setup(cfg Config) error { if cfg.IptablesProvider == nil { - cfg.IptablesProvider = &iptablesExecutor{} + cfg.IptablesProvider = &iptablesExecutor{cfg: cfg} } err := validateConfig(cfg) diff --git a/sdk/iptables/iptables_executor_linux.go b/sdk/iptables/iptables_executor_linux.go index cbd9a7915..224e088eb 100644 --- a/sdk/iptables/iptables_executor_linux.go +++ b/sdk/iptables/iptables_executor_linux.go @@ -11,10 +11,19 @@ import ( // iptablesExecutor implements IptablesProvider using exec.Cmd. type iptablesExecutor struct { commands []*exec.Cmd + cfg Config } func (i *iptablesExecutor) AddRule(name string, args ...string) { - i.commands = append(i.commands, exec.Command(name, args...)) + if i.cfg.NetNS != "" { + // If network namespace is provided, then we need to execute the command in the given network namespace. + nsenterArgs := []string{fmt.Sprintf("--net=%s", i.cfg.NetNS), "--", name} + nsenterArgs = append(nsenterArgs, args...) + cmd := exec.Command("nsenter", nsenterArgs...) + i.commands = append(i.commands, cmd) + } else { + i.commands = append(i.commands, exec.Command(name, args...)) + } } func (i *iptablesExecutor) ApplyRules() error { diff --git a/sdk/iptables/iptables_executor_unsupported.go b/sdk/iptables/iptables_executor_unsupported.go index ba2e75ff7..b26f39f67 100644 --- a/sdk/iptables/iptables_executor_unsupported.go +++ b/sdk/iptables/iptables_executor_unsupported.go @@ -5,7 +5,9 @@ package iptables import "errors" // iptablesExecutor implements IptablesProvider and errors out on any non-linux OS. -type iptablesExecutor struct{} +type iptablesExecutor struct { + cfg Config +} func (i *iptablesExecutor) AddRule(_ string, _ ...string) {} diff --git a/website/content/commands/connect/redirect-traffic.mdx b/website/content/commands/connect/redirect-traffic.mdx index 4318cece9..6fd7c46c3 100644 --- a/website/content/commands/connect/redirect-traffic.mdx +++ b/website/content/commands/connect/redirect-traffic.mdx @@ -53,6 +53,9 @@ Usage: `consul connect redirect-traffic [options]` - `exclude-uid` - Additional user ID to exclude from traffic redirection. May be provided multiple times. +- `netns` - The Linux network namespace where traffic redirection rules should apply. + This must be a path to the network namespace, e.g. /var/run/netns/foo. + #### Enterprise Options @include 'http_api_namespace_options.mdx'