cli/sdk: Allow applying redirect-traffic rules in a provided Linux namespace (#10564)

This commit is contained in:
Iryna Shustava 2021-07-13 09:05:48 -07:00 committed by GitHub
parent ef32234ae1
commit a75a860174
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 7 deletions

6
.changelog/10564.txt Normal file
View File

@ -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.
```

View File

@ -44,6 +44,7 @@ type cmd struct {
excludeOutboundPorts []string excludeOutboundPorts []string
excludeOutboundCIDRs []string excludeOutboundCIDRs []string
excludeUIDs []string excludeUIDs []string
netNS string
} }
func (c *cmd) init() { func (c *cmd) init() {
@ -62,6 +63,8 @@ func (c *cmd) init() {
"Outbound CIDR to exclude from traffic redirection. May be provided multiple times.") "Outbound CIDR to exclude from traffic redirection. May be provided multiple times.")
c.flags.Var((*flags.AppendSliceValue)(&c.excludeUIDs), "exclude-uid", c.flags.Var((*flags.AppendSliceValue)(&c.excludeUIDs), "exclude-uid",
"Additional user ID to exclude from traffic redirection. May be provided multiple times.") "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{} c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags()) flags.Merge(c.flags, c.http.ClientFlags())
@ -130,6 +133,7 @@ func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
ProxyUserID: c.proxyUID, ProxyUserID: c.proxyUID,
ProxyInboundPort: c.proxyInboundPort, ProxyInboundPort: c.proxyInboundPort,
ProxyOutboundPort: c.proxyOutboundPort, ProxyOutboundPort: c.proxyOutboundPort,
NetNS: c.netNS,
} }
// When proxyID is provided, we set up cfg with values // When proxyID is provided, we set up cfg with values

View File

@ -6,16 +6,16 @@ import (
) )
const ( const (
// Chain to intercept inbound traffic // ProxyInboundChain is the chain to intercept inbound traffic.
ProxyInboundChain = "CONSUL_PROXY_INBOUND" 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" ProxyInboundRedirectChain = "CONSUL_PROXY_IN_REDIRECT"
// Chain to intercept outbound traffic // ProxyOutputChain is the chain to intercept outbound traffic.
ProxyOutputChain = "CONSUL_PROXY_OUTPUT" 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" ProxyOutputRedirectChain = "CONSUL_PROXY_REDIRECT"
DefaultTProxyOutboundPort = 15001 DefaultTProxyOutboundPort = 15001
@ -49,6 +49,11 @@ type Config struct {
// from traffic redirection. // from traffic redirection.
ExcludeUIDs []string 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 is the Provider that will apply iptables rules.
IptablesProvider Provider IptablesProvider Provider
} }
@ -71,7 +76,7 @@ type Provider interface {
// https://github.com/openservicemesh/osm/blob/650a1a1dcf081ae90825f3b5dba6f30a0e532725/pkg/injector/iptables.go // https://github.com/openservicemesh/osm/blob/650a1a1dcf081ae90825f3b5dba6f30a0e532725/pkg/injector/iptables.go
func Setup(cfg Config) error { func Setup(cfg Config) error {
if cfg.IptablesProvider == nil { if cfg.IptablesProvider == nil {
cfg.IptablesProvider = &iptablesExecutor{} cfg.IptablesProvider = &iptablesExecutor{cfg: cfg}
} }
err := validateConfig(cfg) err := validateConfig(cfg)

View File

@ -11,11 +11,20 @@ import (
// iptablesExecutor implements IptablesProvider using exec.Cmd. // iptablesExecutor implements IptablesProvider using exec.Cmd.
type iptablesExecutor struct { type iptablesExecutor struct {
commands []*exec.Cmd commands []*exec.Cmd
cfg Config
} }
func (i *iptablesExecutor) AddRule(name string, args ...string) { func (i *iptablesExecutor) AddRule(name string, args ...string) {
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...)) i.commands = append(i.commands, exec.Command(name, args...))
} }
}
func (i *iptablesExecutor) ApplyRules() error { func (i *iptablesExecutor) ApplyRules() error {
_, err := exec.LookPath("iptables") _, err := exec.LookPath("iptables")

View File

@ -5,7 +5,9 @@ package iptables
import "errors" import "errors"
// iptablesExecutor implements IptablesProvider and errors out on any non-linux OS. // 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) {} func (i *iptablesExecutor) AddRule(_ string, _ ...string) {}

View File

@ -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. - `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 #### Enterprise Options
@include 'http_api_namespace_options.mdx' @include 'http_api_namespace_options.mdx'