---
layout: docs
page_title: Perform static DNS queries
description: >-
  Learn how to use standard Consul DNS lookup formats to enable service discovery for services and nodes.
---

# Perform static DNS queries

This topic describes how to query the Consul DNS to look up nodes and services registered with Consul. Refer to [Perform dynamic DNS queries](/consul/docs/discover/service/dynamic) for information about using prepared queries.

## Introduction

Node lookups and service lookups are the fundamental types of queries you can perform using the Consul DNS. Node lookups query the catalog for named Consul agents. Service lookups query the catalog for services registered with Consul. Refer to [DNS Usage Overview](/consul/docs/discover/dns) for additional background information.

## Requirements

All versions of Consul support DNS lookup features.

### ACLs

If ACLs are enabled, you must present a token linked with the necessary policies. We recommend using a separate token in production deployments for querying the DNS. By default, Consul agents resolve DNS requests using the preconfigured tokens in order of precedence:

1. The agent's [`default` token](/consul/docs/reference/agent/configuration-file/acl#acl_tokens_default)
1. The built-in [`anonymous` token](/consul/docs/secure/acl/token#built-in-tokens).

The following table describes the available DNS lookups and required policies when ACLs are enabled:

| Lookup | Type | Description | ACLs Required |
| ---    | ---  | ---         | ---           |
| `*.node.consul` | Node | Allows Consul to resolve DNS requests for the target node. Example: `<target>.node.consul` | `node:read` |
| `*.service.consul`<br/> `*.connect.consul` <br/> `*.ingress.consul` <br/>`*.virtual.consul` |Service: standard | Allows Consul to resolve DNS requests for target service instances running on ACL-authorized nodes. Example: `<target>.service.consul` | `service:read`<br/> `node:read` |

## Node lookups

Specify the name of the node, datacenter, and domain using the following FQDN syntax:

```text
<node>.node[.<datacenter>.dc].<domain>
```

The `datacenter` subdomain is optional. By default, the lookup queries the datacenter of the agent.

By default, the domain is `consul`. Refer to [Configure Consul DNS behavior](/consul/docs/discover/dns/configure) for information about using alternate domains.

### Node lookup results

Node lookups return A and AAAA records that contain the IP address and TXT records containing the `node_meta` values of the node.

By default, TXT record values match the node's metadata key-value pairs according to [RFC1464](https://www.ietf.org/rfc/rfc1464.txt). If the metadata key starts with `rfc1035-`, the TXT record only includes the node's metadata value.

The following example lookup queries the `foo` node in the `default` datacenter:

```shell-session
$ dig @127.0.0.1 -p 8600 foo.node.consul ANY
; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 foo.node.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24355
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;foo.node.consul.   IN  ANY

;; ANSWER SECTION:
foo.node.consul.  0 IN  A 10.1.10.12
foo.node.consul.  0 IN  TXT "meta_key=meta_value"
foo.node.consul.  0 IN  TXT "value only"

;; AUTHORITY SECTION:
consul.     0 IN  SOA ns.consul. postmaster.consul. 1392836399 3600 600 86400 0
```

### Node lookups for Consul Enterprise

Consul Enterprise includes the admin partition concept, which is an abstraction that lets you define isolated administrative network areas. Refer to [Admin partitions](/consul/docs/multi-tenant/admin-partition) for additional information.

Consul nodes reside in admin partitions within a datacenter. By default, node lookups query the same partition and datacenter of the Consul agent that received the DNS query.

Use the following query format to specify a partition for a node lookup:

```text
<node>.node[.<partition>.ap][.<datacenter>.dc].<domain>
```

Consul server agents are in the `default` partition. If you send a DNS query to Consul server agents, you must explicitly specify the partition of the target node if it is not `default`.

## Service lookups

You can query the network for service providers using either the [standard lookup](#standard-lookup) method or [strict RFC 2782 lookup](#rfc-2782-lookup) method.

By default, all SRV records are weighted equally in service lookup responses, but you can configure the weights using the [`Weights`](/consul/docs/reference/service#weights) attribute of the service definition. Refer to [Define Services](/consul/docs/register/service/vm/define) for additional information.

The DNS protocol limits the size of requests, even when performing DNS TCP queries, which may affect your experience querying for services. For services with more than 500 instances, you may not be able to retrieve the complete list of instances for the service. Refer to [RFC 1035, Domain Names - Implementation and Specification](https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.4) for additional information.

Consul randomizes DNS SRV records and ignores weights specified in service configurations when printing responses. If records are truncated, each client using weighted SRV responses may have partial and inconsistent views of instance weights. As a result, the request distribution may be skewed from the intended weights. We recommend calling the [`/catalog/nodes` API endpoint](/consul/api-docs/catalog#list-nodes) to retrieve the complete list of nodes. You can apply query parameters to API calls to sort and filter the results.

### Standard lookups

To perform standard service lookups, specify tags, the name of the service, datacenter, cluster peer, and domain using the following syntax to query for service providers:

```text
[<tag>.]<service>.service[.<datacenter>.dc][.<cluster-peer>.peer][.<sameness-group>.sg].<domain>
```

- The `tag` subdomain is optional. It filters responses so that only service providers containing the tag appear.

- The `datacenter` subdomain is optional. By default, Consul interrogates the querying agent's datacenter.

- The `cluster-peer` name is optional, and specifies the [cluster peer](/consul/docs/east-west/cluster-peering) whose [exported services](/consul/docs/reference/config-entry/exported-services) should be the target of the query.

- The `sameness-group` name is optional, and specifies the [sameness group](/consul/docs/multi-tenant/sameness-group/vm) that should be the target of the query. When Consul receives a DNS request for a service that is tied to a sameness group, it returns service instances from the first healthy member of the sameness group. If the local partition is a member of a sameness group, its service instances take precedence over the members of its sameness group. Optionally, you can include a namespace or admin partition when performing a lookup on a sameness group. Refer to [Service lookups for Consul Enterprise](#service-lookups-for-consul-enterprise) for more information.

By default, the lookups query in the `consul` domain. Refer to [Configure Consul DNS behavior](/consul/docs/discover/dns/configure) for information about using alternate domains.

#### Standard lookup results

Standard services queries return A and SRV records. SRV records include the port that the service is registered on. SRV records are only served if the client specifically requests them.

Services that fail their health check or that fail a node system check are omitted from the results. As a load balancing measure, Consul randomizes the set of nodes returned in the response. These mechanisms help you use DNS with application-level retries as the foundation for a self-healing service-oriented architecture.

The following example retrieves the SRV records for any `redis` service registered in Consul.

```shell-session
$ dig @127.0.0.1 -p 8600 consul.service.consul SRV

; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 consul.service.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50483
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;consul.service.consul.   IN  SRV

;; ANSWER SECTION:
consul.service.consul.  0 IN  SRV 1 1 8300 foobar.node.dc1.consul.

;; ADDITIONAL SECTION:
foobar.node.dc1.consul. 0 IN  A 10.1.10.12
```

The following example command and FQDN retrieves the SRV records for the primary Postgres service in the secondary datacenter:

```shell-session hideClipboard
$ dig @127.0.0.1 -p 8600 primary.postgresql.service.dc2.consul SRV

; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 primary.postgresql.service.dc2.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50483
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;consul.service.consul.   IN  SRV

;; ANSWER SECTION:
consul.service.consul.  0 IN  SRV 1 1 5432 primary.postgresql.service.dc2.consul.

;; ADDITIONAL SECTION:
primary.postgresql.service.dc2.consul. 0 IN  A 10.1.10.12
```

### RFC 2782 lookup

Per [RFC 2782](https://tools.ietf.org/html/rfc2782), SRV queries must prepend `service` and `protocol` values with an underscore (`_`) to prevent DNS collisions. Use the following syntax to perform RFC 2782 lookups:

```text
_<service>._<protocol>[.service][.<datacenter>].<domain>
```

You can create lookups that filter results by placing service tags in the `protocol` field. Use the following syntax to create RFC 2782 lookups that filter results based on service tags:

```text
_<service>._<tag>[.service][.<datacenter>].<domain>
```

The following example queries the `rabbitmq` service tagged with `amqp`, which returns an instance at `rabbitmq.node1.dc1.consul` on port `5672`:

```shell-session
$ dig @127.0.0.1 -p 8600 _rabbitmq._amqp.service.consul SRV
; <<>> DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 _rabbitmq._amqp.service.consul ANY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52838
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;_rabbitmq._amqp.service.consul.  IN  SRV

;; ANSWER SECTION:
_rabbitmq._amqp.service.consul. 0 IN  SRV 1 1 5672 rabbitmq.node1.dc1.consul.

;; ADDITIONAL SECTION:
rabbitmq.node1.dc1.consul.  0 IN  A 10.1.11.20
```

You can also perform RFC 2782 lookups that target a specific [cluster peer](/consul/docs/east-west/cluster-peering) or datacenter by including  `<datacenter>.dc` or `<cluster-peer>.peer` in the query labels:

```text
_<service>._<tag>[.service][.<datacenter>.dc][.<cluster-peer>.peer].<domain>
```

The following example queries the `redis` service tagged with `tcp` for the cluster peer `phx1`, which returns two instances, one at `10.1.11.83:29081` and one at `10.1.11.86:29142`:

```shell-session
$ dig @127.0.0.1 -p 8600 _redis._tcp.service.phx1.peer.consul SRV
; <<>> DiG 9.18.15 <<>> @127.0.0.1 -p 8600 _redis._tcp.service.phx1.peer.consul SRV
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40572
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_redis._tcp.service.phx1.peer.consul.  IN SRV

;; ANSWER SECTION:
_redis._tcp.service.phx1.peer.consul. 0 IN SRV 1 1 29081 0a000d53.addr.consul.
_redis._tcp.service.phx1.peer.consul. 0 IN SRV 1 1 29142 0a010d56.addr.consul.

;; ADDITIONAL SECTION:
0a000d53.addr.consul. 0 IN  A 10.1.11.83
0a010d56.addr.consul. 0 IN  A 10.1.11.86
```

#### SRV responses for hosts in the .addr subdomain

If a service registered with Consul is configured with an explicit IP address or addresses in the  [`address`](/consul/docs/reference/service#address) or [`tagged_address`](/consul/docs/reference/service#tagged_address) parameter, then Consul returns the hostname in the target field of the answer section for the DNS SRV query according to the following format:

```text
<hexadecimal-encoded IP>.addr.<datacenter>.consul.
```

In the following example, the `rabbitmq` service is registered with an explicit IPv4 address of `192.0.2.10`.

<CodeTabs>

```hcl
node_name = "node1"

services {
  name = "rabbitmq"
  address = "192.0.2.10"
  port = 5672
}
```

```json
{
  "node_name": "node1",
  "services": [
    {
      "name": "rabbitmq",
      "address": "192.0.2.10",
      "port": 5672
    }
  ]
}
```

</CodeTabs>

The following example SRV query response contains a single record with a hostname written as a hexadecimal value:

```shell-session
$ dig @127.0.0.1 -p 8600 -t srv _rabbitmq._tcp.service.consul +short
1 1 5672 c000020a.addr.dc1.consul.
```

You can convert hex octets to decimals to reveal the IP address. The following example command converts the hostname expressed as `c000020a` into the IPv4 address specified in the service registration.

```shell-session
$ echo -n "c000020a" | perl -ne 'printf("%vd\n", pack("H*", $_))'
192.0.2.10
```

In the following example, the `rabbitmq` service is registered with an explicit IPv6 address of `2001:db8:1:2:cafe::1337`.

<CodeTabs>

```hcl
node_name = "node1"

services {
  name = "rabbitmq"
  address = "2001:db8:1:2:cafe::1337"
  port = 5672
}
```

```json
{
  "node_name": "node1",
  "services": [
    {
      "name": "rabbitmq",
      "address": "2001:db8:1:2:cafe::1337",
      "port": 5672
    }
  ]
}
```

</CodeTabs>

The following example SRV query response contains a single record with a hostname written as a hexadecimal value.

```shell-session
$ dig @127.0.0.1 -p 8600 -t SRV _rabbitmq._tcp.service.consul +short
1 1 5672 20010db800010002cafe000000001337.addr.dc1.consul.
```

The response contains the fully-expanded IPv6 address with colon separators removed. The following command re-adds the colon separators to display the fully expanded IPv6 address that was specified in the service registration.

```shell-session
$ echo -n "20010db800010002cafe000000001337" | perl -ne 'printf join(":", unpack("(A4)*", $_))."\n"'
2001:0db8:0001:0002:cafe:0000:0000:1337
```

### Service lookups for Consul Enterprise

You can perform the following types of service lookups to query for services in another namespace, partition, and datacenter:

- `.service`
- `.connect`
- `.virtual`
- `.ingress`

Use the following query format to specify namespace, partition, or datacenter:
```
[<tag>.]<service>.service[.<namespace>.ns][.<partition>.ap][.<datacenter>.dc]<domain>
```

The `namespace`, `partition`, and `datacenter` are optional. By default, all service lookups use the `default` namespace within the partition and datacenter of the Consul agent that received the DNS query.

Consul server agents reside in the `default` partition. If DNS queries are addressed to Consul server agents, you must explicitly specify the partition of the target service when querying for services in  partitions other than `default`.

To lookup services imported from a cluster peer, refer to [Service virtual IP lookups for Consul Enterprise](#service-virtual-ip-lookups-for-consul-enterprise).

#### Alternative formats for specifying namespace

Although we recommend using the format described in [Service lookups for Consul Enterprise](#service-lookups-for-consul-enterprise) for readability, you can use the alternate query format to specify namespaces but not partitions:

```
[<tag>.]<service>.service.<namespace>.<datacenter>.<domain>
```

### Service mesh-enabled service lookups

Add the `.connect` subdomain to query for service mesh-enabled services:

```text
<service>.connect.<domain>
```

This finds all service mesh-capable endpoints for the service. A service mesh-capable endpoint may be a proxy for a service or a natively integrated service mesh application. The DNS interface does not differentiate the two.

Many services use a proxy that handles service discovery automatically. As a result, they may not use the DNS format, which is primarily for service mesh-native applications.
This endpoint only finds services within the same datacenter and does not support tags. Refer to the [`catalog` API endpoint](/consul/api-docs/catalog) for more complex behaviors.

### Service virtual IP lookups

Add the `.virtual` subdomain to queries to find the unique virtual IP allocated for a service:

```text
<service>.virtual[.<peer>].<domain>
```

This returns the unique virtual IP for any service mesh-capable service. Each service mesh service has a virtual IP assigned to it by Consul. Sidecar proxies use the virtual IP to enable the [transparent proxy](/consul/docs/connect/transparent-proxy) feature.

The peer name is an optional. The DNS uses it to query for the virtual IP of a service imported from the specified peer.

Consul adds virtual IPs to the [`tagged_addresses`](/consul/docs/reference/service#tagged_addresses) field in the service definition under the `consul-virtual` tag.

#### Service virtual IP lookups for Consul Enterprise

By default, a service virtual IP lookup checks the `default` namespace within the partition and datacenter of the Consul agent that received the DNS query.
To lookup services imported from a partition in another cluster peered to the querying cluster or open-source datacenter, specify the namespace and peer name in the lookup:

```text
<service>.virtual[.<namespace>].<peer>.<domain>
```

To lookup services in a cluster peer that have not been imported, refer to [Service lookups for Consul Enterprise](#service-lookups-for-consul-enterprise).

### Ingress service lookups

Add the `.ingress` subdomain to your DNS FQDN to find ingress-enabled services:

```text
<service>.ingress.<domain>
```

This finds all ingress gateway endpoints for the service.

This endpoint finds services within the same datacenter and does not support tags. Refer to the [`catalog` API endpoint](/consul/api-docs/catalog) for more complex behaviors.

### UDP-based DNS queries

When the DNS query is performed using UDP, Consul truncates the results without setting the truncate bit. This prevents a redundant lookup over TCP that generates additional load. If the lookup is done over TCP, the results are not truncated.
