2014-04-09 03:56:26 +00:00
---
2020-04-07 18:55:19 +00:00
layout: docs
page_title: Forwarding
sidebar_current: docs-guides-forwarding
description: >-
By default, DNS is served from port 53. On most operating systems, this
requires elevated privileges. Instead of running Consul with an administrative
or root account, it is possible to instead forward appropriate queries to
Consul, running on an unprivileged port, from another DNS server or port
redirect.
2014-04-09 03:56:26 +00:00
---
2014-04-09 18:40:52 +00:00
# Forwarding DNS
2014-04-09 03:56:26 +00:00
2016-11-25 16:00:02 +00:00
By default, DNS is served from port 53. On most operating systems, this
2015-02-26 18:34:45 +00:00
requires elevated privileges. Instead of running Consul with an administrative
or root account, it is possible to instead forward appropriate queries to Consul,
2016-06-09 21:29:54 +00:00
running on an unprivileged port, from another DNS server or port redirect.
2014-04-09 03:56:26 +00:00
2019-03-25 14:24:28 +00:00
In this guide, we will demonstrate forwarding from:
2020-02-18 13:16:12 +00:00
- [BIND](#bind-setup)
2019-03-25 14:24:28 +00:00
- [dnsmasq](#dnsmasq-setup)
- [Unbound](#unbound-setup)
- [systemd-resolved](#systemd-resolved-setup)
- [iptables](#iptables-setup)
- [macOS](#macos-setup)
2014-04-09 03:56:26 +00:00
2019-03-25 14:24:28 +00:00
After configuring forwarding, we will demonstrate how to test the configuration. Finally, we will also provide some troubleshooting
2020-02-18 13:16:12 +00:00
guidance.
2019-03-25 14:24:28 +00:00
~> Note, by default, Consul does not resolve DNS
2015-08-30 16:01:49 +00:00
records outside the `.consul.` zone unless the
2015-08-29 01:27:26 +00:00
[recursors](/docs/agent/options.html#recursors) configuration option
2016-11-25 16:00:02 +00:00
has been set. As an example of how this changes Consul's behavior,
2015-08-30 16:01:49 +00:00
suppose a Consul DNS reply includes a CNAME record pointing outside
the `.consul` TLD. The DNS reply will only include CNAME records by
default. By contrast, when `recursors` is set and the upstream resolver is
functioning correctly, Consul will try to resolve CNAMEs and include
2016-11-25 16:00:02 +00:00
any records (e.g. A, AAAA, PTR) for them in its DNS reply.
2015-08-29 01:10:37 +00:00
2019-03-25 14:24:28 +00:00
## BIND Setup
Note, in this example, BIND and Consul are running on the same machine.
2014-04-09 03:56:26 +00:00
2019-03-25 14:24:28 +00:00
First, you have to disable DNSSEC so that Consul and [BIND](https://www.isc.org/downloads/bind/) can communicate. Here is an example of such a configuration:
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
```text
options {
listen-on port 53 { 127.0.0.1; };
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
allow-query { localhost; };
recursion yes;
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
dnssec-enable no;
dnssec-validation no;
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
managed-keys-directory "/var/named/dynamic";
};
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
include "/etc/named/consul.conf";
```
2014-04-09 03:56:26 +00:00
2014-04-09 18:08:32 +00:00
### Zone File
2016-11-25 16:00:02 +00:00
Then we set up a zone for our Consul managed records in `consul.conf`:
2014-04-09 03:56:26 +00:00
2014-10-19 23:40:10 +00:00
```text
zone "consul" IN {
type forward;
forward only;
forwarders { 127.0.0.1 port 8600; };
};
```
2014-04-09 03:56:26 +00:00
2015-02-26 18:34:45 +00:00
Here we assume Consul is running with default settings and is serving
2014-04-09 18:40:52 +00:00
DNS on port 8600.
2014-04-09 03:56:26 +00:00
2019-03-25 14:24:28 +00:00
## Dnsmasq Setup
2015-08-30 16:01:49 +00:00
2019-03-25 14:24:28 +00:00
[Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html) is typically configured via a `dnsmasq.conf` or a series of files in
2016-11-25 18:25:09 +00:00
the `/etc/dnsmasq.d` directory. In Dnsmasq's configuration file
2016-02-02 23:06:25 +00:00
(e.g. `/etc/dnsmasq.d/10-consul`), add the following:
2015-08-29 01:10:37 +00:00
```text
2016-02-02 23:06:25 +00:00
# Enable forward lookup of the 'consul' domain:
2015-08-29 01:10:37 +00:00
server=/consul/127.0.0.1#8600
2016-02-02 23:06:25 +00:00
# Uncomment and modify as appropriate to enable reverse DNS lookups for
# common netblocks found in RFC 1918, 5735, and 6598:
#rev-server=0.0.0.0/8,127.0.0.1#8600
#rev-server=10.0.0.0/8,127.0.0.1#8600
#rev-server=100.64.0.0/10,127.0.0.1#8600
#rev-server=127.0.0.1/8,127.0.0.1#8600
#rev-server=169.254.0.0/16,127.0.0.1#8600
#rev-server=172.16.0.0/12,127.0.0.1#8600
#rev-server=192.168.0.0/16,127.0.0.1#8600
#rev-server=224.0.0.0/4,127.0.0.1#8600
#rev-server=240.0.0.0/4,127.0.0.1#8600
2015-08-29 01:10:37 +00:00
```
2016-02-02 23:06:25 +00:00
Once that configuration is created, restart the `dnsmasq` service.
Additional useful settings in `dnsmasq` to consider include (see
[`dnsmasq(8)`](http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html)
for additional details):
```
# Accept DNS queries only from hosts whose address is on a local subnet.
#local-service
# Don't poll /etc/resolv.conf for changes.
#no-poll
# Don't read /etc/resolv.conf. Get upstream servers only from the command
# line or the dnsmasq configuration file (see the "server" directive below).
#no-resolv
# Specify IP address(es) of other DNS servers for queries not handled
2016-11-25 18:25:09 +00:00
# directly by consul. There is normally one 'server' entry set for every
# 'nameserver' parameter found in '/etc/resolv.conf'. See dnsmasq(8)'s
2016-02-02 23:06:25 +00:00
# 'server' configuration option for details.
#server=1.2.3.4
#server=208.67.222.222
#server=8.8.8.8
# Set the size of dnsmasq's cache. The default is 150 names. Setting the
# cache size to zero disables caching.
#cache-size=65536
```
2015-08-29 01:10:37 +00:00
2019-03-25 14:24:28 +00:00
## Unbound Setup
2017-08-17 20:25:47 +00:00
2019-03-25 14:24:28 +00:00
[Unbound](https://www.unbound.net/) is typically configured via a `unbound.conf` or a series of files in
2017-08-17 20:25:47 +00:00
the `/etc/unbound/unbound.conf.d` directory. In an Unbound configuration file
(e.g. `/etc/unbound/unbound.conf.d/consul.conf`), add the following:
```text
#Allow insecure queries to local resolvers
server:
do-not-query-localhost: no
domain-insecure: "consul"
#Add consul as a stub-zone
stub-zone:
name: "consul"
stub-addr: 127.0.0.1@8600
```
2020-02-18 13:16:12 +00:00
You may have to add the following line to the bottom of your
2017-08-17 20:25:47 +00:00
`/etc/unbound/unbound.conf` file for the new configuration to be included:
```text
include: "/etc/unbound/unbound.conf.d/*.conf"
```
2019-03-25 14:24:28 +00:00
## systemd-resolved Setup
2018-06-04 17:43:47 +00:00
2020-02-18 13:16:12 +00:00
[`systemd-resolved`](https://www.freedesktop.org/wiki/Software/systemd/resolved/) is typically configured with `/etc/systemd/resolved.conf`.
2018-06-04 17:43:47 +00:00
To configure systemd-resolved to send queries for the consul domain to
Consul, configure resolved.conf to contain the following:
```
DNS=127.0.0.1
Domains=~consul
```
The main limitation with this configuration is that the DNS field
cannot contain ports. So for this to work either Consul must be
[configured to listen on port 53](https://www.consul.io/docs/agent/options.html#dns_port)
2020-02-18 13:16:12 +00:00
instead of 8600 or you can use iptables to map port 53 to 8600.
2018-06-04 17:43:47 +00:00
The following iptables commands are sufficient to do the port
mapping.
```
[root@localhost ~]# iptables -t nat -A OUTPUT -d localhost -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600
[root@localhost ~]# iptables -t nat -A OUTPUT -d localhost -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600
```
2020-02-18 13:16:12 +00:00
Binding to port 53 will usually require running either as a privileged user (or on Linux running with the
2018-09-07 14:48:29 +00:00
CAP_NET_BIND_SERVICE capability). If using the Consul docker image you will need to add the following to the
2020-02-18 13:16:12 +00:00
environment to allow Consul to use the port: `CONSUL_ALLOW_PRIVILEGED_PORTS=yes`
2018-09-07 14:48:29 +00:00
2020-02-18 13:16:12 +00:00
Note: With this setup, PTR record queries will still be sent out to the other configured resolvers in
addition to Consul. If you wish to restrict this behavior, your `resolved.conf` should be modified to
```
DNS=127.0.0.1
Domains=~consul ~0.10.in-addr.arpa
```
where the example corresponds to reverse lookups of addresses in the IP range `10.0.0.0/16`. Your
configuration should match your networks.
2018-06-04 17:56:34 +00:00
2019-03-25 14:24:28 +00:00
## iptables Setup
Note, for iptables, the rules must be set on the same host as the Consul
2020-02-18 13:16:12 +00:00
instance and relay hosts should not be on the same host or the redirects will
2019-03-25 14:24:28 +00:00
intercept the traffic.
2016-04-29 06:27:28 +00:00
2016-11-25 16:00:02 +00:00
On Linux systems that support it, incoming requests and requests to
2019-04-01 20:01:00 +00:00
the local host can use [`iptables`](http://www.netfilter.org/) to forward ports on the same machine
2016-11-25 16:00:02 +00:00
without a secondary service. Since Consul, by default, only resolves
2017-01-12 05:08:20 +00:00
the `.consul` TLD, it is especially important to use the `recursors`
2016-11-25 16:00:02 +00:00
option if you wish the `iptables` setup to resolve for other domains.
The recursors should not include the local host as the redirects would
just intercept the requests.
The iptables method is suited for situations where an external DNS
service is already running in your infrastructure and is used as the
recursor or if you want to use an existing DNS server as your query
endpoint and forward requests for the consul domain to the Consul
server. In both of those cases you may want to query the Consul server
but not need the overhead of a separate service on the Consul host.
2016-04-29 06:27:28 +00:00
```
2016-04-29 23:45:59 +00:00
[root@localhost ~]# iptables -t nat -A PREROUTING -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600
[root@localhost ~]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600
[root@localhost ~]# iptables -t nat -A OUTPUT -d localhost -p udp -m udp --dport 53 -j REDIRECT --to-ports 8600
[root@localhost ~]# iptables -t nat -A OUTPUT -d localhost -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 8600
2016-04-29 06:27:28 +00:00
```
2019-03-25 14:24:28 +00:00
## macOS Setup
2017-10-12 21:25:57 +00:00
On macOS systems, you can use the macOS system resolver to point all .consul requests to consul.
2020-02-18 13:16:12 +00:00
Just add a resolver entry in /etc/resolver/ to point at consul.
2020-04-06 20:27:35 +00:00
documentation for this feature is available via: `man5 resolver`.
To setup create a new file `/etc/resolver/consul` (you will need sudo/root access) and put in the file:
2017-10-12 21:25:57 +00:00
```
nameserver 127.0.0.1
port 8600
```
This is telling the macOS resolver daemon for all .consul TLD requests, ask 127.0.0.1 on port 8600.
2019-03-25 14:24:28 +00:00
## Testing
2014-04-09 18:08:32 +00:00
First, perform a DNS query against Consul directly to be sure that the record exists:
2014-10-19 23:40:10 +00:00
```text
2016-11-25 16:00:02 +00:00
[root@localhost ~]# dig @localhost -p 8600 primary.redis.service.dc-1.consul. A
2014-04-09 18:08:32 +00:00
2016-11-25 16:00:02 +00:00
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.32.amzn1 <<>> @localhost primary.redis.service.dc-1.consul. A
2014-10-19 23:40:10 +00:00
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11536
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; QUESTION SECTION:
2016-11-25 16:00:02 +00:00
;primary.redis.service.dc-1.consul. IN A
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; ANSWER SECTION:
2016-11-25 16:00:02 +00:00
primary.redis.service.dc-1.consul. 0 IN A 172.31.3.234
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 9 17:36:12 2014
;; MSG SIZE rcvd: 76
```
2014-04-09 18:08:32 +00:00
2016-02-02 23:06:25 +00:00
Then run the same query against your BIND instance and make sure you get a
valid result:
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
```text
2016-11-25 16:00:02 +00:00
[root@localhost ~]# dig @localhost -p 53 primary.redis.service.dc-1.consul. A
2014-04-09 18:08:32 +00:00
2016-11-25 16:00:02 +00:00
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.32.amzn1 <<>> @localhost primary.redis.service.dc-1.consul. A
2014-10-19 23:40:10 +00:00
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11536
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; QUESTION SECTION:
2016-11-25 16:00:02 +00:00
;primary.redis.service.dc-1.consul. IN A
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; ANSWER SECTION:
2016-11-25 16:00:02 +00:00
primary.redis.service.dc-1.consul. 0 IN A 172.31.3.234
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 9 17:36:12 2014
;; MSG SIZE rcvd: 76
```
2014-04-09 18:08:32 +00:00
2016-02-02 23:06:25 +00:00
If desired, verify reverse DNS using the same methodology:
```text
[root@localhost ~]# dig @127.0.0.1 -p 8600 133.139.16.172.in-addr.arpa. PTR
; <<>> DiG 9.10.3-P3 <<>> @127.0.0.1 -p 8600 133.139.16.172.in-addr.arpa. PTR
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3713
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;133.139.16.172.in-addr.arpa. IN PTR
;; ANSWER SECTION:
133.139.16.172.in-addr.arpa. 0 IN PTR consul1.node.dc1.consul.
;; Query time: 3 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Sun Jan 31 04:25:39 UTC 2016
;; MSG SIZE rcvd: 109
[root@localhost ~]# dig @127.0.0.1 +short -x 172.16.139.133
consul1.node.dc1.consul.
```
2019-03-25 14:24:28 +00:00
## Troubleshooting
2014-04-09 18:08:32 +00:00
2016-02-02 23:06:25 +00:00
If you don't get an answer from your DNS server (e.g. BIND, Dnsmasq) but you
do get an answer from Consul, your best bet is to turn on your DNS server's
query log to see what's happening.
For BIND:
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
```text
[root@localhost ~]# rndc querylog
[root@localhost ~]# tail -f /var/log/messages
```
2014-04-09 18:08:32 +00:00
2015-02-26 18:34:45 +00:00
The log may show errors like this:
2014-04-09 18:08:32 +00:00
2014-10-19 23:40:10 +00:00
```text
error (no valid RRSIG) resolving
error (no valid DS) resolving
```
2014-04-09 03:56:26 +00:00
2015-02-26 18:34:45 +00:00
This indicates that DNSSEC is not disabled properly.
If you see errors about network connections, verify that there are no firewall
or routing problems between the servers running BIND and Consul.
2016-02-02 23:06:25 +00:00
For Dnsmasq, see the `log-queries` configuration option and the `USR1`
signal.
2019-03-25 14:24:28 +00:00
## Summary
2020-02-18 13:16:12 +00:00
In this guide we provided examples of configuring DNS forwarding with many
2019-03-25 14:24:28 +00:00
common, third-party tools. It is the responsibility of the operator to ensure
2020-02-18 13:16:12 +00:00
which ever tool they select is configured properly prior to integration
with Consul.