bugfix: DoT的DNS,配置了SNI但未生效的问题修复
parent
c18a6241d0
commit
217ce9d972
|
@ -18,7 +18,6 @@
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"baidu-aip-sdk": "^4.16.16",
|
"baidu-aip-sdk": "^4.16.16",
|
||||||
"dns-over-http": "^0.2.0",
|
"dns-over-http": "^0.2.0",
|
||||||
"dns-over-tls": "^0.0.9",
|
|
||||||
"is-browser": "^2.1.0",
|
"is-browser": "^2.1.0",
|
||||||
"json5": "^2.2.3",
|
"json5": "^2.2.3",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|
|
@ -168,7 +168,7 @@ module.exports = class BaseDNS {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 设置超时任务
|
// 设置超时任务
|
||||||
let isOver = false
|
let isOver = false
|
||||||
const timeout = 6000
|
const timeout = 8000
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
if (!isOver) {
|
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`)
|
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) {
|
function createAgent (dnsServer) {
|
||||||
return new (dnsServer.startsWith('https:') ? HttpsAgent : Agent)({
|
return new (dnsServer.startsWith('https:') ? HttpsAgent : Agent)({
|
||||||
keepAlive: true,
|
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 BaseDNS = require('./base')
|
||||||
|
|
||||||
const defaultPort = 853
|
const defaultPort = 853
|
||||||
|
@ -16,10 +16,13 @@ module.exports = class DNSOverTLS extends BaseDNS {
|
||||||
host: this.dnsServer,
|
host: this.dnsServer,
|
||||||
port: this.dnsServerPort,
|
port: this.dnsServerPort,
|
||||||
servername: this.dnsServerName || this.dnsServer,
|
servername: this.dnsServerName || this.dnsServer,
|
||||||
|
rejectUnauthorized: !this.dnsServerName,
|
||||||
|
|
||||||
name: hostname,
|
name: hostname,
|
||||||
klass: 'IN',
|
klass: 'IN',
|
||||||
type,
|
type,
|
||||||
|
|
||||||
|
timeout: 4000,
|
||||||
}
|
}
|
||||||
|
|
||||||
return dnstls.query(options)
|
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 = 'baidu.com'
|
||||||
// const sni = ''
|
// 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 n = 0
|
||||||
let success = 0
|
let success = 0
|
||||||
|
|
|
@ -2,18 +2,50 @@ import DNSOverTLS from "../src/lib/dns/tls.js";
|
||||||
|
|
||||||
// 境外DNS的DoT配置sni测试
|
// 境外DNS的DoT配置sni测试
|
||||||
const servers = [
|
const servers = [
|
||||||
'1dot1dot1dot1.cloudflare-dns.com',
|
// 'dot.360.cn',
|
||||||
'cloudflare-dns.com',
|
|
||||||
|
'1.1.1.1', // 可直连,无需SNI(有时候可以,有时候不行)
|
||||||
'one.one.one.one',
|
'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',
|
'dot.sb',
|
||||||
'185.222.222.222',
|
'185.222.222.222',
|
||||||
'45.11.45.11',
|
'45.11.45.11',
|
||||||
|
|
||||||
'dns.adguard.com',
|
'dns.adguard.com',
|
||||||
|
'dns.adguard-dns.com',
|
||||||
'dns-family.adguard.com',
|
'dns-family.adguard.com',
|
||||||
|
'family.adguard-dns.com',
|
||||||
'dns-unfiltered.adguard.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 = [
|
const hostnames = [
|
||||||
|
@ -23,7 +55,7 @@ const hostnames = [
|
||||||
const sni = 'baidu.com'
|
const sni = 'baidu.com'
|
||||||
// const sni = ''
|
// 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 n = 0
|
||||||
let success = 0
|
let success = 0
|
||||||
|
|
|
@ -169,9 +169,6 @@ importers:
|
||||||
dns-over-http:
|
dns-over-http:
|
||||||
specifier: ^0.2.0
|
specifier: ^0.2.0
|
||||||
version: 0.2.0
|
version: 0.2.0
|
||||||
dns-over-tls:
|
|
||||||
specifier: ^0.0.9
|
|
||||||
version: 0.0.9
|
|
||||||
is-browser:
|
is-browser:
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
|
@ -3045,9 +3042,6 @@ packages:
|
||||||
dns-over-http@0.2.0:
|
dns-over-http@0.2.0:
|
||||||
resolution: {integrity: sha512-K+SyN2L3ljxJ2MFtOv/vRS+3/YEMLvOuH7MrmO5ejaubi4w02/DLqzoK1kBGKlQrT9ND57pbapeDf+ue8AElEA==}
|
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:
|
dns-packet@4.2.0:
|
||||||
resolution: {integrity: sha512-bn1AKpfkFbm0MIioOMHZ5qJzl2uypdBwI4nYNsqvhjsegBhcKJUlCrMPWLx6JEezRjxZmxhtIz/FkBEur2l8Cw==}
|
resolution: {integrity: sha512-bn1AKpfkFbm0MIioOMHZ5qJzl2uypdBwI4nYNsqvhjsegBhcKJUlCrMPWLx6JEezRjxZmxhtIz/FkBEur2l8Cw==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
@ -10553,10 +10547,6 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
dns-over-tls@0.0.9:
|
|
||||||
dependencies:
|
|
||||||
dns-packet: 5.6.1
|
|
||||||
|
|
||||||
dns-packet@4.2.0:
|
dns-packet@4.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ip: 1.1.9
|
ip: 1.1.9
|
||||||
|
|
Loading…
Reference in New Issue