diff --git a/.changelog/10564.txt b/.changelog/10564.txt new file mode 100644 index 0000000000..dcdb3c8e04 --- /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 f368bf4c25..a6084ea195 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 f2531c15a7..c80776833d 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 cbd9a79152..224e088eb7 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 ba2e75ff77..b26f39f67e 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 4318cece9b..6fd7c46c37 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'