dev-sidecar/packages/mitmproxy/src/lib/dns/util/dns-over-tls.js

82 lines
2.2 KiB
JavaScript

/**
* 由于组件 `dns-over-tls@0.0.9` 不支持 `rejectUnauthorized` 和 `timeout` 两个参数,所以将源码复制过来,并简化了代码。
*/
const dnsPacket = require('dns-packet')
const tls_1 = require('node:tls')
const randi = require('random-int')
const TWO_BYTES = 2
function getDnsQuery ({ type, name, klass, id }) {
return {
id,
type: 'query',
flags: dnsPacket.RECURSION_DESIRED,
questions: [{ class: klass, name, type }],
}
}
function query ({ host, servername, type, name, klass, port, rejectUnauthorized, timeout }) {
return new Promise((resolve, reject) => {
if (!host || !servername || !name) {
throw new Error('At least host, servername and name must be set.')
}
let response = Buffer.alloc(0)
let packetLength = 0
const dnsQuery = getDnsQuery({ id: randi(0x0, 0xFFFF), type, name, klass })
const dnsQueryBuf = dnsPacket.streamEncode(dnsQuery)
const socket = tls_1.connect({ host, port, servername, rejectUnauthorized, timeout })
// 超时处理
let isFinished = false
let interval
if (timeout > 0) {
interval = setInterval(() => {
if (!isFinished) {
socket.destroy((...args) => {
console.info('socket destory callback args:', args)
})
reject(new Error('DNS查询超时'))
}
}, timeout)
}
socket.on('secureConnect', () => socket.write(dnsQueryBuf))
socket.on('data', (data) => {
if (timeout) {
isFinished = true
clearInterval(interval)
}
if (response.length === 0) {
packetLength = data.readUInt16BE(0)
if (packetLength < 12) {
reject(new Error('Below DNS minimum packet length (DNS Header is 12 bytes)'))
}
response = Buffer.from(data)
} else {
response = Buffer.concat([response, data])
}
if (response.length === packetLength + TWO_BYTES) {
socket.destroy()
resolve(dnsPacket.streamDecode(response))
} else {
reject(new Error('响应长度不正确'))
}
})
socket.on('error', (err) => {
if (timeout) {
isFinished = true
clearInterval(interval)
}
reject(err)
})
})
}
exports.query = query
exports.default = { query }