Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dns-query

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dns-query

Node & Browser tested, Non-JSON DNS over HTTPS fetching with minimal dependencies.

  • 0.10.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
13K
decreased by-12.7%
Maintainers
1
Weekly downloads
 
Created
Source

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.

Contents

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: resolveTxt does not support ttl results. For that reason, when using dns-query in node you can also specify dns endpoints that should be helpful in the node environment.

JavaScript API

import { query, endpoints as defaultEndpoints } from 'dns-query'
const { cloudflare, google, opendns } = defaultEndpoints

let endpoints // If undefined endpoints will be assumed to use one of the dns or doh endpoints!
endpoints = 'doh' // Use any of the given defaultEndpoints to resolve
endpoints = 'dns' // Use the system default dns servers to resolve (Node.js only!)
endpoints = [cloudflare, google, opendns] // Use predefined, well-known endpoints
endpoints = ['cloudflare', 'google', 'opendns'] // Use predefined, well-known endpoints by their name
endpoints = ['https://cloudflare-dns.com/dns-query'] // Use a custom endpoint
endpoints = [{ host: 'cloudflare-dns.com' }] // Specify using properties
endpoints = (endpoint) => endpoint.protocol === 'https:' // Use a filter against the well-known endpoints
endpoints = Promise.resolve('doh') // The endpoints can also be a promise
try {
  const { answers } = await query({
    question: {type: 'A', name: 'google.com'}
  }, {
    /* Options (optional) */
    endpoints: endpoints,
    retry: 3, // (optional) retries if a given endpoint fails; -1 = infinite retries; 0 = no retry
    timeout: 4000, // (optional, default=30000) timeout for single requests
    signal, // (optional) an AbortSignal to abort the request
  })
} catch (error) {
  switch (error.code) {
    case 'HTTP_STATUS': // request failed, http status error
    case 'RESPONSE_ERR': // request failed, invalid response
    case 'ABORT_ERR': // request aborted
    default: // Unexpected error
  }
}

Error Responses

By default query will return the packet as received by the endpoints, even if that package was flagged as an error. The validateResponse helper will give a well readable error message.

import { validateResponse, query } from 'dns-query'

const respone = validateResponse(await query(/* ... */))

Session API

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.

You can use the Session to define the behavior for requests.

import { Session } from 'dns-query'

const session = new Session({
  update: true, // Will load latest definitions from updateURL.
  updateURL: new URL(), // URL to load the latest definitions. (default: project URL)
  persist: true, // True to persist the loaded definitions (nodejs: in filesystem, browser: localStorage)
  localStoragePrefix: 'dnsquery_', // Prefix for files persisted.
  maxAge: 300000, // Max age of persisted data to be used in ms (default: 5min)
  // Defaults for requests
  retries: 3,
  timeout: 3000,
  endpoints: 'doh'
})

await session.wellknown()
await session.endpoints()
await session.query({ /* ... */})
await session.lookupTxt('google.com')

By default, query will try load the latest definitions (update: true) but will persist them only in memory. Subsequent requests will only update the list if it is old.

persist: true is useful when you restart a node process or refresh a browser. The persisted data will then be available making subsequent requests faster still.

Persist: Node.js

In node.js this will try to persist the list of resolvers to the node_modules directory.

Persist: Browser

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').

query(..., {
  localStoragePrefix: 'my_custom_prefix'
})

Txt Helper

The default TXT response of dns-queries is a list of Uint8Array's. If you have a TXT response you can use the combineTXT API to combine the requests.

import { combineTXT } from 'dns-query'

const response = await query(/* ... */)
if (response.question.type === 'TXT') {
  const txt = response.answers.map(answer => combineTXT(answer.data))
}

More convenient still is the lookupTxt API that allows you to simple request the TXT entries for a domain.

import { lookupTxt } from 'dns-query'

const { entries, endpoint } = await lookupTxt('google.com')

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:

  # Fetch from the google dns-over-https endpoint the A-name of google.com
  $ dns-query --json -e google \
      '{ "question": { "type": "A", "name": "google.com" } }'

  # Fetch TXT entries for ipfs.io through regular dns
  $ dns-query --json --dns \
      '{ "question": { "type": "TXT", "name": "ipfs.io" } }'

  # Pass the query through stdin
  $ echo '{ "question": { "type": "A", "name": "google.com" } }' \
      | dns-query --stdin --endpoint cloudflare
  
  # Process binary packages as base64
  $ dns-query --base64 AAAAAAABAAAAAAAABGlwZnMCaW8AABAAAQ==

  # Load the txt data for a domain
  $ dns-query --mode=txt ipfs.io

OPTIONS:

  --mode ........... Mode consume/process data.
    ---mode=free ... Free query input (default)
    ---mode=txt .... TXT data loading shortcut
  --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 = {
  /* https is the default for DoH endpoints and http for debug only! If you don't specify a protocol, https is assumed */
  protocol: 'https:' | 'http:'
  /* https port, defaults to 443 for https, 80 for http */
  port?: number | string | null
  /* Host to look up */
  host: string
  /* Known IPV4 address that can be used for the lookup */
  ipv4?: string
  /* Known IPV6 address that can be used for the lookup */
  ipv6?: string
  /* true, if endpoint supports http/https CORS headers, defaults to false */
  cors?: boolean
  /* Path, prefixed with /, defaults to /dns-query for the http/https protocol */
  path?: string
  /* Method to request in case of http/https, defaults to GET */
  method?: 'POST' | 'GET'
} | {
  protocol: 'udp4:'
  /* ipv4 endpoint to connect-to */
  ipv4: string
  /* https port, defaults to 53; 443 if pk is present */
  port?: number | string | null
  /* dnscrypt public key */
  pk?: string | null
} | {
  protocol: 'udp6:'
  /* ipv4 endpoint to connect-to */
  ipv6: string
  /* https port, defaults to 53; 443 if pk is present */
  port?: number | string | null
  /* dnscrypt public key */
  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' }

See Also

License

MIT

Keywords

FAQs

Package last updated on 01 Jun 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc