Search code examples
node.jsdnsnslookup

Is there an equivalent function of nslookup command in node.js?


Is there an equivalent function of nslookup in node.js?

Here's the execution result of nslookup command on my MacBook Pro:

> nslookup www.amagicshop.com.tw 8.8.8.8
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
www.amagicshop.com.tw   canonical name = s16959.dname.91app.io.
s16959.dname.91app.io   canonical name = proxy.letssl.91app.io.
proxy.letssl.91app.io   canonical name = proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com.
Name:   proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com
Address: 54.178.248.57
Name:   proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com
Address: 52.196.80.17

I'm wondering if there is a function in node.js which, given www.amagicshop.com.tw, and 8.8.8.8 as input, also returns
s16959.dname.91app.io., proxy.letssl.91app.io., proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com., 52.196.80.17, and 54.178.248.57 as output.

I originally thought that dns.resolveAny is an equivalent function of nslookup in node.js. But I was wrong.

Because the following code returns Error: queryAny ESERVFAIL www.amagicshop.com.tw error.

const { Resolver } = require('dns')
const resolver = new Resolver()
resolver.setServers(['8.8.8.8'])

resolver.resolveAny('www.amagicshop.com.tw', (err, result) => {
  if (err) {
    console.error(`error: ${err}`)
  } else {
    console.log(`result:  ${JSON.stringify(result)}`)
  }
})

The result is different from the result of nslookup.

Maybe I have to implement a function which combines resolveCname and resolve4 so that I can achieve what I want.


Solution

  • In order to get all the canonical names we have to call recursively (in nslookup the definition is recursive as well!).

    CNAME

    const dns = require('dns')
    
    let accum = []
    const getCnames = (err, result) => {
      if (err) {
        // no more records
        console.log(accum)
        return accum
      } else {
        const cname = result[0]
        accum.push(cname)
        return dns.resolveCname(cname, getCnames)
      }
    }
    
    dns.resolveCname('www.amagicshop.com.tw', getCnames)
    

    OUPUT

    [ 's16959.dname.91app.io',
      'proxy.letssl.91app.io',
      'proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com' ]
    

    IP addresses

    dns.resolve('www.amagicshop.com.tw', callback=(err, result) => {
    
    if (err) {
        console.error(`error: ${err}`)
      } else {
        console.log(result)
      }
    })
    

    OUTPUT

    [ '52.196.80.17', '54.178.248.57' ]
    

    Combined

    const dns = require('dns')
    
    const resolve = (cname) => {
      const getIp = (accum) =>
        dns.resolve(cname,
          callback=(err, result) => {
            if (err) {
                console.error(`error: ${err}`)
              } else {
                result.push.apply(result, accum)
                console.log(result)
              }
          })
    
      let accum = []
      const getCnames = (err, result) => {
        if (err) {
          // no more records
          getIp(accum)
        } else {
          const cname = result[0]
          accum.push(cname)
          dns.resolveCname(cname, getCnames)
        }
      }
    
      dns.resolveCname(cname, getCnames)
    }
    
    resolve('www.amagicshop.com.tw')
    

    OUTPUT

    [ '52.196.80.17',
      '54.178.248.57',
      's16959.dname.91app.io',
      'proxy.letssl.91app.io',
      'proxy-letssl-91app-io-196811564.ap-northeast-1.elb.amazonaws.com' ]