dns-query
Node & Browser tested, Non-JSON DNS over HTTPS (and DNS) fetching with minimal dependencies.
DNS over HTTPS (DoH) is protocol designed for performing remote Domain Name System
resolution over HTTPS. Requests are made of HTTP to increase user security and privacy.
See DNS over HTTPS for more
information.
This package provides simple function to make DoH queries both in node and the browser.
Important Note before getting started
By default dns-query
uses well-known public dns-over-https servers to execute
queries automatically compiled by the data from the DNSCrypt project.
The npm package comes with the list that was/is current on the time of the publication.
It will will try to automatically download the list from the dns-query website unless
you set the .update
property on a Session
object.
These servers come with caveats that you should be aware of:
- A server may filter, log or limit the requests it receives!
- Filtering can be useful in case you want to avoid malware/ads/adult-content.
- Logging may be required in some countries and limiting may be part of a business model.
- Furthermore the different endpoints may or may not be distributed around the globe,
making requests slower/faster depending on the client's location.
- Not all endpoints supply CORS headers which means that the list is severly reduced if you use this
library in the browser.
If you are presenting this library to an end-user, you may want to allow them to decide what endpoint
they want to use as it has privacy and usage implications!
DNS support
Node.js's dns support is limited, primary example being: lookupTXT
does not support ttl
results. For that reason, when using dns-query
in node you can also specify dns
endpoints.
JavaScript API
const { query, endpoints: defaultEndpoints } = require('dns-query')
const { cloudflare, google, opendns } = defaultEndpoints
let endpoints
endpoints = 'doh'
endpoints = 'dns'
endpoints = [cloudflare, google, opendns]
endpoints = ['cloudflare', 'google', 'opendns']
endpoints = ['https://cloudflare-dns.com/dns-query']
endpoints = [{ host: 'cloudflare-dns.com' }]
endpoints = (endpoint) => endpoint.protocol === 'https:'
endpoints = Promise.resolve('doh')
try {
const { answers } = await query({
question: {type: 'A', name: 'google.com'}
}, {
endpoints: endpoints,
retry: 3,
timeout: 4000,
signal,
})
} catch (error) {
switch (error.code) {
case 'HTTP_STATUS':
case 'RESPONSE_ERR':
case 'ABORT_ERR':
default:
}
}
CLI
You can install dns-query
as a command-line tool using npm i dns-query -g
or by running npx dns-query
.
$ dns-query <options> <input>
dns-query - Execute a dns query over https.
USAGE:
dns-query <Options> <Input>
EXAMPLES:
$ dns-query --json -e google \
'{ "question": { "type": "A", "name": "google.com" } }'
$ dns-query --json --dns \
'{ "question": { "type": "TXT", "name": "ipfs.io" } }'
$ echo '{ "question": { "type": "A", "name": "google.com" } }' \
| dns-query --stdin --endpoint cloudflare
OPTIONS:
--help, -h ....... Show this help
--version, -v .... Show the version
--json ........... --type=json
--base64 ......... --type=base64
--binary ......... --type=binary
--type ........... Input type. Options: json, base64, binary; Default: json
--out ............ Output type. Defaults to the input --type.
--stdin .......... Get <input> from stdin instead of cli arguments
--dns ............ Use dns endpoints
--doh ............ Use doh endpoints
--endpoint, -e ... Use a specific endpoint. Can be either the name of a known
endpoint, a json object or an url. By default uses one of the known endpoints.
If multiple are provided, one at random will be used.
--endpoints ...... Lists all known endpoints as json.
--resolvers ...... List all known resolvers as json.
--response ....... Show the http response in the result.
--retries ........ Number of retries to do in case requests fails, default: 5
--timeout ........ Timeout for the request in milliseconds, default: 30000 (5 sec)
--max-age ........ Max age of the persisted data, default: 300000 (5 min)
--no-persist ..... Dont persist the the latest resolvers
--offline ........ Do not update the resolver list
Endpoints
For an endpoint to work, it needs to satisfy this interface:
type EndpointProps = {
protocol: 'https:' | 'http:'
port?: number | string | null
host: string
ipv4?: string
ipv6?: string
cors?: boolean
path?: string
method?: 'POST' | 'GET'
} | {
protocol: 'udp4:'
ipv4: string
port?: number | string | null
pk?: string | null
} | {
protocol: 'udp6:'
ipv6: string
port?: number | string | null
pk?: string | null
}
String endpoints
Instead of passing an object you can also pass a string. If the string matches the name
of one of the endpoints, that endpoint will be used. If it doesnt match any endpoint,
then it will be parsed using the parseEndpoint
method understands an URL like structure
with additional properties defined like flags ([<name>]
).
Examples:
foo.com
→ { host: 'foo.com' }
http://bar.com:81/query [post]
→
{ host: 'bar.com', path: '/query', port: 81, method: 'post', protocol: 'http:' }
Note: If no path is given, such as foo.com
, the path will be assumed as /dns-query
, but
if a path is given such as foo.com/
it will assume that path /
!
To specify DNS endpoints you need to prefix them using udp:
(or udp4:
, udp6
)
udp://1.1.1.1
→ { host: '1.1.1.1', protocol: 'udp4' }
Persisting Resolvers
Loading the latest list of resolvers from the servers will increase both the load
on the server hosting the list and your application's responsiveness. dns-query
comes
with support for persisting the resolvers in order to ease the load.
While the CLI does that by default, you need to enable it when using the JavaScript
API.
query(..., {
persist: true
})
In node.js this will try to persist the list of resolvers to the node_modules
directory.
In the browser it will use localStorage
to store the copy of resolvers. By default
it will use the localStoragePrefix = 'dnsquery_'
option. You will be able to find
the persisted resolvers under localStorage.getItem('dnsquery_resolvers.json')
.
You can change the prefix in the options.
query(..., {
localStoragePrefix: 'my_custom_prefix'
})
See Also
License
MIT