cli/sdk: Allow redirection to a different consul dns port (#15050)

This commit is contained in:
Iryna Shustava 2022-10-21 13:15:32 -06:00 committed by GitHub
parent 19d983936c
commit 46fe21a204
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 2 deletions

6
.changelog/15050.txt Normal file
View File

@ -0,0 +1,6 @@
```release-note:feature
cli: Add `-consul-dns-port` flag to the `consul connect redirect-traffic` command to allow forwarding DNS traffic to a specific Consul DNS port.
```
```release-note:feature
sdk: Configure `iptables` to forward DNS traffic to a specific DNS port.
```

View File

@ -38,6 +38,7 @@ type cmd struct {
// Flags. // Flags.
nodeName string nodeName string
consulDNSIP string consulDNSIP string
consulDNSPort int
proxyUID string proxyUID string
proxyID string proxyID string
proxyInboundPort int proxyInboundPort int
@ -55,6 +56,7 @@ func (c *cmd) init() {
c.flags.StringVar(&c.nodeName, "node-name", "", c.flags.StringVar(&c.nodeName, "node-name", "",
"The node name where the proxy service is registered. It requires proxy-id to be specified. This is needed if running in an environment without client agents.") "The node name where the proxy service is registered. It requires proxy-id to be specified. This is needed if running in an environment without client agents.")
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.consulDNSIP, "consul-dns-ip", "", "IP used to reach Consul DNS. If provided, DNS queries will be redirected to Consul.")
c.flags.IntVar(&c.consulDNSPort, "consul-dns-port", 0, "Port 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.")
@ -136,6 +138,7 @@ type trafficRedirectProxyConfig struct {
func (c *cmd) generateConfigFromFlags() (iptables.Config, error) { func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
cfg := iptables.Config{ cfg := iptables.Config{
ConsulDNSIP: c.consulDNSIP, ConsulDNSIP: c.consulDNSIP,
ConsulDNSPort: c.consulDNSPort,
ProxyUserID: c.proxyUID, ProxyUserID: c.proxyUID,
ProxyInboundPort: c.proxyInboundPort, ProxyInboundPort: c.proxyInboundPort,
ProxyOutboundPort: c.proxyOutboundPort, ProxyOutboundPort: c.proxyOutboundPort,

View File

@ -128,13 +128,14 @@ func TestGenerateConfigFromFlags(t *testing.T) {
}, },
}, },
{ {
name: "proxyID with Consul DNS IP provided", name: "proxyID with Consul DNS IP and port provided",
command: func() cmd { command: func() cmd {
var c cmd var c cmd
c.init() c.init()
c.proxyUID = "1234" c.proxyUID = "1234"
c.proxyID = "test-proxy-id" c.proxyID = "test-proxy-id"
c.consulDNSIP = "10.0.34.16" c.consulDNSIP = "10.0.34.16"
c.consulDNSPort = 8600
return c return c
}, },
consulServices: []api.AgentServiceRegistration{ consulServices: []api.AgentServiceRegistration{
@ -151,6 +152,7 @@ func TestGenerateConfigFromFlags(t *testing.T) {
}, },
expCfg: iptables.Config{ expCfg: iptables.Config{
ConsulDNSIP: "10.0.34.16", ConsulDNSIP: "10.0.34.16",
ConsulDNSPort: 8600,
ProxyUserID: "1234", ProxyUserID: "1234",
ProxyInboundPort: 20000, ProxyInboundPort: 20000,
ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, ProxyOutboundPort: iptables.DefaultTProxyOutboundPort,

View File

@ -2,6 +2,7 @@ package iptables
import ( import (
"errors" "errors"
"fmt"
"strconv" "strconv"
) )
@ -30,6 +31,9 @@ type Config struct {
// ConsulDNSIP is the IP for Consul DNS to direct DNS queries to. // ConsulDNSIP is the IP for Consul DNS to direct DNS queries to.
ConsulDNSIP string ConsulDNSIP string
// ConsulDNSPort is the port for Consul DNS to direct DNS queries to.
ConsulDNSPort int
// ProxyUserID is the user ID of the proxy process. // ProxyUserID is the user ID of the proxy process.
ProxyUserID string ProxyUserID string
@ -107,7 +111,7 @@ func Setup(cfg Config) error {
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. // 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 != "" { if cfg.ConsulDNSIP != "" && cfg.ConsulDNSPort == 0 {
// Traffic in the DNSChain is directed to the Consul DNS Service IP. // 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", "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) cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", DNSChain, "-p", "tcp", "--dport", "53", "-j", "DNAT", "--to-destination", cfg.ConsulDNSIP)
@ -115,6 +119,19 @@ func Setup(cfg Config) error {
// For outbound TCP and UDP traffic going to port 53 (DNS), jump to the DNSChain. // 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", "udp", "--dport", "53", "-j", DNSChain)
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "--dport", "53", "-j", DNSChain) cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "--dport", "53", "-j", DNSChain)
} else if cfg.ConsulDNSPort != 0 {
consulDNSIP := "127.0.0.1"
if cfg.ConsulDNSIP != "" {
consulDNSIP = cfg.ConsulDNSIP
}
consulDNSHostPort := fmt.Sprintf("%s:%d", consulDNSIP, cfg.ConsulDNSPort)
// Traffic in the DNSChain is directed to the Consul DNS Service IP.
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", DNSChain, "-p", "udp", "-d", consulDNSIP, "--dport", "53", "-j", "DNAT", "--to-destination", consulDNSHostPort)
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", DNSChain, "-p", "tcp", "-d", consulDNSIP, "--dport", "53", "-j", "DNAT", "--to-destination", consulDNSHostPort)
// For outbound TCP and UDP traffic going to port 53 (DNS), jump to the DNSChain. Only redirect traffic that's going to consul's DNS IP.
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "udp", "-d", consulDNSIP, "--dport", "53", "-j", DNSChain)
cfg.IptablesProvider.AddRule("iptables", "-t", "nat", "-A", "OUTPUT", "-p", "tcp", "-d", consulDNSIP, "--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.

View File

@ -64,6 +64,63 @@ 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 port provided",
Config{
ProxyUserID: "123",
ProxyInboundPort: 20000,
ConsulDNSPort: 8600,
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 -d 127.0.0.1 --dport 53 -j DNAT --to-destination 127.0.0.1:8600",
"iptables -t nat -A CONSUL_DNS_REDIRECT -p tcp -d 127.0.0.1 --dport 53 -j DNAT --to-destination 127.0.0.1:8600",
"iptables -t nat -A OUTPUT -p udp -d 127.0.0.1 --dport 53 -j CONSUL_DNS_REDIRECT",
"iptables -t nat -A OUTPUT -p tcp -d 127.0.0.1 --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",
},
},
{
"Consul DNS IP and port provided",
Config{
ProxyUserID: "123",
ProxyInboundPort: 20000,
ConsulDNSIP: "10.0.34.16",
ConsulDNSPort: 8600,
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 -d 10.0.34.16 --dport 53 -j DNAT --to-destination 10.0.34.16:8600",
"iptables -t nat -A CONSUL_DNS_REDIRECT -p tcp -d 10.0.34.16 --dport 53 -j DNAT --to-destination 10.0.34.16:8600",
"iptables -t nat -A OUTPUT -p udp -d 10.0.34.16 --dport 53 -j CONSUL_DNS_REDIRECT",
"iptables -t nat -A OUTPUT -p tcp -d 10.0.34.16 --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{

View File

@ -36,6 +36,8 @@ Usage: `consul connect redirect-traffic [options]`
- `-consul-dns-ip` - The IP address of the Consul DNS resolver. If provided, DNS queries will be redirected to the provided IP address for name resolution. - `-consul-dns-ip` - The IP address of the Consul DNS resolver. If provided, DNS queries will be redirected to the provided IP address for name resolution.
- `-consul-dns-port` - The port of the Consul DNS resolver. If provided, DNS queries will be redirected to the provided IP address for name resolution.
- `-proxy-id` - The [proxy service](/docs/connect/registration/service-registration) ID. - `-proxy-id` - The [proxy service](/docs/connect/registration/service-registration) ID.
This service ID must already be registered with the local agent. This service ID must already be registered with the local agent.