bugfix: DoT的DNS,配置了SNI但未生效的问题修复
parent
c18a6241d0
commit
217ce9d972
|
@ -18,7 +18,6 @@
|
|||
"axios": "^1.7.7",
|
||||
"baidu-aip-sdk": "^4.16.16",
|
||||
"dns-over-http": "^0.2.0",
|
||||
"dns-over-tls": "^0.0.9",
|
||||
"is-browser": "^2.1.0",
|
||||
"json5": "^2.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
|
|
|
@ -168,7 +168,7 @@ module.exports = class BaseDNS {
|
|||
return new Promise((resolve, reject) => {
|
||||
// 设置超时任务
|
||||
let isOver = false
|
||||
const timeout = 6000
|
||||
const timeout = 8000
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (!isOver) {
|
||||
log.error(`[DNS-over-${this.dnsType} '${this.dnsName}'] DNS查询超时, hostname: ${hostname}, sni: ${this.dnsServerName || '无'}, type: ${type}${this.dnsServer ? `, dnsServer: ${this.dnsServer}` : ''}${this.dnsServerPort ? `:${this.dnsServerPort}` : ''}, cost: ${Date.now() - start} ms`)
|
||||
|
|
|
@ -9,7 +9,7 @@ const dohQueryAsync = promisify(doh.query)
|
|||
function createAgent (dnsServer) {
|
||||
return new (dnsServer.startsWith('https:') ? HttpsAgent : Agent)({
|
||||
keepAlive: true,
|
||||
timeout: 20000,
|
||||
timeout: 4000,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const dnstls = require('dns-over-tls')
|
||||
const dnstls = require('./util/dns-over-tls')
|
||||
const BaseDNS = require('./base')
|
||||
|
||||
const defaultPort = 853
|
||||
|
@ -16,10 +16,13 @@ module.exports = class DNSOverTLS extends BaseDNS {
|
|||
host: this.dnsServer,
|
||||
port: this.dnsServerPort,
|
||||
servername: this.dnsServerName || this.dnsServer,
|
||||
rejectUnauthorized: !this.dnsServerName,
|
||||
|
||||
name: hostname,
|
||||
klass: 'IN',
|
||||
type,
|
||||
|
||||
timeout: 4000,
|
||||
}
|
||||
|
||||
return dnstls.query(options)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* 由于组件 `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 }
|
|
@ -38,7 +38,7 @@ const hostnames = [
|
|||
const sni = 'baidu.com'
|
||||
// const sni = ''
|
||||
|
||||
console.log(`\n--------------- 测试DoH的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名 ---------------\n`)
|
||||
console.log(`\n--------------- 测试DoH的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名,SNI: ${sni || '无'} ---------------\n`)
|
||||
|
||||
let n = 0
|
||||
let success = 0
|
||||
|
|
|
@ -2,18 +2,50 @@ import DNSOverTLS from "../src/lib/dns/tls.js";
|
|||
|
||||
// 境外DNS的DoT配置sni测试
|
||||
const servers = [
|
||||
'1dot1dot1dot1.cloudflare-dns.com',
|
||||
'cloudflare-dns.com',
|
||||
// 'dot.360.cn',
|
||||
|
||||
'1.1.1.1', // 可直连,无需SNI(有时候可以,有时候不行)
|
||||
'one.one.one.one',
|
||||
// '1.1.1.1', // 可直连,无需SNI
|
||||
'cloudflare-dns.com',
|
||||
'security.cloudflare-dns.com',
|
||||
'family.cloudflare-dns.com',
|
||||
'1dot1dot1dot1.cloudflare-dns.com',
|
||||
|
||||
'dot.sb',
|
||||
'185.222.222.222',
|
||||
'45.11.45.11',
|
||||
|
||||
'dns.adguard.com',
|
||||
'dns.adguard-dns.com',
|
||||
'dns-family.adguard.com',
|
||||
'family.adguard-dns.com',
|
||||
'dns-unfiltered.adguard.com',
|
||||
'unfiltered.adguard-dns.com',
|
||||
'dns.bebasid.com',
|
||||
'unfiltered.dns.bebasid.com',
|
||||
'antivirus.bebasid.com',
|
||||
'internetsehat.bebasid.com',
|
||||
'family-adblock.bebasid.com',
|
||||
'oisd.dns.bebasid.com',
|
||||
'hagezi.dns.bebasid.com',
|
||||
'dns.cfiec.net',
|
||||
'dns.opendns.com',
|
||||
'familyshield.opendns.com',
|
||||
'sandbox.opendns.com',
|
||||
'family-filter-dns.cleanbrowsing.org',
|
||||
'adult-filter-dns.cleanbrowsing.org',
|
||||
'security-filter-dns.cleanbrowsing.org',
|
||||
'p0.freedns.controld.com',
|
||||
'p1.freedns.controld.com',
|
||||
'p2.freedns.controld.com',
|
||||
'p3.freedns.controld.com',
|
||||
'dns.decloudus.com',
|
||||
'getdnsapi.net',
|
||||
'dnsovertls.sinodun.com',
|
||||
'dnsovertls1.sinodun.com',
|
||||
'dns.de.futuredns.eu.org',
|
||||
'dns.us.futuredns.eu.org',
|
||||
'unicast.censurfridns.dk',
|
||||
]
|
||||
|
||||
const hostnames = [
|
||||
|
@ -23,7 +55,7 @@ const hostnames = [
|
|||
const sni = 'baidu.com'
|
||||
// const sni = ''
|
||||
|
||||
console.log(`\n--------------- 测试DoT的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名 ---------------\n`)
|
||||
console.log(`\n--------------- 测试DoT的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名,SNI: ${sni || '无'} ---------------\n`)
|
||||
|
||||
let n = 0
|
||||
let success = 0
|
||||
|
|
|
@ -169,9 +169,6 @@ importers:
|
|||
dns-over-http:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
dns-over-tls:
|
||||
specifier: ^0.0.9
|
||||
version: 0.0.9
|
||||
is-browser:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
|
@ -3045,9 +3042,6 @@ packages:
|
|||
dns-over-http@0.2.0:
|
||||
resolution: {integrity: sha512-K+SyN2L3ljxJ2MFtOv/vRS+3/YEMLvOuH7MrmO5ejaubi4w02/DLqzoK1kBGKlQrT9ND57pbapeDf+ue8AElEA==}
|
||||
|
||||
dns-over-tls@0.0.9:
|
||||
resolution: {integrity: sha512-IdI/Qgku2KQPLtUBsC6HDdK6bWIZADQMOYWtqJzRivV5Z+EDKIVAaC+tWE6lJ9vn11qj5L39ZaIaTj/14Lzgkw==}
|
||||
|
||||
dns-packet@4.2.0:
|
||||
resolution: {integrity: sha512-bn1AKpfkFbm0MIioOMHZ5qJzl2uypdBwI4nYNsqvhjsegBhcKJUlCrMPWLx6JEezRjxZmxhtIz/FkBEur2l8Cw==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -10553,10 +10547,6 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
dns-over-tls@0.0.9:
|
||||
dependencies:
|
||||
dns-packet: 5.6.1
|
||||
|
||||
dns-packet@4.2.0:
|
||||
dependencies:
|
||||
ip: 1.1.9
|
||||
|
|
Loading…
Reference in New Issue