diff --git a/doc/wiki/加速服务使用说明.md b/doc/wiki/加速服务使用说明.md index 2cd1d1e..4cbfb5c 100644 --- a/doc/wiki/加速服务使用说明.md +++ b/doc/wiki/加速服务使用说明.md @@ -43,7 +43,7 @@ "requestReplace": { "headers": { "User-Agent": "Mozilla/5.0", // 替换User-Agent - "Referer": "[remove]" // 删除Referer头 + "Referer": "[remove]" // 删除Refzerer头 }, "doDownload": true // 启用下载请求处理.要转换为下载请求,需要 responseReplace 拦截器的配合使用 }, @@ -55,9 +55,6 @@ "backup2.example.com" ], - //"proxy": "https://$1.proxy.com", - //"replace": "https://(.*?)\\.example\\.com" - //使用${path}数组捕获和替换 "sni": "example.com", // SNI服务器名称指示 "unVerifySsl": true, // 跳过SSL证书验证 diff --git a/packages/gui/src/view/pages/server.vue b/packages/gui/src/view/pages/server.vue index 7ceb64f..a3b02a9 100644 --- a/packages/gui/src/view/pages/server.vue +++ b/packages/gui/src/view/pages/server.vue @@ -163,7 +163,43 @@ export default { const listener = async (event, message) => { console.log('get speed event', event, message) if (message.key === 'getList') { - this.speedTestList = message.value + // 详细记录接收到的原始数据 + console.log('speedTestList raw data:', JSON.stringify(message.value, null, 2)) + + // 数据验证和标准化 + const validatedData = {} + for (const hostname in message.value) { + const item = message.value[hostname] + if (!item.backupList) { + console.warn(`Missing backupList for ${hostname}`) + continue + } + + validatedData[hostname] = { + alive: item.alive || [], + backupList: item.backupList.map(ipObj => { + // 标准化IP地址格式 + const standardized = { + host: ipObj.host, + port: ipObj.port || 443, + 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) @@ -453,8 +489,10 @@ export default { {{ element.host }} {{ element.time }}{{ element.time ? 'ms' : '' }} {{ element.dns }} + IPv6 @@ -509,4 +547,18 @@ export default { width: 45px; } } +.ipv6-tag { + position: relative; + padding-right: 40px; +} +.ipv6-badge { + position: absolute; + right: 5px; + top: 2px; + font-size: 10px; + background: #1890ff; + color: white; + padding: 0 4px; + border-radius: 3px; +} diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js index 6668ac0..adc2dcd 100644 --- a/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js +++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js @@ -11,52 +11,77 @@ module.exports = { if (tester) { 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, 4) + callback(null, aliveIpObj.host, family) return } else { log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`) } } - dns.lookup(hostname).then((ip) => { + + // 优先尝试IPv6查询 + dns.lookup(hostname, { family: 6 }).then((ip) => { + if (ip && ip !== hostname) { + if (isDnsIntercept) { + isDnsIntercept.dns = dns + 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}`) + } + callback(null, ip, 6) + return + } + + // 回退到IPv4查询 + return dns.lookup(hostname) + }).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) + } + if (isDnsIntercept) { isDnsIntercept.dns = dns isDnsIntercept.hostname = hostname isDnsIntercept.ip = ip } - if (ip !== hostname) { - // 判断是否为测速失败的IP,如果是,则不使用当前IP - let isTestFailedIp = false - if (tester && tester.ready && tester.backupList && tester.backupList.length > 0) { - for (let i = 0; i < tester.backupList.length; i++) { - const item = tester.backupList[i] - if (item.host === ip) { - if (item.time == null) { - isTestFailedIp = true - } - break + // 判断是否为测速失败的IP + let isTestFailedIp = false + if (tester && tester.ready && tester.backupList && tester.backupList.length > 0) { + for (let i = 0; i < tester.backupList.length; i++) { + const item = tester.backupList[i] + if (item.host === ip) { + if (item.time == null) { + isTestFailedIp = true } + break } } - if (isTestFailedIp === false) { - 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, 4) - return - } else { - // 使用默认dns - log.info(`----- ${action}: ${hostname}, use hostname by default DNS: ${hostname}, skip test failed ip from dns '${dns.dnsName}: ${ip}'${target}, options:`, options) + } + + 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}${target}, options:`, options, ', dns:', 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) => { + log.error(`DNS lookup error for ${hostname}:`, e) defaultDns.lookup(hostname, options, callback) }) } diff --git a/packages/mitmproxy/src/lib/speed/SpeedTester.js b/packages/mitmproxy/src/lib/speed/SpeedTester.js index 59f4995..26858e8 100644 --- a/packages/mitmproxy/src/lib/speed/SpeedTester.js +++ b/packages/mitmproxy/src/lib/speed/SpeedTester.js @@ -79,7 +79,31 @@ class SpeedTester { } async getFromOneDns (dns) { - return await dns._lookupInternal(this.hostname) + // 优先尝试IPv6查询 + try { + const ipv6Result = await dns._lookupInternal(this.hostname, { family: 6 }) + if (ipv6Result && ipv6Result.length > 0) { + // 标准化IPv6地址格式 + const standardized = ipv6Result.map(ip => { + // 确保IPv6地址格式统一 + if (ip.includes(':')) { + return ip.toLowerCase().replace(/\[|\]/g, '') + } + return ip + }) + log.debug(`[dns] Got IPv6 addresses for ${this.hostname}:`, standardized) + return standardized + } + } catch (e) { + log.debug(`[dns] IPv6 lookup failed for ${this.hostname}: ${e.message}`) + } + + // 回退到IPv4查询 + const ipv4Result = await dns._lookupInternal(this.hostname) + if (ipv4Result) { + log.debug(`[dns] Got IPv4 addresses for ${this.hostname}:`, ipv4Result) + } + return ipv4Result } async test () { @@ -88,6 +112,11 @@ class SpeedTester { 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) { diff --git a/packages/mitmproxy/test/ipv6nettest.js b/packages/mitmproxy/test/ipv6nettest.js new file mode 100644 index 0000000..b31eb10 --- /dev/null +++ b/packages/mitmproxy/test/ipv6nettest.js @@ -0,0 +1,55 @@ +const net = require('net'); +const { setTimeout } = require('timers/promises'); + +// 测试的IPv6地址和端口 +const TEST_HOST = '6.ipw.cn'; +const TEST_PORT = 80; +const TIMEOUT = 5000; // 5秒超时 + +async function testIPv6Connection() { + const socket = new net.Socket(); + + // 设置超时 + socket.setTimeout(TIMEOUT); + + try { + // 尝试连接 + await new Promise((resolve, reject) => { + socket.on('connect', () => { + const { address, port } = socket.address(); + console.log(`成功连接到 ${TEST_HOST} 的IPv6地址 [${address}]:${port}`); + socket.end(); + resolve(); + }); + + socket.on('timeout', () => { + socket.destroy(); + reject(new Error('连接超时')); + }); + + socket.on('error', (err) => { + reject(err); + }); + + socket.connect(TEST_PORT, TEST_HOST); + }); + + return true; + } catch (err) { + console.error('IPv6连接测试失败:', err.message); + return false; + } finally { + socket.destroy(); + } +} + +// 执行测试 +testIPv6Connection() + .then(success => { + console.log(`IPv6连接测试结果: ${success ? '成功' : '失败'}`); + process.exit(success ? 0 : 1); + }) + .catch(err => { + console.error('测试过程中发生错误:', err); + process.exit(1); + });