Skip to content

Commit

Permalink
cli/sdk: Allow redirection to a different consul dns port (hashicorp#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ishustava authored Oct 21, 2022
1 parent 44c9c9b commit 2a25669
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changelog/15050.txt
Original file line number Diff line number Diff line change
@@ -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.
```
3 changes: 3 additions & 0 deletions command/connect/redirecttraffic/redirect_traffic.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type cmd struct {
// Flags.
nodeName string
consulDNSIP string
consulDNSPort int
proxyUID string
proxyID string
proxyInboundPort int
Expand All @@ -55,6 +56,7 @@ func (c *cmd) init() {
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.")
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.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.")
Expand Down Expand Up @@ -136,6 +138,7 @@ type trafficRedirectProxyConfig struct {
func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
cfg := iptables.Config{
ConsulDNSIP: c.consulDNSIP,
ConsulDNSPort: c.consulDNSPort,
ProxyUserID: c.proxyUID,
ProxyInboundPort: c.proxyInboundPort,
ProxyOutboundPort: c.proxyOutboundPort,
Expand Down
4 changes: 3 additions & 1 deletion command/connect/redirecttraffic/redirect_traffic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
var c cmd
c.init()
c.proxyUID = "1234"
c.proxyID = "test-proxy-id"
c.consulDNSIP = "10.0.34.16"
c.consulDNSPort = 8600
return c
},
consulServices: []api.AgentServiceRegistration{
Expand All @@ -151,6 +152,7 @@ func TestGenerateConfigFromFlags(t *testing.T) {
},
expCfg: iptables.Config{
ConsulDNSIP: "10.0.34.16",
ConsulDNSPort: 8600,
ProxyUserID: "1234",
ProxyInboundPort: 20000,
ProxyOutboundPort: iptables.DefaultTProxyOutboundPort,
Expand Down
19 changes: 18 additions & 1 deletion sdk/iptables/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package iptables

import (
"errors"
"fmt"
"strconv"
)

Expand Down Expand Up @@ -30,6 +31,9 @@ type Config struct {
// ConsulDNSIP is the IP for Consul DNS to direct DNS queries to.
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 string

Expand Down Expand Up @@ -107,14 +111,27 @@ func Setup(cfg Config) error {
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 != "" {
if cfg.ConsulDNSIP != "" && cfg.ConsulDNSPort == 0 {
// 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)
} 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.
Expand Down
57 changes: 57 additions & 0 deletions sdk/iptables/iptables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,63 @@ func TestSetup(t *testing.T) {
"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",
Config{
Expand Down
2 changes: 2 additions & 0 deletions website/content/commands/connect/redirect-traffic.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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-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.
This service ID must already be registered with the local agent.

Expand Down

0 comments on commit 2a25669

Please sign in to comment.