尝试ipv6支持
parent
04decbed48
commit
8a722282fb
|
@ -43,7 +43,7 @@
|
||||||
"requestReplace": {
|
"requestReplace": {
|
||||||
"headers": {
|
"headers": {
|
||||||
"User-Agent": "Mozilla/5.0", // 替换User-Agent
|
"User-Agent": "Mozilla/5.0", // 替换User-Agent
|
||||||
"Referer": "[remove]" // 删除Referer头
|
"Referer": "[remove]" // 删除Refzerer头
|
||||||
},
|
},
|
||||||
"doDownload": true // 启用下载请求处理.要转换为下载请求,需要 responseReplace 拦截器的配合使用
|
"doDownload": true // 启用下载请求处理.要转换为下载请求,需要 responseReplace 拦截器的配合使用
|
||||||
},
|
},
|
||||||
|
@ -55,9 +55,6 @@
|
||||||
"backup2.example.com"
|
"backup2.example.com"
|
||||||
],
|
],
|
||||||
|
|
||||||
//"proxy": "https://$1.proxy.com",
|
|
||||||
//"replace": "https://(.*?)\\.example\\.com"
|
|
||||||
//使用${path}数组捕获和替换
|
|
||||||
|
|
||||||
"sni": "example.com", // SNI服务器名称指示
|
"sni": "example.com", // SNI服务器名称指示
|
||||||
"unVerifySsl": true, // 跳过SSL证书验证
|
"unVerifySsl": true, // 跳过SSL证书验证
|
||||||
|
|
|
@ -163,7 +163,43 @@ export default {
|
||||||
const listener = async (event, message) => {
|
const listener = async (event, message) => {
|
||||||
console.log('get speed event', event, message)
|
console.log('get speed event', event, message)
|
||||||
if (message.key === 'getList') {
|
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)
|
this.$api.ipc.on('speed', listener)
|
||||||
|
@ -453,8 +489,10 @@ export default {
|
||||||
<a-tag
|
<a-tag
|
||||||
v-for="(element, index) of item.backupList" :key="index" style="margin:2px;"
|
v-for="(element, index) of item.backupList" :key="index" style="margin:2px;"
|
||||||
:title="element.dns" :color="element.time ? (element.time > config.server.setting.lowSpeedDelay ? 'orange' : 'green') : 'red'"
|
:title="element.dns" :color="element.time ? (element.time > config.server.setting.lowSpeedDelay ? 'orange' : 'green') : 'red'"
|
||||||
|
:class="{'ipv6-tag': element.host.includes(':')}"
|
||||||
>
|
>
|
||||||
{{ element.host }} {{ element.time }}{{ element.time ? 'ms' : '' }} {{ element.dns }}
|
{{ element.host }} {{ element.time }}{{ element.time ? 'ms' : '' }} {{ element.dns }}
|
||||||
|
<span v-if="element.host.includes(':')" class="ipv6-badge">IPv6</span>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
@ -509,4 +547,18 @@ export default {
|
||||||
width: 45px;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,52 +11,77 @@ module.exports = {
|
||||||
if (tester) {
|
if (tester) {
|
||||||
const aliveIpObj = tester.pickFastAliveIpObj()
|
const aliveIpObj = tester.pickFastAliveIpObj()
|
||||||
if (aliveIpObj) {
|
if (aliveIpObj) {
|
||||||
|
const family = aliveIpObj.host.includes(':') ? 6 : 4
|
||||||
log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`)
|
log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`)
|
||||||
if (res) {
|
if (res) {
|
||||||
res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`)
|
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
|
return
|
||||||
} else {
|
} else {
|
||||||
log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`)
|
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) {
|
if (isDnsIntercept) {
|
||||||
isDnsIntercept.dns = dns
|
isDnsIntercept.dns = dns
|
||||||
isDnsIntercept.hostname = hostname
|
isDnsIntercept.hostname = hostname
|
||||||
isDnsIntercept.ip = ip
|
isDnsIntercept.ip = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip !== hostname) {
|
// 判断是否为测速失败的IP
|
||||||
// 判断是否为测速失败的IP,如果是,则不使用当前IP
|
let isTestFailedIp = false
|
||||||
let isTestFailedIp = false
|
if (tester && tester.ready && tester.backupList && tester.backupList.length > 0) {
|
||||||
if (tester && tester.ready && tester.backupList && tester.backupList.length > 0) {
|
for (let i = 0; i < tester.backupList.length; i++) {
|
||||||
for (let i = 0; i < tester.backupList.length; i++) {
|
const item = tester.backupList[i]
|
||||||
const item = tester.backupList[i]
|
if (item.host === ip) {
|
||||||
if (item.host === ip) {
|
if (item.time == null) {
|
||||||
if (item.time == null) {
|
isTestFailedIp = true
|
||||||
isTestFailedIp = true
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isTestFailedIp === false) {
|
}
|
||||||
log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.dnsName}': ${ip}${target} -----`)
|
|
||||||
if (res) {
|
if (!isTestFailedIp) {
|
||||||
res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.dnsName === '预设IP' ? 'PreSet' : dns.dnsName}`)
|
const family = ip.includes(':') ? 6 : 4
|
||||||
}
|
log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.dnsName}': ${ip}${target} -----`)
|
||||||
callback(null, ip, 4)
|
if (res) {
|
||||||
return
|
res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.dnsName === '预设IP' ? 'PreSet' : dns.dnsName}`)
|
||||||
} else {
|
|
||||||
// 使用默认dns
|
|
||||||
log.info(`----- ${action}: ${hostname}, use hostname by default DNS: ${hostname}, skip test failed ip from dns '${dns.dnsName}: ${ip}'${target}, options:`, options)
|
|
||||||
}
|
}
|
||||||
|
callback(null, ip, family)
|
||||||
} else {
|
} else {
|
||||||
// 使用默认dns
|
// 使用默认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)
|
defaultDns.lookup(hostname, options, callback)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,31 @@ class SpeedTester {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFromOneDns (dns) {
|
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 () {
|
async test () {
|
||||||
|
@ -88,6 +112,11 @@ class SpeedTester {
|
||||||
this.backupList = _.unionBy(newBackupList, 'host')
|
this.backupList = _.unionBy(newBackupList, 'host')
|
||||||
this.testCount++
|
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)
|
log.info('[speed]', this.hostname, '➜ ip-list:', this.backupList)
|
||||||
await this.testBackups()
|
await this.testBackups()
|
||||||
if (config.notify) {
|
if (config.notify) {
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
Loading…
Reference in New Issue