5.6 KiB
title, updated, created, source
| title | updated | created | source |
|---|---|---|---|
| Configuring Consul DNS Forwarding in Ubuntu 16.04 | 2021-09-01 13:45:43Z | 2021-09-01 13:45:43Z | https://andydote.co.uk/2019/05/29/consul-dns-forwarding/ |
-
DEPRECATED - This doesn’t work properly
Please see this post for an updated version which works!
One of the advantages of using Consul for service discovery is that besides an HTTP API, you can also query it by DNS.
The DNS server is listening on port
8600by default, and you can query both A records or SRV records from it. SRV records are useful as they contain additional properties (priority,weightandport), and you can get multiple records back from a single query, letting you do load balancing client side:$ dig @localhost -p 8600 consul.service.consul SRV +short 1 10 8300 vagrant1.node.dc1.consul. 1 14 8300 vagrant2.node.dc1.consul. 2 100 8300 vagrant3.node.dc1.consul.A Records are also useful, as it means we should be able to treat services registered to Consul like any other domain - but it doesn’t work:
$ curl http://consul.service.consul:8500 curl: (6) Could not resolve host: consul.service.consulThe reason for this is that the system’s built-in DNS resolver doesn’t know how to query Consul. We can, however, configure it to forward any
*.consulrequests to Consul. -
Solution - Forward DNS queries to Consul
As I usually target Ubuntu based machines, this means configuring
systemd-resolvedto forward to Consul. However, we want to keep Consul listening on it’s default port (8600), andsystemd-resolvedcan only forward requests to port53, so we need also to configureiptablesto redirect the requests.The steps are as follows:
- Configure
systemd-resolvedto forward.consulTLD queries to the local consul agent - Configure
iptablesto redirect53to8600
So let’s get to it!
-
IPTables configuration changes don’t persist through reboots, so the easiest way to solve this is with the
iptables-persistentpackage.Typically I am scripting machines (using [Packer] or [Vagrant]), so I configure the install to be non-interactive:
echo iptables-persistent iptables-persistent/autosave_v4 boolean false | sudo debconf-set-selections echo iptables-persistent iptables-persistent/autosave_v6 boolean false | sudo debconf-set-selections sudo DEBIAN_FRONTEND=noninteractive apt install -yq iptables-persistent -
The file to change is
/etc/systemd/resolved.conf. By default it looks like this:[Resolve] #DNS= #FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844 #Domains= #LLMNR=yes #DNSSEC=noWe need to change the
DNSandDomainslines - either editing the file by hand, or scripting a replacement withsed:sudo sed -i 's/#DNS=/DNS=127.0.0.1/g; s/#Domains=/Domains=~consul/g' /etc/systemd/resolved.confThe result of which is the file now reading like this:
[Resolve] DNS=127.0.0.1 #FallbackDNS=8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844 Domains=~consul #LLMNR=yes #DNSSEC=noBy specifying the
Domainsas~consul, we are telling resolvd to forward requests for theconsulTLD to the server specified in theDNSline. -
For compatibility with some applications (e.g.
curlandping), we also need to update/etc/resolv.confto specify our local nameserver. You do this not by editing the file directly!Instead, we need to add
nameserver 127.0.0.1to/etc/resolvconf/resolv.conf.d/head. Again, I will script this, and as we needsudoto write to the file, the easiest way is to useteeto append the line and then runresolvconf -uto apply the change:echo "nameserver 127.0.0.1" | sudo tee --append /etc/resolvconf/resolv.conf.d/head sudo resolvconf -u -
Finally, we need to configure iptables so that when
systemd-resolvedsends a DNS query to localhost on port53, it gets redirected to port8600. We’ll do this for both TCP and UDP requests, and then usenetfilter-persistentto make the rules persistent:sudo iptables -t nat -A OUTPUT -d localhost -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600 sudo iptables -t nat -A OUTPUT -d localhost -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600 sudo netfilter-persistent save
- Configure
-
First, we can test that both Consul and Systemd-Resolved return an address for a consul service:
$ dig @localhost -p 8600 consul.service.consul +short 10.0.2.15 $ dig @localhost consul.service.consul +short 10.0.2.15And now we can try using
curlto verify that we can resolve consul domains and normal domains still:$ curl -s -o /dev/null -w "%{http_code}\n" http://consul.service.consul:8500/ui/ 200 $ curl -s -o /dev/null -w "%{http_code}\n" http://google.com 301 -
There are also guides available on how to do this on Hashicorp’s website, covering other DNS resolvers too (such as BIND, Dnsmasq, Unbound).