mirror of https://github.com/status-im/consul.git
command/redirect_traffic: Redirect DNS requests to Consul if -consul-dns-ip is passed in (#11480)
* command/redirect_traffic: add rules to redirect DNS to Consul. Currently uses a hack to get the consul dns service ip, and this hack only works when the service is deployed in the same namespace as consul. * command/redirect_traffic: redirect DNS to Consul when -consul-dns-ip is passed in * Add unit tests to Consul DNS IP table redirect rules Co-authored-by: Ashwin Venkatesh <ashwin@hashicorp.com> Co-authored-by: Iryna Shustava <ishustava@users.noreply.github.com>
This commit is contained in:
parent
aeaa0a6c96
commit
139c4eb844
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
sdk: Add support for iptable rules that allow DNS lookup redirection to Consul DNS.
|
||||||
|
```
|
|
@ -36,6 +36,7 @@ type cmd struct {
|
||||||
client *api.Client
|
client *api.Client
|
||||||
|
|
||||||
// Flags.
|
// Flags.
|
||||||
|
consulDNSIP string
|
||||||
proxyUID string
|
proxyUID string
|
||||||
proxyID string
|
proxyID string
|
||||||
proxyInboundPort int
|
proxyInboundPort int
|
||||||
|
@ -50,6 +51,7 @@ type cmd struct {
|
||||||
func (c *cmd) init() {
|
func (c *cmd) init() {
|
||||||
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
|
||||||
|
c.flags.StringVar(&c.consulDNSIP, "consul-dns-ip", "", "IP used to reach Consul DNS. If provided, DNS queries will be redirected to Consul.")
|
||||||
c.flags.StringVar(&c.proxyUID, "proxy-uid", "", "The user ID of the proxy to exclude from traffic redirection.")
|
c.flags.StringVar(&c.proxyUID, "proxy-uid", "", "The user ID of the proxy to exclude from traffic redirection.")
|
||||||
c.flags.StringVar(&c.proxyID, "proxy-id", "", "The service ID of the proxy service registered with Consul.")
|
c.flags.StringVar(&c.proxyID, "proxy-id", "", "The service ID of the proxy service registered with Consul.")
|
||||||
c.flags.IntVar(&c.proxyInboundPort, "proxy-inbound-port", 0, "The inbound port that the proxy is listening on.")
|
c.flags.IntVar(&c.proxyInboundPort, "proxy-inbound-port", 0, "The inbound port that the proxy is listening on.")
|
||||||
|
@ -130,6 +132,7 @@ type trafficRedirectProxyConfig struct {
|
||||||
// generateConfigFromFlags generates iptables.Config based on command flags.
|
// generateConfigFromFlags generates iptables.Config based on command flags.
|
||||||
func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
|
func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
|
||||||
cfg := iptables.Config{
|
cfg := iptables.Config{
|
||||||
|
ConsulDNSIP: c.consulDNSIP,
|
||||||
ProxyUserID: c.proxyUID,
|
ProxyUserID: c.proxyUID,
|
||||||
ProxyInboundPort: c.proxyInboundPort,
|
ProxyInboundPort: c.proxyInboundPort,
|
||||||
ProxyOutboundPort: c.proxyOutboundPort,
|
ProxyOutboundPort: c.proxyOutboundPort,
|
||||||
|
|
|
@ -127,6 +127,35 @@ func TestGenerateConfigFromFlags(t *testing.T) {
|
||||||
ProxyOutboundPort: iptables.DefaultTProxyOutboundPort,
|
ProxyOutboundPort: iptables.DefaultTProxyOutboundPort,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "proxyID with Consul DNS IP provided",
|
||||||
|
command: func() cmd {
|
||||||
|
var c cmd
|
||||||
|
c.init()
|
||||||
|
c.proxyUID = "1234"
|
||||||
|
c.proxyID = "test-proxy-id"
|
||||||
|
c.consulDNSIP = "10.0.34.16"
|
||||||
|
return c
|
||||||
|
},
|
||||||
|
consulServices: []api.AgentServiceRegistration{
|
||||||
|
{
|
||||||
|
Kind: api.ServiceKindConnectProxy,
|
||||||
|
ID: "test-proxy-id",
|
||||||
|
Name: "test-proxy",
|
||||||
|
Port: 20000,
|
||||||
|
Address: "1.1.1.1",
|
||||||
|
Proxy: &api.AgentServiceConnectProxyConfig{
|
||||||
|
DestinationServiceName: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expCfg: iptables.Config{
|
||||||
|
ConsulDNSIP: "10.0.34.16",
|
||||||
|
ProxyUserID: "1234",
|
||||||
|
ProxyInboundPort: 20000,
|
||||||
|
ProxyOutboundPort: iptables.DefaultTProxyOutboundPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "proxyID with bind_port(string) provided",
|
name: "proxyID with bind_port(string) provided",
|
||||||
command: func() cmd {
|
command: func() cmd {
|
||||||
|
|
|
@ -18,12 +18,18 @@ const (
|
||||||
// ProxyOutputRedirectChain is the 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"
|
||||||
|
|
||||||
|
// DNSChain is the chain to redirect outbound DNS traffic to Consul DNS.
|
||||||
|
DNSChain = "CONSUL_DNS_REDIRECT"
|
||||||
|
|
||||||
DefaultTProxyOutboundPort = 15001
|
DefaultTProxyOutboundPort = 15001
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config is used to configure which traffic interception and redirection
|
// Config is used to configure which traffic interception and redirection
|
||||||
// rules should be applied with the iptables commands.
|
// rules should be applied with the iptables commands.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// ConsulDNSIP is the IP for Consul DNS to direct DNS queries to.
|
||||||
|
ConsulDNSIP string
|
||||||
|
|
||||||
// ProxyUserID is the user ID of the proxy process.
|
// ProxyUserID is the user ID of the proxy process.
|
||||||
ProxyUserID string
|
ProxyUserID string
|
||||||
|
|
||||||
|
@ -90,7 +96,7 @@ func Setup(cfg Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create chains we will use for redirection.
|
// Create chains we will use for redirection.
|
||||||
chains := []string{ProxyInboundChain, ProxyInboundRedirectChain, ProxyOutputChain, ProxyOutputRedirectChain}
|
chains := []string{ProxyInboundChain, ProxyInboundRedirectChain, ProxyOutputChain, ProxyOutputRedirectChain, DNSChain}
|
||||||
for _, chain := range chains {
|
for _, chain := range chains {
|
||||||
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-N", chain)
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-N", chain)
|
||||||
}
|
}
|
||||||
|
@ -100,6 +106,17 @@ func Setup(cfg Config) error {
|
||||||
// Redirects outbound TCP traffic hitting PROXY_REDIRECT chain to Envoy's outbound listener port.
|
// Redirects outbound TCP traffic hitting PROXY_REDIRECT chain to Envoy's outbound listener port.
|
||||||
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", ProxyOutputRedirectChain, "-p", "tcp", "-j", "REDIRECT", "--to-port", strconv.Itoa(cfg.ProxyOutboundPort))
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", ProxyOutputRedirectChain, "-p", "tcp", "-j", "REDIRECT", "--to-port", strconv.Itoa(cfg.ProxyOutboundPort))
|
||||||
|
|
||||||
|
// The DNS rules are applied before the rules that directs all TCP traffic, so that the traffic going to port 53 goes through this rule first.
|
||||||
|
if cfg.ConsulDNSIP != "" {
|
||||||
|
// Traffic in the DNSChain is directed to the Consul DNS Service IP.
|
||||||
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", DNSChain, "-p", "udp", "--dport", "53", "-j", "DNAT", "--to-destination", cfg.ConsulDNSIP)
|
||||||
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", DNSChain, "-p", "tcp", "--dport", "53", "-j", "DNAT", "--to-destination", cfg.ConsulDNSIP)
|
||||||
|
|
||||||
|
// For outbound TCP and UDP traffic going to port 53 (DNS), jump to the DNSChain.
|
||||||
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "udp", "--dport", "53", "-j", DNSChain)
|
||||||
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "--dport", "53", "-j", DNSChain)
|
||||||
|
}
|
||||||
|
|
||||||
// For outbound TCP traffic jump from OUTPUT chain to PROXY_OUTPUT chain.
|
// For outbound TCP traffic jump from OUTPUT chain to PROXY_OUTPUT chain.
|
||||||
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "-j", ProxyOutputChain)
|
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "-j", ProxyOutputChain)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 15001",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 15001",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -35,6 +36,34 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -A CONSUL_PROXY_INBOUND -p tcp -j CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -A CONSUL_PROXY_INBOUND -p tcp -j CONSUL_PROXY_IN_REDIRECT",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Consul DNS IP provided",
|
||||||
|
Config{
|
||||||
|
ProxyUserID: "123",
|
||||||
|
ProxyInboundPort: 20000,
|
||||||
|
ConsulDNSIP: "10.0.34.16",
|
||||||
|
IptablesProvider: &fakeIptablesProvider{},
|
||||||
|
},
|
||||||
|
[]string{
|
||||||
|
"iptables -t nat -N CONSUL_PROXY_INBOUND",
|
||||||
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 15001",
|
||||||
|
"iptables -t nat -A CONSUL_DNS_REDIRECT -p udp --dport 53 -j DNAT --to-destination 10.0.34.16",
|
||||||
|
"iptables -t nat -A CONSUL_DNS_REDIRECT -p tcp --dport 53 -j DNAT --to-destination 10.0.34.16",
|
||||||
|
"iptables -t nat -A OUTPUT -p udp --dport 53 -j CONSUL_DNS_REDIRECT",
|
||||||
|
"iptables -t nat -A OUTPUT -p tcp --dport 53 -j CONSUL_DNS_REDIRECT",
|
||||||
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -d 127.0.0.1/32 -j RETURN",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -j CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_IN_REDIRECT -p tcp -j REDIRECT --to-port 20000",
|
||||||
|
"iptables -t nat -A PREROUTING -p tcp -j CONSUL_PROXY_INBOUND",
|
||||||
|
"iptables -t nat -A CONSUL_PROXY_INBOUND -p tcp -j CONSUL_PROXY_IN_REDIRECT",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"proxy outbound port is provided",
|
"proxy outbound port is provided",
|
||||||
Config{
|
Config{
|
||||||
|
@ -48,6 +77,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -72,6 +102,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -98,6 +129,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -124,6 +156,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -150,6 +183,7 @@ func TestSetup(t *testing.T) {
|
||||||
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_IN_REDIRECT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -N CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
"iptables -t nat -N CONSUL_PROXY_REDIRECT",
|
||||||
|
"iptables -t nat -N CONSUL_DNS_REDIRECT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
"iptables -t nat -A CONSUL_PROXY_REDIRECT -p tcp -j REDIRECT --to-port 21000",
|
||||||
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
"iptables -t nat -A OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||||
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
"iptables -t nat -A CONSUL_PROXY_OUTPUT -m owner --uid-owner 123 -j RETURN",
|
||||||
|
@ -171,7 +205,6 @@ func TestSetup(t *testing.T) {
|
||||||
require.Equal(t, c.expectedRules, c.cfg.IptablesProvider.Rules())
|
require.Equal(t, c.expectedRules, c.cfg.IptablesProvider.Rules())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetup_errors(t *testing.T) {
|
func TestSetup_errors(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue