feat: speedTest
parent
6bc097fc68
commit
219323a0d6
|
@ -152,11 +152,31 @@ module.exports = {
|
||||||
server: 'https://dns.alidns.com/dns-query',
|
server: 'https://dns.alidns.com/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000
|
||||||
},
|
},
|
||||||
|
ipaddress: {
|
||||||
|
type: 'ipaddress',
|
||||||
|
server: 'ipaddress',
|
||||||
|
cacheSize: 1000
|
||||||
|
},
|
||||||
usa: {
|
usa: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://1.1.1.1/dns-query',
|
server: 'https://1.1.1.1/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000
|
||||||
},
|
},
|
||||||
|
quad9: {
|
||||||
|
type: 'https',
|
||||||
|
server: 'https://9.9.9.9/dns-query',
|
||||||
|
cacheSize: 1000
|
||||||
|
}
|
||||||
|
// google: {
|
||||||
|
// type: 'https',
|
||||||
|
// server: 'https://8.8.8.8/dns-query',
|
||||||
|
// cacheSize: 1000
|
||||||
|
// },
|
||||||
|
// dnsSB: {
|
||||||
|
// type: 'https',
|
||||||
|
// server: 'https://doh.dns.sb/dns-query',
|
||||||
|
// cacheSize: 1000
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
mapping: {
|
mapping: {
|
||||||
// 'assets.fastgit.org': 'usa',
|
// 'assets.fastgit.org': 'usa',
|
||||||
|
@ -167,9 +187,14 @@ module.exports = {
|
||||||
'*.githubusercontent.com': 'usa',
|
'*.githubusercontent.com': 'usa',
|
||||||
'*.githubassets.com': 'usa',
|
'*.githubassets.com': 'usa',
|
||||||
// "解决push的时候需要输入密码的问题",
|
// "解决push的时候需要输入密码的问题",
|
||||||
|
'github.com': 'usa',
|
||||||
'*github.com': 'usa',
|
'*github.com': 'usa',
|
||||||
'*.vuepress.vuejs.org': 'usa',
|
'*.vuepress.vuejs.org': 'usa',
|
||||||
'gh.docmirror.top': 'usa'
|
'gh.docmirror.top': 'usa'
|
||||||
|
},
|
||||||
|
speedTest: {
|
||||||
|
hostnameList: ['github.com'],
|
||||||
|
dnsProviders: ['usa', 'quad9']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: '梯子',
|
name: '梯子',
|
||||||
enabled: false,
|
enabled: false, // 默认关闭梯子
|
||||||
server: {
|
server: {
|
||||||
},
|
},
|
||||||
serverDefault: {
|
serverDefault: {
|
||||||
|
@ -10,7 +10,8 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
targets: {
|
targets: {
|
||||||
'*facebook.com': true
|
'*facebook.com': true,
|
||||||
|
'github.com': true
|
||||||
},
|
},
|
||||||
pac: {
|
pac: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
|
@ -53,7 +53,6 @@ export default {
|
||||||
},
|
},
|
||||||
async created () {
|
async created () {
|
||||||
const platform = await this.$api.info.getSystemPlatform()
|
const platform = await this.$api.info.getSystemPlatform()
|
||||||
console.log('11', platform)
|
|
||||||
this.systemPlatform = platform
|
this.systemPlatform = platform
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -69,6 +69,7 @@
|
||||||
<a-select :disabled="item.value ===false" v-model="item.value">
|
<a-select :disabled="item.value ===false" v-model="item.value">
|
||||||
<a-select-option value="usa">USA DNS</a-select-option>
|
<a-select-option value="usa">USA DNS</a-select-option>
|
||||||
<a-select-option value="aliyun">Aliyun DNS</a-select-option>
|
<a-select-option value="aliyun">Aliyun DNS</a-select-option>
|
||||||
|
<a-select-option value="ipaddress">IpAddress</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="3">
|
<a-col :span="3">
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"agentkeepalive": "^2.1.1",
|
"agentkeepalive": "^2.1.1",
|
||||||
|
"axios": "^0.21.1",
|
||||||
"child_process": "^1.0.2",
|
"child_process": "^1.0.2",
|
||||||
"colors": "^1.1.2",
|
"colors": "^1.1.2",
|
||||||
"commander": "^2.9.0",
|
"commander": "^2.9.0",
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
const DNSOverTLS = require('./tls.js')
|
const DNSOverTLS = require('./tls.js')
|
||||||
const DNSOverHTTPS = require('./https.js')
|
const DNSOverHTTPS = require('./https.js')
|
||||||
|
const DNSOverIpAddress = require('./ipaddress.js')
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initDNS (dnsProviders) {
|
initDNS (dnsProviders) {
|
||||||
const dnsMap = {}
|
const dnsMap = {}
|
||||||
for (const provider in dnsProviders) {
|
for (const provider in dnsProviders) {
|
||||||
const conf = dnsProviders[provider]
|
const conf = dnsProviders[provider]
|
||||||
|
if (conf.type === 'ipaddress') {
|
||||||
|
dnsMap[provider] = new DNSOverIpAddress(conf.server)
|
||||||
|
continue
|
||||||
|
}
|
||||||
dnsMap[provider] = conf.type === 'https' ? new DNSOverHTTPS(conf.server) : new DNSOverTLS(conf.server)
|
dnsMap[provider] = conf.type === 'https' ? new DNSOverHTTPS(conf.server) : new DNSOverTLS(conf.server)
|
||||||
}
|
}
|
||||||
return dnsMap
|
return dnsMap
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
const dnstls = require('dns-over-tls')
|
||||||
|
const BaseDNS = require('./base')
|
||||||
|
const axios = require('axios')
|
||||||
|
const log = require('../../utils/util.log')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
module.exports = class DNSOverIpAddress extends BaseDNS {
|
||||||
|
async _lookup (hostname) {
|
||||||
|
const url = `https://${hostname}.ipaddress.com`
|
||||||
|
|
||||||
|
// const res = fs.readFileSync(path.resolve(__dirname, './data.txt')).toString()
|
||||||
|
const res = await axios.get(url)
|
||||||
|
if (res.status !== 200 && res.status !== 201) {
|
||||||
|
log.info(`[dns] get ${hostname} ipaddress: error:${res}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const ret = res.data
|
||||||
|
|
||||||
|
const regexp = /<tr><th>IP Address<\/th><td><ul class="comma-separated"><li>([^<]*)<\/li><\/ul><\/td><\/tr>/gm
|
||||||
|
const matched = regexp.exec(ret)
|
||||||
|
let ip = null
|
||||||
|
|
||||||
|
if (matched && matched.length >= 1) {
|
||||||
|
ip = matched[1]
|
||||||
|
log.info(`[dns] get ${hostname} ipaddress:${ip}`)
|
||||||
|
return [ip]
|
||||||
|
}
|
||||||
|
log.info(`[dns] get ${hostname} ipaddress: error`)
|
||||||
|
return null
|
||||||
|
|
||||||
|
// const { answers } = await dnstls.query(hostname)
|
||||||
|
//
|
||||||
|
// const answer = answers.find(answer => answer.type === 'A' && answer.class === 'IN')
|
||||||
|
//
|
||||||
|
// log.info('dns lookup:', hostname, answer)
|
||||||
|
// if (answer) {
|
||||||
|
// return answer.data
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,8 @@ module.exports = {
|
||||||
const regexp = new RegExp(interceptOpt.replace)
|
const regexp = new RegExp(interceptOpt.replace)
|
||||||
proxyTarget = req.url.replace(regexp, proxyConf)
|
proxyTarget = req.url.replace(regexp, proxyConf)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line
|
||||||
|
// no-template-curly-in-string
|
||||||
proxyTarget = proxyTarget.replace('${host}', rOptions.hostname)
|
proxyTarget = proxyTarget.replace('${host}', rOptions.hostname)
|
||||||
|
|
||||||
// const backup = interceptOpt.backup
|
// const backup = interceptOpt.backup
|
||||||
|
|
|
@ -48,7 +48,6 @@ function injectScriptIntoHtml (tags, chunk, script) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
console.log('insert script:', tag)
|
|
||||||
const scriptBuf = Buffer.from(script)
|
const scriptBuf = Buffer.from(script)
|
||||||
const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length)
|
const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length)
|
||||||
chunk.copy(chunkNew, 0, 0, index)
|
chunk.copy(chunkNew, 0, 0, index)
|
||||||
|
|
|
@ -6,6 +6,8 @@ const DnsUtil = require('../../dns/index')
|
||||||
const localIP = '127.0.0.1'
|
const localIP = '127.0.0.1'
|
||||||
const defaultDns = require('dns')
|
const defaultDns = require('dns')
|
||||||
|
|
||||||
|
const speedTest = require('../../speed/index.js')
|
||||||
|
|
||||||
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
||||||
for (const intercept of sslConnectInterceptors) {
|
for (const intercept of sslConnectInterceptors) {
|
||||||
const ret = intercept(req, cltSocket, head)
|
const ret = intercept(req, cltSocket, head)
|
||||||
|
@ -32,6 +34,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
||||||
const hostname = srvUrl.hostname
|
const hostname = srvUrl.hostname
|
||||||
if (isSslConnect(sslConnectInterceptors, req, cltSocket, head)) {
|
if (isSslConnect(sslConnectInterceptors, req, cltSocket, head)) {
|
||||||
fakeServerCenter.getServerPromise(hostname, srvUrl.port).then((serverObj) => {
|
fakeServerCenter.getServerPromise(hostname, srvUrl.port).then((serverObj) => {
|
||||||
|
log.info('--- fakeServer connect', hostname)
|
||||||
connect(req, cltSocket, head, localIP, serverObj.port)
|
connect(req, cltSocket, head, localIP, serverObj.port)
|
||||||
}, (e) => {
|
}, (e) => {
|
||||||
log.error('getServerPromise', e)
|
log.error('getServerPromise', e)
|
||||||
|
@ -57,9 +60,19 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig) {
|
||||||
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
||||||
if (dns) {
|
if (dns) {
|
||||||
options.lookup = (hostname, options, callback) => {
|
options.lookup = (hostname, options, callback) => {
|
||||||
|
const tester = speedTest.getSpeedTester(hostname)
|
||||||
|
if (tester) {
|
||||||
|
const ip = tester.pickFastAliveIp()
|
||||||
|
if (ip) {
|
||||||
|
log.info(`-----${hostname} use alive ip:${ip}-----`)
|
||||||
|
callback(null, ip, 4)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
dns.lookup(hostname).then(ip => {
|
dns.lookup(hostname).then(ip => {
|
||||||
isDnsIntercept = { dns, hostname, ip }
|
isDnsIntercept = { dns, hostname, ip }
|
||||||
if (ip !== hostname) {
|
if (ip !== hostname) {
|
||||||
|
log.info(`-----${hostname} use ip:${ip}-----`)
|
||||||
callback(null, ip, 4)
|
callback(null, ip, 4)
|
||||||
} else {
|
} else {
|
||||||
defaultDns.lookup(hostname, options, callback)
|
defaultDns.lookup(hostname, options, callback)
|
||||||
|
|
|
@ -7,7 +7,7 @@ const log = require('../../../utils/util.log')
|
||||||
const RequestCounter = require('../../choice/RequestCounter')
|
const RequestCounter = require('../../choice/RequestCounter')
|
||||||
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
||||||
const OverWallMiddleware = require('../middleware/overwall')
|
const OverWallMiddleware = require('../middleware/overwall')
|
||||||
|
const speedTest = require('../../speed/index.js')
|
||||||
const defaultDns = require('dns')
|
const defaultDns = require('dns')
|
||||||
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
||||||
// create requestHandler function
|
// create requestHandler function
|
||||||
|
@ -106,10 +106,19 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
const dns = DnsUtil.hasDnsLookup(dnsConfig, rOptions.hostname)
|
const dns = DnsUtil.hasDnsLookup(dnsConfig, rOptions.hostname)
|
||||||
if (dns) {
|
if (dns) {
|
||||||
rOptions.lookup = (hostname, options, callback) => {
|
rOptions.lookup = (hostname, options, callback) => {
|
||||||
|
const tester = speedTest.getSpeedTester(hostname)
|
||||||
|
if (tester) {
|
||||||
|
const ip = tester.pickFastAliveIp()
|
||||||
|
if (ip) {
|
||||||
|
log.info(`-----${hostname} use alive ip:${ip}-----`)
|
||||||
|
callback(null, ip, 4)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
dns.lookup(hostname).then(ip => {
|
dns.lookup(hostname).then(ip => {
|
||||||
isDnsIntercept = { dns, hostname, ip }
|
isDnsIntercept = { dns, hostname, ip }
|
||||||
if (ip !== hostname) {
|
if (ip !== hostname) {
|
||||||
log.info(`request url :${url},use ip :${ip}`)
|
log.info(`----request url :${url},use ip :${ip}----`)
|
||||||
callback(null, ip, 4)
|
callback(null, ip, 4)
|
||||||
} else {
|
} else {
|
||||||
log.info(`request url :${url},use hostname :${hostname}`)
|
log.info(`request url :${url},use hostname :${hostname}`)
|
||||||
|
@ -266,7 +275,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
})().catch(e => {
|
})().catch(e => {
|
||||||
if (!res.writableEnded) {
|
if (!res.writableEnded) {
|
||||||
const status = e.status || 500
|
const status = e.status || 500
|
||||||
res.writeHead(status)
|
res.writeHead(status, { 'Content-Type': 'text/html;charset=UTF8' })
|
||||||
res.write(`DevSidecar Warning:\n\n ${e.toString()}`)
|
res.write(`DevSidecar Warning:\n\n ${e.toString()}`)
|
||||||
res.end()
|
res.end()
|
||||||
log.error('request error', e.message)
|
log.error('request error', e.message)
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
const tlsUtils = require('../tls/tlsUtils')
|
const tlsUtils = require('../tls/tlsUtils')
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
|
const https = require('https')
|
||||||
const config = require('../common/config')
|
const config = require('../common/config')
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
const createRequestHandler = require('./createRequestHandler')
|
const createRequestHandler = require('./createRequestHandler')
|
||||||
const createConnectHandler = require('./createConnectHandler')
|
const createConnectHandler = require('./createConnectHandler')
|
||||||
const createFakeServerCenter = require('./createFakeServerCenter')
|
const createFakeServerCenter = require('./createFakeServerCenter')
|
||||||
const createUpgradeHandler = require('./createUpgradeHandler')
|
const createUpgradeHandler = require('./createUpgradeHandler')
|
||||||
|
const DnsUtil = require('../../dns/index')
|
||||||
|
const defaultDns = require('dns')
|
||||||
|
const speedTest = require('../../speed/index.js')
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createProxy ({
|
createProxy ({
|
||||||
port = config.defaultPort,
|
port = config.defaultPort,
|
||||||
|
@ -35,7 +39,40 @@ module.exports = {
|
||||||
log.info(`CA private key saved in: ${caKeyPath}`)
|
log.info(`CA private key saved in: ${caKeyPath}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function lookup (hostname, options, callback) {
|
||||||
|
// const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
||||||
|
// if (dns) {
|
||||||
|
// dns.lookup(hostname).then(ip => {
|
||||||
|
// // isDnsIntercept = { dns, hostname, ip }
|
||||||
|
// if (ip !== hostname) {
|
||||||
|
// log.info(`-----${hostname} use ip:${ip}-----`)
|
||||||
|
// callback(null, ip, 4)
|
||||||
|
// } else {
|
||||||
|
// defaultDns.lookup(hostname, options, callback)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// defaultDns.lookup(hostname, options, callback)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// https.globalAgent.lookup = lookup
|
||||||
|
|
||||||
port = ~~port
|
port = ~~port
|
||||||
|
|
||||||
|
const speedTestConfig = dnsConfig.speedTest
|
||||||
|
const dnsMap = dnsConfig.providers
|
||||||
|
if (speedTestConfig) {
|
||||||
|
const dnsProviders = speedTestConfig.dnsProviders
|
||||||
|
const map = {}
|
||||||
|
for (const dnsProvider of dnsProviders) {
|
||||||
|
if (dnsMap[dnsProvider]) {
|
||||||
|
map[dnsProvider] = dnsMap[dnsProvider]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
speedTest.initSpeedTestPool({ hostnameList: speedTestConfig.hostnameList, dnsMap: map })
|
||||||
|
}
|
||||||
|
|
||||||
const requestHandler = createRequestHandler(
|
const requestHandler = createRequestHandler(
|
||||||
createIntercepts,
|
createIntercepts,
|
||||||
middlewares,
|
middlewares,
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
const net = require('net')
|
||||||
|
const config = require('./config.js')
|
||||||
|
const log = require('../../utils/util.log.js')
|
||||||
|
const DISABLE_TIMEOUT = 60 * 60 * 1000 // 1个小时不访问,取消获取
|
||||||
|
|
||||||
|
class SpeedTester {
|
||||||
|
constructor ({ hostname }) {
|
||||||
|
this.dnsMap = config.getConfig().dnsMap
|
||||||
|
this.hostname = hostname
|
||||||
|
this.lastReadTime = Date.now()
|
||||||
|
this.ready = false
|
||||||
|
this.alive = []
|
||||||
|
this.backupList = []
|
||||||
|
this.keepCheckId = false
|
||||||
|
|
||||||
|
this.loadingIps = false
|
||||||
|
this.loadingTest = false
|
||||||
|
|
||||||
|
this.test()
|
||||||
|
}
|
||||||
|
|
||||||
|
pickFastAliveIp () {
|
||||||
|
this.touch()
|
||||||
|
if (this.alive.length === 0) {
|
||||||
|
this.test()
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return this.alive[0].host
|
||||||
|
}
|
||||||
|
|
||||||
|
touch () {
|
||||||
|
this.lastReadTime = Date.now()
|
||||||
|
if (!this.keepCheckId) {
|
||||||
|
this.startChecker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startChecker () {
|
||||||
|
if (this.keepCheckId) {
|
||||||
|
clearInterval(this.keepCheckId)
|
||||||
|
}
|
||||||
|
this.keepCheckId = setInterval(() => {
|
||||||
|
if (Date.now() - DISABLE_TIMEOUT > this.lastReadTime) {
|
||||||
|
// 超过很长时间没有访问,取消测试
|
||||||
|
clearInterval(this.keepCheckId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.alive.length > 0) {
|
||||||
|
this.testBackups()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.test()
|
||||||
|
}, 60 * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getIpListFromDns (dnsMap) {
|
||||||
|
const ips = {}
|
||||||
|
const promiseList = []
|
||||||
|
for (const key in dnsMap) {
|
||||||
|
const one = this.getFromOneDns(dnsMap[key]).then(ipList => {
|
||||||
|
if (ipList) {
|
||||||
|
for (const ip of ipList) {
|
||||||
|
ips[ip] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
promiseList.push(one)
|
||||||
|
}
|
||||||
|
await Promise.all(promiseList)
|
||||||
|
const items = []
|
||||||
|
for (const ip in ips) {
|
||||||
|
items.push({ host: ip, port: 443 })
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFromOneDns (dns) {
|
||||||
|
return await dns._lookup(this.hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
async test () {
|
||||||
|
this.backupList = await this.getIpListFromDns(this.dnsMap)
|
||||||
|
log.info('[speed]', this.hostname, ' ips:', this.backupList)
|
||||||
|
this.testBackups()
|
||||||
|
}
|
||||||
|
|
||||||
|
async testBackups () {
|
||||||
|
const testAll = []
|
||||||
|
const aliveList = []
|
||||||
|
for (const item of this.backupList) {
|
||||||
|
testAll.push(this.doTest(item, aliveList))
|
||||||
|
}
|
||||||
|
await Promise.all(testAll)
|
||||||
|
this.alive = aliveList
|
||||||
|
this.ready = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async doTest (item, aliveList) {
|
||||||
|
try {
|
||||||
|
const ret = await this.testOne(item)
|
||||||
|
aliveList.push({ ...ret, ...item })
|
||||||
|
aliveList.sort((a, b) => a.time - b.time)
|
||||||
|
} catch (e) {
|
||||||
|
log.error('[speed] test error', this.hostname, item.host, e.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOne (item) {
|
||||||
|
const timeout = 5000
|
||||||
|
const { host, port } = item
|
||||||
|
const startTime = Date.now()
|
||||||
|
let isOver = false
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let timeoutId = null
|
||||||
|
const client = net.createConnection({ host, port }, () => {
|
||||||
|
// 'connect' 监听器
|
||||||
|
const connectionTime = Date.now()
|
||||||
|
isOver = true
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
resolve({ status: 'success', time: connectionTime - startTime })
|
||||||
|
client.end()
|
||||||
|
})
|
||||||
|
client.on('end', () => {
|
||||||
|
})
|
||||||
|
client.on('error', (error) => {
|
||||||
|
log.error('[speed]test error', this.hostname, host, error.message)
|
||||||
|
isOver = true
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
if (isOver) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.error('[speed] test timeout', this.hostname, host)
|
||||||
|
reject(new Error('timeout'))
|
||||||
|
client.end()
|
||||||
|
}, timeout)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SpeedTester
|
|
@ -0,0 +1,8 @@
|
||||||
|
const config = {
|
||||||
|
|
||||||
|
}
|
||||||
|
module.exports = {
|
||||||
|
getConfig () {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
const SpeedTester = require('./SpeedTester.js')
|
||||||
|
const _ = require('lodash')
|
||||||
|
const config = require('./config')
|
||||||
|
|
||||||
|
const SpeedTestPool = {
|
||||||
|
|
||||||
|
}
|
||||||
|
function initSpeedTestPool ({ hostnameList, dnsMap }) {
|
||||||
|
config.getConfig().dnsMap = dnsMap
|
||||||
|
_.forEach(hostnameList, (hostname) => {
|
||||||
|
SpeedTestPool[hostname] = new SpeedTester({ hostname })
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('[speed] dnsMap', dnsMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
SpeedTester,
|
||||||
|
initSpeedTestPool,
|
||||||
|
getSpeedTester (hostname) {
|
||||||
|
let instance = SpeedTestPool[hostname]
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new SpeedTester({ hostname })
|
||||||
|
SpeedTestPool[hostname] = instance
|
||||||
|
}
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,8 @@ module.exports = (config) => {
|
||||||
port: serverConfig.port,
|
port: serverConfig.port,
|
||||||
dnsConfig: {
|
dnsConfig: {
|
||||||
providers: dnsUtil.initDNS(serverConfig.dns.providers),
|
providers: dnsUtil.initDNS(serverConfig.dns.providers),
|
||||||
mapping: dnsMapping
|
mapping: dnsMapping,
|
||||||
|
speedTest: config.dns.speedTest
|
||||||
},
|
},
|
||||||
setting,
|
setting,
|
||||||
middlewares,
|
middlewares,
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
const SpeedTester = require('../src/lib/speed/SpeedTester.js')
|
||||||
|
const SpeedTest = require('../src/lib/speed/index.js')
|
||||||
|
const dns = require('../src/lib/dns/index.js')
|
||||||
|
|
||||||
|
const dnsMap = dns.initDNS({
|
||||||
|
ipaddress: {
|
||||||
|
type: 'ipaddress',
|
||||||
|
server: 'ipaddress',
|
||||||
|
cacheSize: 1000
|
||||||
|
},
|
||||||
|
usa: {
|
||||||
|
type: 'https',
|
||||||
|
server: 'https://1.1.1.1/dns-query',
|
||||||
|
cacheSize: 1000
|
||||||
|
}
|
||||||
|
// google: {
|
||||||
|
// type: 'https',
|
||||||
|
// server: 'https://8.8.8.8/dns-query',
|
||||||
|
// cacheSize: 1000
|
||||||
|
// },
|
||||||
|
// dnsSB: {
|
||||||
|
// type: 'https',
|
||||||
|
// server: 'https://doh.dns.sb/dns-query',
|
||||||
|
// cacheSize: 1000
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
|
||||||
|
SpeedTest.initSpeedTestPool({ hostnameList: {}, dnsMap })
|
||||||
|
|
||||||
|
const tester = new SpeedTester({ hostname: 'github.com' })
|
||||||
|
tester.test().then(ret => {
|
||||||
|
console.log(tester.alive)
|
||||||
|
})
|
|
@ -10,13 +10,34 @@ const dnsProviders = dns.initDNS({
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://1.1.1.1/dns-query',
|
server: 'https://1.1.1.1/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000
|
||||||
|
},
|
||||||
|
ipaddress: {
|
||||||
|
type: 'ipaddress',
|
||||||
|
server: 'ipaddress',
|
||||||
|
cacheSize: 1000
|
||||||
|
},
|
||||||
|
quad9: {
|
||||||
|
type: 'https',
|
||||||
|
server: 'https://9.9.9.9/dns-query',
|
||||||
|
cacheSize: 1000
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// const test = '111<tr><th>IP Address</th><td><ul class="comma-separated"><li>140.82.113.4</li></ul></td></tr>2222'
|
||||||
|
// // <tr><th>IP Address</th><td><ul class="comma-separated"><li>140.82.113.4</li></ul></td></tr>
|
||||||
|
// // <tr><th>IP Address</th><td><ul class="comma-separated"><li>(.*)</li></ul></td></tr>
|
||||||
|
// const regexp = /<tr><th>IP Address<\/th><td><ul class="comma-separated"><li>(.*)<\/li><\/ul><\/td><\/tr>/
|
||||||
|
// const matched = regexp.exec(test)
|
||||||
|
// console.log('data:', matched)
|
||||||
|
|
||||||
const hostname0 = 'github.com'
|
const hostname0 = 'github.com'
|
||||||
dnsProviders.usa.lookup(hostname0)
|
// console.log('first')
|
||||||
dnsProviders.usa.lookup(hostname0)
|
// dnsProviders.usa.lookup(hostname0)
|
||||||
dnsProviders.usa.lookup(hostname0)
|
console.log('test')
|
||||||
|
dnsProviders.quad9.lookup(hostname0)
|
||||||
|
// dnsProviders.usa.lookup(hostname0)
|
||||||
|
// dnsProviders.ipaddress.lookup(hostname0)
|
||||||
|
// dnsProviders.ipaddress.lookup(hostname0)
|
||||||
|
|
||||||
// const hostname = 'api.github.com'
|
// const hostname = 'api.github.com'
|
||||||
// dnsProviders.usa.lookup(hostname)
|
// dnsProviders.usa.lookup(hostname)
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
const https = require('https')
|
const http = require('http')
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
|
||||||
|
},
|
||||||
|
lookup (hostname, options, callback) {
|
||||||
|
const ip = '106.52.191.148'
|
||||||
|
console.log('lookup')
|
||||||
|
callback(null, ip, 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = https.get('https://api.github.com/', options, function (response) {
|
var request = http.get('http://test.target/', options, function (response) {
|
||||||
response.on('data', function (data) {
|
response.on('data', function (data) {
|
||||||
process.stdout.write(data)
|
process.stdout.write(data)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1501,6 +1501,13 @@ aws4@^1.8.0:
|
||||||
resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101166484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101166484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||||
integrity sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=
|
integrity sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=
|
||||||
|
|
||||||
|
axios@^0.21.1:
|
||||||
|
version "0.21.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
|
||||||
|
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.10.0"
|
||||||
|
|
||||||
babel-eslint@^10.1.0:
|
babel-eslint@^10.1.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1599054223324&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
|
resolved "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1599054223324&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
|
||||||
|
@ -2984,6 +2991,11 @@ flush-write-stream@^1.0.0:
|
||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
readable-stream "^2.3.6"
|
readable-stream "^2.3.6"
|
||||||
|
|
||||||
|
follow-redirects@^1.10.0:
|
||||||
|
version "1.13.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
|
||||||
|
integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
|
||||||
|
|
||||||
for-in@^1.0.2:
|
for-in@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
resolved "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||||
|
|
Loading…
Reference in New Issue