Skip to content

Commit 217ce9d

Browse files
bugfix: DoT的DNS,配置了SNI但未生效的问题修复
1 parent c18a624 commit 217ce9d

File tree

8 files changed

+124
-19
lines changed

8 files changed

+124
-19
lines changed

packages/mitmproxy/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"axios": "^1.7.7",
1919
"baidu-aip-sdk": "^4.16.16",
2020
"dns-over-http": "^0.2.0",
21-
"dns-over-tls": "^0.0.9",
2221
"is-browser": "^2.1.0",
2322
"json5": "^2.2.3",
2423
"lodash": "^4.17.21",

packages/mitmproxy/src/lib/dns/base.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ module.exports = class BaseDNS {
168168
return new Promise((resolve, reject) => {
169169
// 设置超时任务
170170
let isOver = false
171-
const timeout = 6000
171+
const timeout = 8000
172172
const timeoutId = setTimeout(() => {
173173
if (!isOver) {
174174
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`)

packages/mitmproxy/src/lib/dns/https.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const dohQueryAsync = promisify(doh.query)
99
function createAgent (dnsServer) {
1010
return new (dnsServer.startsWith('https:') ? HttpsAgent : Agent)({
1111
keepAlive: true,
12-
timeout: 20000,
12+
timeout: 4000,
1313
})
1414
}
1515

packages/mitmproxy/src/lib/dns/tls.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const dnstls = require('dns-over-tls')
1+
const dnstls = require('./util/dns-over-tls')
22
const BaseDNS = require('./base')
33

44
const defaultPort = 853
@@ -16,10 +16,13 @@ module.exports = class DNSOverTLS extends BaseDNS {
1616
host: this.dnsServer,
1717
port: this.dnsServerPort,
1818
servername: this.dnsServerName || this.dnsServer,
19+
rejectUnauthorized: !this.dnsServerName,
1920

2021
name: hostname,
2122
klass: 'IN',
2223
type,
24+
25+
timeout: 4000,
2326
}
2427

2528
return dnstls.query(options)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* 由于组件 `[email protected]` 不支持 `rejectUnauthorized` 和 `timeout` 两个参数,所以将源码复制过来,并简化了代码。
3+
*/
4+
const dnsPacket = require('dns-packet')
5+
const tls_1 = require('node:tls')
6+
const randi = require('random-int')
7+
8+
const TWO_BYTES = 2
9+
10+
function getDnsQuery ({ type, name, klass, id }) {
11+
return {
12+
id,
13+
type: 'query',
14+
flags: dnsPacket.RECURSION_DESIRED,
15+
questions: [{ class: klass, name, type }],
16+
}
17+
}
18+
19+
function query ({ host, servername, type, name, klass, port, rejectUnauthorized, timeout }) {
20+
return new Promise((resolve, reject) => {
21+
if (!host || !servername || !name) {
22+
throw new Error('At least host, servername and name must be set.')
23+
}
24+
25+
let response = Buffer.alloc(0)
26+
let packetLength = 0
27+
const dnsQuery = getDnsQuery({ id: randi(0x0, 0xFFFF), type, name, klass })
28+
const dnsQueryBuf = dnsPacket.streamEncode(dnsQuery)
29+
const socket = tls_1.connect({ host, port, servername, rejectUnauthorized, timeout })
30+
31+
// 超时处理
32+
let isFinished = false
33+
let interval
34+
if (timeout > 0) {
35+
interval = setInterval(() => {
36+
if (!isFinished) {
37+
socket.destroy((...args) => {
38+
console.info('socket destory callback args:', args)
39+
})
40+
41+
reject(new Error('DNS查询超时'))
42+
}
43+
}, timeout)
44+
}
45+
46+
socket.on('secureConnect', () => socket.write(dnsQueryBuf))
47+
socket.on('data', (data) => {
48+
if (timeout) {
49+
isFinished = true
50+
clearInterval(interval)
51+
}
52+
53+
if (response.length === 0) {
54+
packetLength = data.readUInt16BE(0)
55+
if (packetLength < 12) {
56+
reject(new Error('Below DNS minimum packet length (DNS Header is 12 bytes)'))
57+
}
58+
response = Buffer.from(data)
59+
} else {
60+
response = Buffer.concat([response, data])
61+
}
62+
63+
if (response.length === packetLength + TWO_BYTES) {
64+
socket.destroy()
65+
resolve(dnsPacket.streamDecode(response))
66+
} else {
67+
reject(new Error('响应长度不正确'))
68+
}
69+
})
70+
socket.on('error', (err) => {
71+
if (timeout) {
72+
isFinished = true
73+
clearInterval(interval)
74+
}
75+
reject(err)
76+
})
77+
})
78+
}
79+
80+
exports.query = query
81+
exports.default = { query }

packages/mitmproxy/test/dnsTest-abroad-doh-sni.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const hostnames = [
3838
const sni = 'baidu.com'
3939
// const sni = ''
4040

41-
console.log(`\n--------------- 测试DoH的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名 ---------------\n`)
41+
console.log(`\n--------------- 测试DoH的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名,SNI: ${sni || '无'} ---------------\n`)
4242

4343
let n = 0
4444
let success = 0

packages/mitmproxy/test/dnsTest-abroad-dot-sni.mjs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,50 @@ import DNSOverTLS from "../src/lib/dns/tls.js";
22

33
// 境外DNS的DoT配置sni测试
44
const servers = [
5-
'1dot1dot1dot1.cloudflare-dns.com',
6-
'cloudflare-dns.com',
5+
// 'dot.360.cn',
6+
7+
'1.1.1.1', // 可直连,无需SNI(有时候可以,有时候不行)
78
'one.one.one.one',
8-
// '1.1.1.1', // 可直连,无需SNI
9+
'cloudflare-dns.com',
10+
'security.cloudflare-dns.com',
11+
'family.cloudflare-dns.com',
12+
'1dot1dot1dot1.cloudflare-dns.com',
913

1014
'dot.sb',
1115
'185.222.222.222',
1216
'45.11.45.11',
1317

1418
'dns.adguard.com',
19+
'dns.adguard-dns.com',
1520
'dns-family.adguard.com',
21+
'family.adguard-dns.com',
1622
'dns-unfiltered.adguard.com',
23+
'unfiltered.adguard-dns.com',
24+
'dns.bebasid.com',
25+
'unfiltered.dns.bebasid.com',
26+
'antivirus.bebasid.com',
27+
'internetsehat.bebasid.com',
28+
'family-adblock.bebasid.com',
29+
'oisd.dns.bebasid.com',
30+
'hagezi.dns.bebasid.com',
31+
'dns.cfiec.net',
32+
'dns.opendns.com',
33+
'familyshield.opendns.com',
34+
'sandbox.opendns.com',
35+
'family-filter-dns.cleanbrowsing.org',
36+
'adult-filter-dns.cleanbrowsing.org',
37+
'security-filter-dns.cleanbrowsing.org',
38+
'p0.freedns.controld.com',
39+
'p1.freedns.controld.com',
40+
'p2.freedns.controld.com',
41+
'p3.freedns.controld.com',
42+
'dns.decloudus.com',
43+
'getdnsapi.net',
44+
'dnsovertls.sinodun.com',
45+
'dnsovertls1.sinodun.com',
46+
'dns.de.futuredns.eu.org',
47+
'dns.us.futuredns.eu.org',
48+
'unicast.censurfridns.dk',
1749
]
1850

1951
const hostnames = [
@@ -23,7 +55,7 @@ const hostnames = [
2355
const sni = 'baidu.com'
2456
// const sni = ''
2557

26-
console.log(`\n--------------- 测试DoT的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名 ---------------\n`)
58+
console.log(`\n--------------- 测试DoT的SNI功能:共 ${servers.length} 个服务,${hostnames.length} 个域名,SNI: ${sni || '无'} ---------------\n`)
2759

2860
let n = 0
2961
let success = 0

pnpm-lock.yaml

Lines changed: 0 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)