diff --git a/packages/gui/src/view/pages/server.vue b/packages/gui/src/view/pages/server.vue index a3b02a9..d44855a 100644 --- a/packages/gui/src/view/pages/server.vue +++ b/packages/gui/src/view/pages/server.vue @@ -161,11 +161,7 @@ export default { }, registerSpeedTestEvent () { const listener = async (event, message) => { - console.log('get speed event', event, message) if (message.key === 'getList') { - // 详细记录接收到的原始数据 - console.log('speedTestList raw data:', JSON.stringify(message.value, null, 2)) - // 数据验证和标准化 const validatedData = {} for (const hostname in message.value) { @@ -185,21 +181,12 @@ export default { dns: ipObj.dns || 'unknown', time: ipObj.time || null } - - // 特殊处理IPv6地址 - if (ipObj.host.includes(':')) { - console.log('Found IPv6 address:', { - original: ipObj.host, - standardized: standardized.host - }) - } return standardized }) } } this.speedTestList = validatedData - console.log('Validated speed test data:', JSON.stringify(validatedData, null, 2)) } } this.$api.ipc.on('speed', listener) @@ -549,16 +536,101 @@ export default { } .ipv6-tag { position: relative; - padding-right: 40px; + padding-right: 45px !important; + margin-right: 5px !important; + display: inline-flex !important; + align-items: center !important; + min-width: 200px !important; } .ipv6-badge { position: absolute; right: 5px; - top: 2px; + top: 50%; + transform: translateY(-50%); font-size: 10px; background: #1890ff; color: white; padding: 0 4px; border-radius: 3px; + line-height: 16px; + height: 16px; +} +.ip-box { + display: flex; + flex-wrap: wrap; + gap: 8px; + padding: 8px; + background-color: #fafafa; + border-radius: 4px; + margin-top: 8px; + max-width: 100%; + overflow: hidden; +} +.ip-item { + display: flex; + align-items: center; + padding: 4px 8px; + background-color: #fff; + border: 1px solid #e8e8e8; + border-radius: 4px; + font-size: 12px; + color: #666; + word-break: break-all; + max-width: calc(100% - 16px); + flex: 1 1 auto; + min-width: 0; +} +.ip-item .ip-text { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.ip-item .ip-speed { + margin-left: 8px; + white-space: nowrap; +} +.ip-item .ip-speed.success { + color: #52c41a; +} +.ip-item .ip-speed.warning { + color: #faad14; +} +.ip-item .ip-speed.error { + color: #ff4d4f; +} +.domain-box { + margin-bottom: 16px; + padding: 12px; + background-color: #fff; + border: 1px solid #e8e8e8; + border-radius: 4px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + overflow: hidden; +} +.domain-box .domain-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +} +.domain-box .domain-title { + font-size: 14px; + font-weight: 500; + color: #333; + margin: 0; + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.domain-box .domain-actions { + display: flex; + align-items: center; + gap: 8px; + margin-left: 8px; + flex-shrink: 0; } diff --git a/packages/mitmproxy/src/lib/dns/base.js b/packages/mitmproxy/src/lib/dns/base.js index fb44844..6a745c6 100644 --- a/packages/mitmproxy/src/lib/dns/base.js +++ b/packages/mitmproxy/src/lib/dns/base.js @@ -52,7 +52,7 @@ module.exports = class BaseDNS { } } - async lookup (hostname) { + async lookup (hostname, options = {}) { try { let ipCache = this.cache.get(hostname) if (ipCache) { @@ -66,9 +66,9 @@ module.exports = class BaseDNS { } const t = new Date() - let ipList = await this._lookupInternal(hostname) + let ipList = await this._lookupInternal(hostname, options) if (ipList == null) { - // 没有获取到ipv4地址 + // 没有获取到ip ipList = [] } ipList.push(hostname) // 把原域名加入到统计里去 @@ -83,7 +83,7 @@ module.exports = class BaseDNS { } } - async _lookupInternal (hostname) { + async _lookupInternal (hostname, options = {}) { // 获取当前域名的预设IP列表 let hostnamePreSetIpList = matchUtil.matchHostname(this.preSetIpList, hostname, `matched preSetIpList(${this.dnsName})`) if (hostnamePreSetIpList && (hostnamePreSetIpList.length > 0 || hostnamePreSetIpList.length === undefined)) { @@ -100,24 +100,28 @@ module.exports = class BaseDNS { } } - return await this._lookup(hostname) + return await this._lookup(hostname, options) } - async _lookup (hostname) { + async _lookup (hostname, options = {}) { const start = Date.now() try { - const response = await this._doDnsQuery(hostname) + const response = await this._doDnsQuery(hostname, options) const cost = Date.now() - start if (response == null || response.answers == null || response.answers.length == null || response.answers.length === 0) { // 说明没有获取到ip log.warn(`[DNS-over-${this.dnsType} '${this.dnsName}'] 没有该域名的IP地址: ${hostname}, cost: ${cost} ms, response:`, response) return [] } - const ret = response.answers.filter(item => item.type === 'A').map(item => item.data) + + // 根据查询类型过滤结果 + const type = options.family === 6 ? 'AAAA' : 'A' + const ret = response.answers.filter(item => item.type === type).map(item => item.data) + if (ret.length === 0) { - log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 没有该域名的IPv4地址: ${hostname}, cost: ${cost} ms`) + log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 没有该域名的IPv${options.family === 6 ? '6' : '4'}地址: ${hostname}, cost: ${cost} ms`) } else { - log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 获取到该域名的IPv4地址: ${hostname} - ${JSON.stringify(ret)}, cost: ${cost} ms`) + log.info(`[DNS-over-${this.dnsType} '${this.dnsName}'] 获取到该域名的IPv${options.family === 6 ? '6' : '4'}地址: ${hostname} - ${JSON.stringify(ret)}, cost: ${cost} ms`) } return ret } catch (e) { diff --git a/packages/mitmproxy/src/lib/dns/https.js b/packages/mitmproxy/src/lib/dns/https.js index 3ab889c..42f773d 100644 --- a/packages/mitmproxy/src/lib/dns/https.js +++ b/packages/mitmproxy/src/lib/dns/https.js @@ -8,9 +8,19 @@ module.exports = class DNSOverHTTPS extends BaseDNS { constructor (dnsName, cacheSize, preSetIpList, dnsServer) { super(dnsName, 'HTTPS', cacheSize, preSetIpList) this.dnsServer = dnsServer + this.isIPv6 = dnsServer.includes(':') && dnsServer.includes('[') && dnsServer.includes(']') } - async _doDnsQuery (hostname) { - return await dohQueryAsync({ url: this.dnsServer }, [{ type: 'A', name: hostname }]) + async _doDnsQuery (hostname, options = {}) { + return await dohQueryAsync( + { + url: this.dnsServer, + family: this.isIPv6 ? 6 : 4 + }, + [{ + type: options.family === 6 ? 'AAAA' : 'A', + name: hostname + }] + ) } } diff --git a/packages/mitmproxy/src/lib/dns/tcp.js b/packages/mitmproxy/src/lib/dns/tcp.js index 6141609..8ab8209 100644 --- a/packages/mitmproxy/src/lib/dns/tcp.js +++ b/packages/mitmproxy/src/lib/dns/tcp.js @@ -4,16 +4,17 @@ const dnsPacket = require('dns-packet') const randi = require('random-int') const BaseDNS = require('./base') -const defaultPort = 53 // UDP类型的DNS服务默认端口号 +const defaultPort = 53 // TCP类型的DNS服务默认端口号 module.exports = class DNSOverTCP extends BaseDNS { constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort) { super(dnsName, 'TCP', cacheSize, preSetIpList) this.dnsServer = dnsServer this.dnsServerPort = Number.parseInt(dnsServerPort) || defaultPort + this.isIPv6 = dnsServer.includes(':') && dnsServer.includes('[') && dnsServer.includes(']') } - _doDnsQuery (hostname) { + _doDnsQuery (hostname, options = {}) { return new Promise((resolve, reject) => { // 构造 DNS 查询报文 const packet = dnsPacket.encode({ @@ -21,7 +22,7 @@ module.exports = class DNSOverTCP extends BaseDNS { type: 'query', id: randi(0x0, 0xFFFF), questions: [{ - type: 'A', + type: options.family === 6 ? 'AAAA' : 'A', name: hostname, }], }) @@ -30,6 +31,7 @@ module.exports = class DNSOverTCP extends BaseDNS { const tcpClient = net.createConnection({ host: this.dnsServer, port: this.dnsServerPort, + family: this.isIPv6 ? 6 : 4 }, () => { // TCP DNS 报文前需添加 2 字节长度头 const lengthBuffer = Buffer.alloc(2) diff --git a/packages/mitmproxy/src/lib/dns/tls.js b/packages/mitmproxy/src/lib/dns/tls.js index b4b5d99..80b01ee 100644 --- a/packages/mitmproxy/src/lib/dns/tls.js +++ b/packages/mitmproxy/src/lib/dns/tls.js @@ -9,19 +9,21 @@ module.exports = class DNSOverTLS extends BaseDNS { this.dnsServer = dnsServer this.dnsServerPort = Number.parseInt(dnsServerPort) || defaultPort this.dnsServerName = dnsServerName + this.isIPv6 = dnsServer.includes(':') && dnsServer.includes('[') && dnsServer.includes(']') } - async _doDnsQuery (hostname) { - const options = { + async _doDnsQuery (hostname, options = {}) { + const queryOptions = { host: this.dnsServer, port: this.dnsServerPort, servername: this.dnsServerName || this.dnsServer, + family: this.isIPv6 ? 6 : 4, name: hostname, klass: 'IN', - type: 'A', + type: options.family === 6 ? 'AAAA' : 'A', } - return await dnstls.query(options) + return await dnstls.query(queryOptions) } } diff --git a/packages/mitmproxy/src/lib/dns/udp.js b/packages/mitmproxy/src/lib/dns/udp.js index 86d9b30..57552bc 100644 --- a/packages/mitmproxy/src/lib/dns/udp.js +++ b/packages/mitmproxy/src/lib/dns/udp.js @@ -15,7 +15,7 @@ module.exports = class DNSOverUDP extends BaseDNS { this.socketType = this.isIPv6 ? 'udp6' : 'udp4' } - _doDnsQuery (hostname) { + _doDnsQuery (hostname, options = {}) { return new Promise((resolve, reject) => { // 构造 DNS 查询报文 const packet = dnsPacket.encode({ @@ -23,7 +23,7 @@ module.exports = class DNSOverUDP extends BaseDNS { type: 'query', id: randi(0x0, 0xFFFF), questions: [{ - type: 'A', + type: options.family === 6 ? 'AAAA' : 'A', name: hostname, }], }) diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js index adc2dcd..0dea8c4 100644 --- a/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js +++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js @@ -12,14 +12,11 @@ module.exports = { const aliveIpObj = tester.pickFastAliveIpObj() if (aliveIpObj) { const family = aliveIpObj.host.includes(':') ? 6 : 4 - log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`) if (res) { res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`) } callback(null, aliveIpObj.host, family) return - } else { - log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`) } } @@ -31,7 +28,6 @@ module.exports = { isDnsIntercept.hostname = hostname isDnsIntercept.ip = ip } - log.info(`----- ${action}: ${hostname}, use ipv6 from dns '${dns.dnsName}': ${ip}${target} -----`) if (res) { res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.dnsName === '预设IP' ? 'PreSet' : dns.dnsName}`) } @@ -44,7 +40,6 @@ module.exports = { }).then((ip) => { if (!ip || ip === hostname) { // 使用默认dns - log.info(`----- ${action}: ${hostname}, use hostname by default DNS: ${hostname}${target}, options:`, options, ', dns:', dns) return defaultDns.lookup(hostname, options, callback) } @@ -70,14 +65,12 @@ module.exports = { if (!isTestFailedIp) { const family = ip.includes(':') ? 6 : 4 - log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.dnsName}': ${ip}${target} -----`) if (res) { res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.dnsName === '预设IP' ? 'PreSet' : dns.dnsName}`) } callback(null, ip, family) } else { // 使用默认dns - log.info(`----- ${action}: ${hostname}, use hostname by default DNS: ${hostname}, skip test failed ip from dns '${dns.dnsName}: ${ip}'${target}, options:`, options) defaultDns.lookup(hostname, options, callback) } }).catch((e) => { diff --git a/packages/mitmproxy/src/lib/speed/SpeedTester.js b/packages/mitmproxy/src/lib/speed/SpeedTester.js index 26858e8..c781e99 100644 --- a/packages/mitmproxy/src/lib/speed/SpeedTester.js +++ b/packages/mitmproxy/src/lib/speed/SpeedTester.js @@ -79,6 +79,8 @@ class SpeedTester { } async getFromOneDns (dns) { + const results = [] + // 优先尝试IPv6查询 try { const ipv6Result = await dns._lookupInternal(this.hostname, { family: 6 }) @@ -91,19 +93,23 @@ class SpeedTester { } return ip }) - log.debug(`[dns] Got IPv6 addresses for ${this.hostname}:`, standardized) - return standardized + results.push(...standardized) } } catch (e) { - log.debug(`[dns] IPv6 lookup failed for ${this.hostname}: ${e.message}`) + // IPv6查询失败,继续尝试IPv4 } - // 回退到IPv4查询 - const ipv4Result = await dns._lookupInternal(this.hostname) - if (ipv4Result) { - log.debug(`[dns] Got IPv4 addresses for ${this.hostname}:`, ipv4Result) + // 尝试IPv4查询 + try { + const ipv4Result = await dns._lookupInternal(this.hostname) + if (ipv4Result) { + results.push(...ipv4Result) + } + } catch (e) { + // IPv4查询失败 } - return ipv4Result + + return results } async test () { @@ -111,13 +117,6 @@ class SpeedTester { const newBackupList = [...newList, ...this.backupList] this.backupList = _.unionBy(newBackupList, 'host') this.testCount++ - - // 详细记录IPv6地址 - const ipv6List = this.backupList.filter(item => item.host.includes(':')) - if (ipv6List.length > 0) { - log.info('[speed] IPv6 addresses found for', this.hostname, ':', ipv6List) - } - log.info('[speed]', this.hostname, '➜ ip-list:', this.backupList) await this.testBackups() if (config.notify) { config.notify({ key: 'test' })