Skip to content

Commit 56b3f18

Browse files
authored
Merge pull request #572 from 8odream/2.0.0.3
IPv6 support based on 2.0.0.3 (the last version able to be built)
2 parents a48e41f + 5a3d321 commit 56b3f18

8 files changed

Lines changed: 218 additions & 57 deletions

File tree

packages/gui/src/view/pages/server.vue

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,10 @@ export default {
455455
</a>
456456
<a-tag
457457
v-for="(element, index) of item.backupList" :key="index" style="margin:2px;"
458-
:title="element.title || `测速中:${element.host}`" :color="element.time ? (element.time > config.server.setting.lowSpeedDelay ? 'orange' : 'green') : (element.title ? 'red' : '')"
458+
:title="element.title || `测速中:${element.host}`" :color="element.time ? (element.time > config.server.setting.lowSpeedDelay ? 'orange' : 'green') : (element.title ? 'red' : '')" :class="{'ipv6-tag': element.host.includes(':')}"
459459
>
460460
{{ element.host }} {{ element.time ? `${element.time}ms` : (element.title ? '' : '测速中') }} {{ element.dns }}
461+
<span v-if="element.host.includes(':')" class="ipv6-badge">IPv6</span>
461462
</a-tag>
462463
</a-card>
463464
</a-col>
@@ -511,5 +512,26 @@ export default {
511512
.ant-input-group-addon:first-child {
512513
width: 45px;
513514
}
515+
.ipv6-tag {
516+
position: relative;
517+
padding-right: 45px !important;
518+
margin-right: 5px !important;
519+
display: inline-flex !important;
520+
align-items: center !important;
521+
min-width: 200px !important;
522+
}
523+
.ipv6-badge {
524+
position: absolute;
525+
right: 5px;
526+
top: 50%;
527+
transform: translateY(-50%);
528+
font-size: 10px;
529+
background: #1890ff;
530+
color: white;
531+
padding: 0 4px;
532+
border-radius: 3px;
533+
line-height: 16px;
534+
height: 16px;
535+
}
514536
}
515537
</style>

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

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const LRUCache = require('lru-cache')
22
const log = require('../../utils/util.log.server')
3+
const net = require('node:net')
34
const matchUtil = require('../../utils/util.match')
45
const { DynamicChoice } = require('../choice/index')
56

@@ -52,7 +53,7 @@ module.exports = class BaseDNS {
5253
}
5354
}
5455

55-
async lookup (hostname, ipChecker) {
56+
async lookup (hostname, ipChecker, options = {}) {
5657
try {
5758
let ipCache = this.cache.get(hostname)
5859
if (ipCache) {
@@ -71,9 +72,9 @@ module.exports = class BaseDNS {
7172
}
7273

7374
const t = Date.now()
74-
let ipList = await this._lookupWithPreSetIpList(hostname)
75+
let ipList = await this._lookupWithPreSetIpList(hostname, options)
7576
if (ipList == null) {
76-
// 没有获取到ipv4地址
77+
// 没有获取到ip地址
7778
ipList = []
7879
}
7980
ipList.push(hostname) // 把原域名加入到统计里去
@@ -102,7 +103,7 @@ module.exports = class BaseDNS {
102103
}
103104
}
104105

105-
async _lookupWithPreSetIpList (hostname) {
106+
async _lookupWithPreSetIpList (hostname, options = {}) {
106107
if (this.preSetIpList) {
107108
// 获取当前域名的预设IP列表
108109
let hostnamePreSetIpList = matchUtil.matchHostname(this.preSetIpList, hostname, `matched preSetIpList(${this.dnsName})`)
@@ -114,28 +115,50 @@ module.exports = class BaseDNS {
114115
}
115116

116117
if (hostnamePreSetIpList.length > 0) {
117-
hostnamePreSetIpList.isPreSet = true
118-
log.info(`[DNS-over-PreSet '${this.dnsName}'] 获取到该域名的预设IP列表: ${hostname} - ${JSON.stringify(hostnamePreSetIpList)}`)
119-
return hostnamePreSetIpList
118+
const result = []
119+
for (const item of hostnamePreSetIpList) {
120+
if (net.isIP(item)) {
121+
// 如果是IP地址,直接使用
122+
result.push(item)
123+
} else {
124+
// 如果是域名,进行DNS解析
125+
try {
126+
const resolved = await this._lookup(item, options)
127+
if (resolved && resolved.length > 0) {
128+
result.push(...resolved)
129+
}
130+
} catch (e) {
131+
log.error(`[DNS-over-${this.dnsType} '${this.dnsName}'] 解析预设域名失败: ${item}`, e)
132+
}
133+
}
134+
}
135+
136+
if (result.length > 0) {
137+
result.isPreSet = true
138+
log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 获取到该域名的预设IP列表: ${hostname} - ${JSON.stringify(result)}`)
139+
return result
140+
}
120141
}
121142
}
122143
}
123144

124-
return await this._lookup(hostname)
145+
return await this._lookup(hostname, options)
125146
}
126147

127-
async _lookup (hostname) {
148+
async _lookup (hostname, options = {}) {
128149
const start = Date.now()
129150

130151
let response
131152
try {
132153
// 执行DNS查询
133154
log.debug(`[DNS-over-${this.dnsType} '${this.dnsName}'] query start: ${hostname}`)
134-
response = await this._doDnsQuery(hostname, 'A', start)
155+
response = await this._doDnsQuery(hostname, options, start)
135156
} catch {
136157
// 异常日志在 _doDnsQuery已经打印过,这里就不再打印了
137158
return []
138159
}
160+
// 根据查询类型过滤结果
161+
const type = options.family === 6 ? 'AAAA' : 'A'
139162

140163
try {
141164
const cost = Date.now() - start
@@ -146,11 +169,11 @@ module.exports = class BaseDNS {
146169
return []
147170
}
148171

149-
const ret = response.answers.filter(item => item.type === 'A').map(item => item.data)
172+
const ret = response.answers.filter(item => item.type === type).map(item => item.data)
150173
if (ret.length === 0) {
151-
log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 没有该域名的IP地址: ${hostname}, cost: ${cost} ms`)
174+
log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 没有该域名的IPv${options.family === 6 ? '6' : '4'}地址: ${hostname}, cost: ${cost} ms`)
152175
} else {
153-
log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 获取到该域名的IP地址${hostname} - ${JSON.stringify(ret)}, cost: ${cost} ms`)
176+
log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 获取到该域名的IPv${options.family === 6 ? '6' : '4'}地址${hostname} - ${JSON.stringify(ret)}, cost: ${cost} ms`)
154177
}
155178

156179
return ret
@@ -160,7 +183,7 @@ module.exports = class BaseDNS {
160183
}
161184
}
162185

163-
_doDnsQuery (hostname, type = 'A', start) {
186+
_doDnsQuery (hostname, options = {}, start = null) {
164187
if (start == null) {
165188
start = Date.now()
166189
}
@@ -171,14 +194,14 @@ module.exports = class BaseDNS {
171194
const timeout = 6000
172195
const timeoutId = setTimeout(() => {
173196
if (!isOver) {
174-
log.error(`[DNS-over-${this.dnsType} '${this.dnsName}'] DNS查询超时, hostname: ${hostname}, type: ${type}${this.dnsServer ? `, dnsServer: ${this.dnsServer}` : ''}${this.dnsServerPort ? `:${this.dnsServerPort}` : ''}, cost: ${Date.now() - start} ms`)
197+
log.error(`[DNS-over-${this.dnsType} '${this.dnsName}'] DNS查询超时, hostname: ${hostname}, cost: ${Date.now() - start} ms`)
175198
reject(new Error('DNS查询超时'))
176199
}
177200
}, timeout)
178201

179202
try {
180-
this._dnsQueryPromise(hostname, type)
181-
.then((response) => {
203+
this._dnsQueryPromise(hostname, options)
204+
.then((response) => {
182205
isOver = true
183206
clearTimeout(timeoutId)
184207
resolve(response)

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@ module.exports = class DNSOverHTTPS extends BaseDNS {
2020
this.dnsServerName = dnsServerName
2121
}
2222

23-
_dnsQueryPromise (hostname, type = 'A') {
23+
_dnsQueryPromise (hostname, options = {}) {
2424
// 请求参数
25-
const options = {
25+
const type = options.family === 6 ? 'AAAA' : 'A'
26+
const requestOptions = {
2627
url: this.dnsServer,
2728
agent: createAgent(this.dnsServer),
2829
}
2930
if (this.dnsServerName) {
3031
// 设置SNI
31-
options.servername = this.dnsServerName
32-
options.rejectUnauthorized = false
32+
requestOptions.servername = this.dnsServerName
33+
requestOptions.rejectUnauthorized = false
3334
}
3435

3536
// DNS查询参数
@@ -40,6 +41,6 @@ module.exports = class DNSOverHTTPS extends BaseDNS {
4041
},
4142
]
4243

43-
return dohQueryAsync(options, questions)
44+
return dohQueryAsync(requestOptions, questions)
4445
}
4546
}

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,20 @@ const defaultPort = 53 // TCP类型的DNS服务默认端口号
99
module.exports = class DNSOverTCP extends BaseDNS {
1010
constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort) {
1111
super(dnsName, 'TCP', cacheSize, preSetIpList)
12-
this.dnsServer = dnsServer.replace(/\s+/, '')
12+
this.dnsServer = dnsServer.replace(/\s+/g, '')
1313
this.dnsServerPort = Number.parseInt(dnsServerPort) || defaultPort
14+
this.isIPv6 = dnsServer.includes(':') && dnsServer.includes('[') && dnsServer.includes(']')
1415
}
1516

16-
_dnsQueryPromise (hostname, type = 'A') {
17+
_dnsQueryPromise (hostname, options = {}) {
1718
return new Promise((resolve, reject) => {
1819
// 构造 DNS 查询报文
1920
const packet = dnsPacket.encode({
2021
flags: dnsPacket.RECURSION_DESIRED,
2122
type: 'query',
2223
id: randi(0x0, 0xFFFF),
2324
questions: [{
24-
type,
25+
type: options.family === 6 ? 'AAAA' : 'A',
2526
name: hostname,
2627
}],
2728
})
@@ -30,6 +31,7 @@ module.exports = class DNSOverTCP extends BaseDNS {
3031
const tcpClient = net.createConnection({
3132
host: this.dnsServer,
3233
port: this.dnsServerPort,
34+
family: this.isIPv6 ? 6 : 4
3335
}, () => {
3436
// TCP DNS 报文前需添加 2 字节长度头
3537
const lengthBuffer = Buffer.alloc(2)

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@ const defaultPort = 853
66
module.exports = class DNSOverTLS extends BaseDNS {
77
constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort, dnsServerName) {
88
super(dnsName, 'TLS', cacheSize, preSetIpList)
9-
this.dnsServer = dnsServer.replace(/\s+/, '')
9+
this.dnsServer = dnsServer.replace(/\s+/g, '')
1010
this.dnsServerPort = Number.parseInt(dnsServerPort) || defaultPort
1111
this.dnsServerName = dnsServerName
12+
this.isIPv6 = dnsServer.includes(':') && dnsServer.includes('[') && dnsServer.includes(']')
1213
}
1314

14-
_dnsQueryPromise (hostname, type = 'A') {
15-
const options = {
15+
_dnsQueryPromise (hostname, options = {}) {
16+
const queryOptions = {
1617
host: this.dnsServer,
1718
port: this.dnsServerPort,
1819
servername: this.dnsServerName || this.dnsServer,
19-
20+
family: this.isIPv6 ? 6 : 4,
2021
name: hostname,
2122
klass: 'IN',
22-
type,
23+
type: options.family === 6 ? 'AAAA' : 'A',
2324
}
2425

25-
return dnstls.query(options)
26+
return dnstls.query(queryOptions)
2627
}
2728
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = class DNSOverUDP extends BaseDNS {
1515
this.socketType = this.isIPv6 ? 'udp6' : 'udp4'
1616
}
1717

18-
_dnsQueryPromise (hostname, type = 'A') {
18+
_dnsQueryPromise (hostname, options = {}) {
1919
return new Promise((resolve, reject) => {
2020
let isOver = false
2121
const timeout = 5000
@@ -27,7 +27,7 @@ module.exports = class DNSOverUDP extends BaseDNS {
2727
type: 'query',
2828
id: randi(0x0, 0xFFFF),
2929
questions: [{
30-
type,
30+
type: options.family === 6 ? 'AAAA' : 'A',
3131
name: hostname,
3232
}],
3333
})

0 commit comments

Comments
 (0)