diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js
index 4c9e3ec7..9c87c962 100644
--- a/packages/core/src/config/index.js
+++ b/packages/core/src/config/index.js
@@ -24,7 +24,7 @@ module.exports = {
'.*': { proxy: 'raw.fastgit.org' }
},
'github.githubassets.com': {
- '.*': { proxy: 'assets.fastgit.org' }
+ '.*': { proxy: 'assets.fastgit.org', test: 'https://github.githubassets.com/favicons/favicon.svg' }
},
'customer-stories-feed.github.com': {
'.*': { proxy: 'customer-stories-feed.fastgit.org' }
diff --git a/packages/core/src/index.js b/packages/core/src/index.js
index 90f43a5a..5e60f682 100644
--- a/packages/core/src/index.js
+++ b/packages/core/src/index.js
@@ -8,7 +8,7 @@ process.on('uncaughtException', function (err) {
// console.error(err.errno)
return
}
- console.error('uncaughtException',err)
+ console.error('uncaughtException', err)
})
process.on('unhandledRejection', (reason, p) => {
diff --git a/packages/core/src/modules/plugin/node/index.js b/packages/core/src/modules/plugin/node/index.js
index e924c88b..8ec2fa9f 100644
--- a/packages/core/src/modules/plugin/node/index.js
+++ b/packages/core/src/modules/plugin/node/index.js
@@ -137,6 +137,7 @@ const NodePlugin = function (context) {
]
const ret = await shell.exec(cmds, { type: 'cmd' })
event.fire('status', { key: 'plugin.node.enabled', value: false })
+ console.info('关闭【NPM】代理成功')
return ret
}
}
diff --git a/packages/core/src/modules/server/index.js b/packages/core/src/modules/server/index.js
index 653901f3..fbd01490 100644
--- a/packages/core/src/modules/server/index.js
+++ b/packages/core/src/modules/server/index.js
@@ -97,9 +97,9 @@ const serverApi = {
}
})
},
- async restart () {
+ async restart ({ mitmproxyPath }) {
await serverApi.kill()
- await serverApi.start()
+ await serverApi.start({ mitmproxyPath })
},
getServer () {
return server
diff --git a/packages/gui/src/background.js b/packages/gui/src/background.js
index 954fbf55..72739947 100644
--- a/packages/gui/src/background.js
+++ b/packages/gui/src/background.js
@@ -35,7 +35,7 @@ function setTray (app) {
}
]
// 设置系统托盘图标
- const iconPath = path.join(__dirname, '../extra/favicon.ico')
+ const iconPath = path.join(__dirname, '../extra/icons/128x128.png')
const appTray = new Tray(iconPath)
// 图标的上下文菜单
@@ -44,14 +44,25 @@ function setTray (app) {
// 设置托盘悬浮提示
appTray.setToolTip('DevSidecar-开发者边车辅助工具')
- // 设置托盘菜单
- appTray.setContextMenu(contextMenu)
-
// 单击托盘小图标显示应用
appTray.on('click', () => {
// 显示主程序
win.show()
})
+
+ // 设置托盘菜单
+ // appTray.setContextMenu(contextMenu)
+
+ // appTray.on('double-click', function () {
+ // console.log('double click')
+ // win.show()
+ // })
+ appTray.on('right-click', function (event, bounds) {
+ setTimeout(function () {
+ appTray.popUpContextMenu(contextMenu)
+ }, 200)
+ })
+
return appTray
}
diff --git a/packages/gui/src/bridge/index.js b/packages/gui/src/bridge/index.js
index d10aa8ea..236f0cf3 100644
--- a/packages/gui/src/bridge/index.js
+++ b/packages/gui/src/bridge/index.js
@@ -21,6 +21,9 @@ const localApi = {
server: {
start () {
return DevSidecar.api.server.start({ mitmproxyPath })
+ },
+ restart () {
+ return DevSidecar.api.server.restart({ mitmproxyPath })
}
},
config: {
diff --git a/packages/gui/src/view/event.js b/packages/gui/src/view/event.js
index 2eb4cfa0..18763240 100644
--- a/packages/gui/src/view/event.js
+++ b/packages/gui/src/view/event.js
@@ -22,7 +22,7 @@ function register (app) {
}
function handleServerStartError (err, app) {
- if (err.message.indexOf('listen EADDRINUSE') >= 0) {
+ if (err.message && err.message.indexOf('listen EADDRINUSE') >= 0) {
app.$confirm({
title: '端口被占用,代理服务启动失败',
content: '是否要杀掉占用进程?',
diff --git a/packages/gui/src/view/mixins/plugin.js b/packages/gui/src/view/mixins/plugin.js
index a22fbda8..b5597c7d 100644
--- a/packages/gui/src/view/mixins/plugin.js
+++ b/packages/gui/src/view/mixins/plugin.js
@@ -10,7 +10,8 @@ export default {
config: undefined,
status: status,
labelCol: { span: 4 },
- wrapperCol: { span: 20 }
+ wrapperCol: { span: 20 },
+ applyLoading: false
}
},
created () {
@@ -27,12 +28,17 @@ export default {
}
})
},
- apply () {
- return this.saveConfig().then(() => {
- if (this.applyAfter) {
- return this.applyAfter()
- }
- })
+ async apply () {
+ this.applyLoading = true
+ await this.applyBefore()
+ await this.saveConfig()
+ if (this.applyAfter) {
+ await this.applyAfter()
+ }
+ this.applyLoading = false
+ },
+ async applyBefore () {
+
},
reloadDefault (key) {
this.$api.config.resetDefault(key).then(ret => {
diff --git a/packages/gui/src/view/pages/plugin/node.vue b/packages/gui/src/view/pages/plugin/node.vue
index 36017be9..773aed35 100644
--- a/packages/gui/src/view/pages/plugin/node.vue
+++ b/packages/gui/src/view/pages/plugin/node.vue
@@ -59,8 +59,8 @@
@@ -91,13 +91,13 @@ export default {
this.npmVariables = ret
})
},
- onSwitchRegistry (event) {
- return this.setRegistry(event.target.value).then(() => {
- this.$message.success('切换成功')
- })
+ async onSwitchRegistry (event) {
+ await this.setRegistry(event.target.value)
+ this.$message.success('切换成功')
},
- setRegistry (registry) {
- return this.$api.plugin.node.setRegistry(registry)
+ async setRegistry (registry) {
+ this.apply()
+ await this.$api.plugin.node.setRegistry(registry)
},
setNpmVariableAll () {
this.saveConfig().then(() => {
diff --git a/packages/gui/src/view/pages/proxy.vue b/packages/gui/src/view/pages/proxy.vue
index d97f195c..d788a46d 100644
--- a/packages/gui/src/view/pages/proxy.vue
+++ b/packages/gui/src/view/pages/proxy.vue
@@ -21,8 +21,8 @@
diff --git a/packages/gui/src/view/pages/server.vue b/packages/gui/src/view/pages/server.vue
index d4bd27f1..4ff2b689 100644
--- a/packages/gui/src/view/pages/server.vue
+++ b/packages/gui/src/view/pages/server.vue
@@ -69,8 +69,8 @@
@@ -109,8 +109,28 @@ export default {
})
}
},
- applyAfter () {
+ async applyBefore () {
+ const dnsMapping = {}
+ for (const item of this.dnsMappings) {
+ if (item.key) {
+ dnsMapping[item.key] = item.value
+ }
+ }
+ this.config.server.dns.mapping = dnsMapping
+ },
+ async applyAfter () {
+ if (this.status.server.enabled) {
+ return this.$api.server.restart()
+ }
+ },
+ deleteDnsMapping (item, index) {
+ this.dnsMappings.splice(index, 1)
+ },
+ restoreDefDnsMapping (item, index) {
+ },
+ addDnsMapping () {
+ this.dnsMappings.unshift({ key: '', value: 'usa' })
}
}
}
diff --git a/packages/mitmproxy/src/lib/dns/base.js b/packages/mitmproxy/src/lib/dns/base.js
index dc36080f..5a70932c 100644
--- a/packages/mitmproxy/src/lib/dns/base.js
+++ b/packages/mitmproxy/src/lib/dns/base.js
@@ -1,11 +1,72 @@
const LRU = require('lru-cache')
-const { isIP } = require('validator')
+// const { isIP } = require('validator')
const getLogger = require('../utils/logger')
const logger = getLogger('dns')
const cacheSize = 1024
-function _isIP (v) {
- return v && isIP(v)
+// eslint-disable-next-line no-unused-vars
+// function _isIP (v) {
+// return v && isIP(v)
+// }
+
+class IpCache {
+ constructor (hostname) {
+ this.hostname = hostname
+ this.count = {}
+ this.lookupCount = 0
+ this.createTime = new Date()
+ }
+
+ /**
+ * 获取到新的ipList
+ * @param ipList
+ */
+ setIpList (ipList) {
+ this.ip = ipList.shift()
+ this.ipList = ipList
+ this.lookupCount++
+ this.doCount(this.ip, false)
+ }
+
+ /**
+ * 换下一个ip
+ * @param count
+ */
+ changeNext (count) {
+ count.keepErrorCount = 0 // 清空连续失败
+ if (this.ipList > 0) {
+ this.ip = this.ipList.shift()
+ } else {
+ this.ip = null
+ }
+ }
+
+ /**
+ * 记录使用次数或错误次数
+ * @param ip
+ * @param isError
+ */
+ doCount (ip, isError) {
+ let count = this.count[ip]
+ if (count == null) {
+ count = this.count[ip] = { total: 0, error: 0, keepErrorCount: 0, successRate: 0 }
+ }
+ if (isError) {
+ count.error++
+ count.keepErrorCount++
+ } else {
+ count.total++
+ }
+ count.successRate = 1 - (count.error / count.total)
+ if (isError && this.ip === ip) {
+ if (count.keepErrorCount >= 5) {
+ this.changeNext(count)
+ }
+ if (count.successRate < 0.51) {
+ this.changeNext(count)
+ }
+ }
+ }
}
module.exports = class BaseDNS {
@@ -13,30 +74,39 @@ module.exports = class BaseDNS {
this.cache = new LRU(cacheSize)
}
+ count (hostname, ip, isError = true) {
+ const ipCache = this.cache.get(hostname)
+ if (ipCache) {
+ ipCache.doCount(ip, isError)
+ }
+ }
+
async lookup (hostname) {
try {
- let ip = this.cache.get(hostname)
- if (ip) {
- return ip
+ let ipCache = this.cache.get(hostname)
+ if (ipCache) {
+ if (ipCache.ip != null) {
+ ipCache.doCount(ipCache.ip, false)
+ return ipCache.ip
+ }
+ } else {
+ ipCache = new IpCache(hostname)
+ this.cache.set(hostname, ipCache)
}
const t = new Date()
-
- ip = hostname
- for (let depth = 0; !_isIP(ip) && depth < 5; depth++) {
- ip = await this._lookup(ip).catch(error => {
- logger.debug(ip, error)
- return ip
- })
+ let ipList = await this._lookup(hostname)
+ if (ipList == null) {
+ // 没有获取到ipv4地址
+ ipList = []
}
+ ipList.push(hostname) // 把原域名加入到统计里去
- if (!_isIP(ip)) {
- throw new Error(`BAD IP FORMAT (${ip})`)
- }
+ ipCache.setIpList(ipList)
- logger.debug(`[DNS] ${hostname} -> ${ip} (${new Date() - t} ms)`)
- this.cache.set(hostname, ip)
- return ip
+ logger.debug(`[DNS] ${hostname} -> ${ipCache.ip} (${new Date() - t} ms)`)
+
+ return ipCache.ip
} catch (error) {
logger.debug(`[DNS] cannot resolve hostname ${hostname} (${error})`)
return hostname
diff --git a/packages/mitmproxy/src/lib/dns/https.js b/packages/mitmproxy/src/lib/dns/https.js
index a516c080..a827b2d3 100644
--- a/packages/mitmproxy/src/lib/dns/https.js
+++ b/packages/mitmproxy/src/lib/dns/https.js
@@ -12,6 +12,17 @@ module.exports = class DNSOverHTTPS extends BaseDNS {
async _lookup (hostname) {
const result = await dohQueryAsync({ url: this.dnsServer }, [{ type: 'A', name: hostname }])
- return result.answers[0].data
+ if (result.answers.length === 0) {
+ // 说明没有获取到ip
+ console.log('该域名没有ip地址解析', hostname)
+ return []
+ }
+ const ret = result.answers.filter(item => { return item.type === 'A' }).map(item => { return item.data })
+ if (ret.length === 0) {
+ console.log('该域名没有ipv4地址解析', hostname)
+ } else {
+ console.log('获取到域名地址:', hostname, JSON.stringify(ret))
+ }
+ return ret
}
}
diff --git a/packages/mitmproxy/src/lib/dns/index.js b/packages/mitmproxy/src/lib/dns/index.js
index 275aa23c..08bdbec1 100644
--- a/packages/mitmproxy/src/lib/dns/index.js
+++ b/packages/mitmproxy/src/lib/dns/index.js
@@ -23,7 +23,6 @@ module.exports = {
}
}
if (providerName) {
- console.log('匹配到dns:', providerName, hostname)
return dnsConfig.providers[providerName]
}
}
diff --git a/packages/mitmproxy/src/lib/proxy/common/util.js b/packages/mitmproxy/src/lib/proxy/common/util.js
index 41bde449..0e6d9e38 100644
--- a/packages/mitmproxy/src/lib/proxy/common/util.js
+++ b/packages/mitmproxy/src/lib/proxy/common/util.js
@@ -6,13 +6,13 @@ const tunnelAgent = require('tunnel-agent')
const util = exports
const httpsAgent = new HttpsAgent({
keepAlive: true,
- timeout: 5000,
+ timeout: 15000,
keepAliveTimeout: 60000, // free socket keepalive for 30 seconds
rejectUnauthorized: false
})
const httpAgent = new Agent({
keepAlive: true,
- timeout: 5000,
+ timeout: 15000,
keepAliveTimeout: 60000 // free socket keepalive for 30 seconds
})
let socketId = 0
@@ -34,7 +34,7 @@ util.getOptionsFormRequest = (req, ssl, externalProxy = null) => {
try {
externalProxyUrl = externalProxy(req, ssl)
} catch (e) {
- console.error('externalProxy',e)
+ console.error('externalProxy', e)
}
}
}
diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js
index 11f37e29..5f1194c9 100644
--- a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js
+++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js
@@ -21,7 +21,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, fakeServe
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
if (dns) {
dns.lookup(hostname).then(ip => {
- connect(req, cltSocket, head, ip, srvUrl.port)
+ connect(req, cltSocket, head, ip, srvUrl.port, { dns, hostname, ip })
})
}
}
@@ -30,7 +30,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, fakeServe
}
}
-function connect (req, cltSocket, head, hostname, port) {
+function connect (req, cltSocket, head, hostname, port, isDnsIntercept) {
// tunneling https
// console.log('connect:', hostname, port)
const start = new Date().getTime()
@@ -57,6 +57,12 @@ function connect (req, cltSocket, head, hostname, port) {
const end = new Date().getTime()
console.error('代理连接失败:', e.message, hostname, port, (end - start) + 'ms')
cltSocket.destroy()
+
+ if (isDnsIntercept) {
+ const { dns, ip, hostname } = isDnsIntercept
+ dns.count(hostname, ip, true)
+ console.error('记录ip失败次数,用于优选ip:', hostname, ip)
+ }
})
return proxySocket
} catch (error) {
diff --git a/packages/mitmproxy/test/dnsTest.js b/packages/mitmproxy/test/dnsTest.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/packages/mitmproxy/test/dnsTest.mjs b/packages/mitmproxy/test/dnsTest.mjs
new file mode 100644
index 00000000..28b67d60
--- /dev/null
+++ b/packages/mitmproxy/test/dnsTest.mjs
@@ -0,0 +1,23 @@
+import dns from '../src/lib/dns/index.js'
+
+const dnsProviders = dns.initDNS({
+ aliyun: {
+ type: 'https',
+ server: 'https://dns.alidns.com/dns-query',
+ cacheSize: 1000
+ },
+ usa: {
+ type: 'https',
+ server: 'https://cloudflare-dns.com/dns-query',
+ cacheSize: 1000
+ }
+})
+
+// let hostname = 'www.yonsz.com'
+// dnsProviders.usa.lookup(hostname)
+
+// const hostname = 'api.github.com'
+// dnsProviders.usa.lookup(hostname)
+
+const hostname1 = 'api.github.com'
+dnsProviders.aliyun.lookup(hostname1)