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
a34f81cc29
commit
d396faf246
|
@ -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
|
||||
|
||||
// Flags.
|
||||
consulDNSIP string
|
||||
proxyUID string
|
||||
proxyID string
|
||||
proxyInboundPort int
|
||||
|
@ -50,6 +51,7 @@ type cmd struct {
|
|||
func (c *cmd) init() {
|
||||
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.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.")
|
||||
|
@ -130,6 +132,7 @@ type trafficRedirectProxyConfig struct {
|
|||
// generateConfigFromFlags generates iptables.Config based on command flags.
|
||||
func (c *cmd) generateConfigFromFlags() (iptables.Config, error) {
|
||||
cfg := iptables.Config{
|
||||
ConsulDNSIP: c.consulDNSIP,
|
||||
ProxyUserID: c.proxyUID,
|
||||
ProxyInboundPort: c.proxyInboundPort,
|
||||
ProxyOutboundPort: c.proxyOutboundPort,
|
||||
|
|
|
@ -127,6 +127,35 @@ func TestGenerateConfigFromFlags(t *testing.T) {
|
|||
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",
|
||||
command: func() cmd {
|
||||
|
|
|
@ -18,12 +18,18 @@ const (
|
|||
// ProxyOutputRedirectChain is the chain to redirect outbound traffic to the proxy
|
||||
ProxyOutputRedirectChain = "CONSUL_PROXY_REDIRECT"
|
||||
|
||||
// DNSChain is the chain to redirect outbound DNS traffic to Consul DNS.
|
||||
DNSChain = "CONSUL_DNS_REDIRECT"
|
||||
|
||||
DefaultTProxyOutboundPort = 15001
|
||||
)
|
||||
|
||||
// Config is used to configure which traffic interception and redirection
|
||||
// rules should be applied with the iptables commands.
|
||||
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 string
|
||||
|
||||
|
@ -90,7 +96,7 @@ func Setup(cfg Config) error {
|
|||
}
|
||||
|
||||
// Create chains we will use for redirection.
|
||||
chains := []string{ProxyInboundChain, ProxyInboundRedirectChain, ProxyOutputChain, ProxyOutputRedirectChain}
|
||||
chains := []string{ProxyInboundChain, ProxyInboundRedirectChain, ProxyOutputChain, ProxyOutputRedirectChain, DNSChain}
|
||||
for _, chain := range chains {
|
||||
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.
|
||||
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.
|
||||
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_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 OUTPUT -p tcp -j CONSUL_PROXY_OUTPUT",
|
||||
"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",
|
||||
},
|
||||
},
|
||||
{
|
||||
"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",
|
||||
Config{
|
||||
|
@ -48,6 +77,7 @@ func TestSetup(t *testing.T) {
|
|||
"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 21000",
|
||||
"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",
|
||||
|
@ -72,6 +102,7 @@ func TestSetup(t *testing.T) {
|
|||
"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 21000",
|
||||
"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",
|
||||
|
@ -98,6 +129,7 @@ func TestSetup(t *testing.T) {
|
|||
"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 21000",
|
||||
"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",
|
||||
|
@ -124,6 +156,7 @@ func TestSetup(t *testing.T) {
|
|||
"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 21000",
|
||||
"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",
|
||||
|
@ -150,6 +183,7 @@ func TestSetup(t *testing.T) {
|
|||
"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 21000",
|
||||
"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",
|
||||
|
@ -171,7 +205,6 @@ func TestSetup(t *testing.T) {
|
|||
require.Equal(t, c.expectedRules, c.cfg.IptablesProvider.Rules())
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetup_errors(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue