refactor: 修复关闭代理失败的bug
parent
a392b4c54d
commit
750e444af2
|
@ -22,7 +22,7 @@
|
||||||
等你来提issue
|
等你来提issue
|
||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
目前仅支持windows
|
||||||
### 1、安装与启动
|
### 1、安装与启动
|
||||||
```shell
|
```shell
|
||||||
git clone https://gitee.com/docmirror/dev-sidecar.git
|
git clone https://gitee.com/docmirror/dev-sidecar.git
|
||||||
|
|
|
@ -80,6 +80,12 @@ module.exports = {
|
||||||
'downloads.openwrt.org': { '.*': { proxy: 'openwrt.proxy.ustclug.org' } },
|
'downloads.openwrt.org': { '.*': { proxy: 'openwrt.proxy.ustclug.org' } },
|
||||||
'secure.gravatar.com': { '.*': { proxy: 'gravatar.proxy.ustclug.org' } }
|
'secure.gravatar.com': { '.*': { proxy: 'gravatar.proxy.ustclug.org' } }
|
||||||
},
|
},
|
||||||
|
whiteList: {
|
||||||
|
'alipay.com': true,
|
||||||
|
'*.alipay.com': true,
|
||||||
|
'pay.weixin.qq.com': true,
|
||||||
|
'www.baidu.com': true
|
||||||
|
},
|
||||||
dns: {
|
dns: {
|
||||||
providers: {
|
providers: {
|
||||||
aliyun: {
|
aliyun: {
|
||||||
|
|
|
@ -87,7 +87,9 @@ module.exports = {
|
||||||
plugins.push(close())
|
plugins.push(close())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Promise.all(plugins)
|
if (plugins.length > 0) {
|
||||||
|
await Promise.all(plugins)
|
||||||
|
}
|
||||||
|
|
||||||
if (status.proxy.enabled) {
|
if (status.proxy.enabled) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -20,7 +20,7 @@ const ProxyPlugin = function (context) {
|
||||||
|
|
||||||
async unsetProxy () {
|
async unsetProxy () {
|
||||||
try {
|
try {
|
||||||
shell.setSystemProxy()
|
await shell.setSystemProxy()
|
||||||
event.fire('status', { key: 'proxy.enabled', vlaue: false })
|
event.fire('status', { key: 'proxy.enabled', vlaue: false })
|
||||||
console.log('关闭系统代理成功')
|
console.log('关闭系统代理成功')
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -52,7 +52,6 @@ const serverApi = {
|
||||||
serverProcess.send({ type: 'action', event: { key: 'close' } })
|
serverProcess.send({ type: 'action', event: { key: 'close' } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('fork return pid: ' + serverProcess.pid)
|
|
||||||
serverProcess.on('message', function (msg) {
|
serverProcess.on('message', function (msg) {
|
||||||
console.log('收到子进程消息', msg)
|
console.log('收到子进程消息', msg)
|
||||||
if (msg.type === 'status') {
|
if (msg.type === 'status') {
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
const interceptors = require('../../../lib/interceptor')
|
|
||||||
const dnsUtil = require('../../../lib/dns')
|
|
||||||
const lodash = require('lodash')
|
|
||||||
function matchHostname (intercepts, hostname) {
|
|
||||||
const interceptOpts = intercepts[hostname]
|
|
||||||
if (interceptOpts) {
|
|
||||||
return interceptOpts
|
|
||||||
}
|
|
||||||
if (!interceptOpts) {
|
|
||||||
for (const target in intercepts) {
|
|
||||||
if (target.indexOf('*') < 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 正则表达式匹配
|
|
||||||
if (hostname.match(target)) {
|
|
||||||
return intercepts[target]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isMatched (url, regexp) {
|
|
||||||
return url.match(regexp)
|
|
||||||
}
|
|
||||||
|
|
||||||
function domainRegexply (target) {
|
|
||||||
return target.replace(/\./g, '\\.').replace(/\*/g, '.*')
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = (config) => {
|
|
||||||
const regexpIntercepts = {}
|
|
||||||
lodash.each(config.intercepts, (value, domain) => {
|
|
||||||
if (domain.indexOf('*') >= 0) {
|
|
||||||
const regDomain = domainRegexply(domain)
|
|
||||||
regexpIntercepts[regDomain] = value
|
|
||||||
} else {
|
|
||||||
regexpIntercepts[domain] = value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const intercepts = regexpIntercepts
|
|
||||||
const dnsMapping = config.dns.mapping
|
|
||||||
const serverConfig = config
|
|
||||||
|
|
||||||
return {
|
|
||||||
port: serverConfig.port,
|
|
||||||
dnsConfig: {
|
|
||||||
providers: dnsUtil.initDNS(serverConfig.dns.providers),
|
|
||||||
mapping: dnsMapping
|
|
||||||
},
|
|
||||||
sslConnectInterceptor: (req, cltSocket, head) => {
|
|
||||||
const hostname = req.url.split(':')[0]
|
|
||||||
return !!matchHostname(intercepts, hostname) // 配置了拦截的域名,将会被代理
|
|
||||||
},
|
|
||||||
requestInterceptor: (rOptions, req, res, ssl, next) => {
|
|
||||||
const hostname = rOptions.hostname
|
|
||||||
const interceptOpts = matchHostname(intercepts, hostname)
|
|
||||||
if (!interceptOpts) { // 该域名没有配置拦截器,直接过
|
|
||||||
next()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const regexp in interceptOpts) { // 遍历拦截配置
|
|
||||||
const interceptOpt = interceptOpts[regexp]
|
|
||||||
if (regexp !== true) {
|
|
||||||
if (!isMatched(req.url, regexp)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const interceptImpl of interceptors) {
|
|
||||||
// 根据拦截配置挑选合适的拦截器来处理
|
|
||||||
if (!interceptImpl.is(interceptOpt) && interceptImpl.requestInterceptor) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = interceptImpl.requestInterceptor(interceptOpt, rOptions, req, res, ssl)
|
|
||||||
if (result) { // 拦截成功,其他拦截器就不处理了
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// 拦截失败
|
|
||||||
console.error('拦截处理失败',err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next()
|
|
||||||
},
|
|
||||||
responseInterceptor: (req, res, proxyReq, proxyRes, ssl, next) => {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
const mitmproxy = require('../../../lib/proxy')
|
|
||||||
const ProxyOptions = require('./options')
|
|
||||||
|
|
||||||
function fireError (e) {
|
|
||||||
process.send({ type: 'error', event: e })
|
|
||||||
}
|
|
||||||
function fireStatus (status) {
|
|
||||||
process.send({ type: 'status', event: status })
|
|
||||||
}
|
|
||||||
|
|
||||||
let server
|
|
||||||
function start () {
|
|
||||||
const config = JSON.parse(process.argv[2])
|
|
||||||
const proxyOptions = ProxyOptions(config)
|
|
||||||
const newServer = mitmproxy.createProxy(proxyOptions, () => {
|
|
||||||
fireStatus(true)
|
|
||||||
console.log('代理服务已启动:127.0.0.1:' + proxyOptions.port)
|
|
||||||
})
|
|
||||||
newServer.on('close', () => {
|
|
||||||
if (server === newServer) {
|
|
||||||
server = null
|
|
||||||
fireStatus(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
newServer.on('error', (e) => {
|
|
||||||
console.log('server error', e)
|
|
||||||
// newServer = null
|
|
||||||
fireError(e)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const api = {
|
|
||||||
async close () {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (server) {
|
|
||||||
server.close((err) => {
|
|
||||||
if (err) {
|
|
||||||
console.log('close error', err, ',', err.code, ',', err.message, ',', err.errno)
|
|
||||||
if (err.code === 'ERR_SERVER_NOT_RUNNING') {
|
|
||||||
console.log('代理服务关闭成功')
|
|
||||||
resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
reject(err)
|
|
||||||
} else {
|
|
||||||
console.log('代理服务关闭成功')
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.log('server is null')
|
|
||||||
fireStatus(false)
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
process.on('message', function (msg) {
|
|
||||||
console.log('child get msg: ' + JSON.stringify(msg))
|
|
||||||
if (msg.type === 'action') {
|
|
||||||
api[msg.event.key](msg.event.params)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 启动服务
|
|
||||||
start()
|
|
|
@ -42,8 +42,9 @@ async function _winUnsetProxy (exec) {
|
||||||
_winAsyncRegSet(regKey, 'ProxyEnable', Registry.REG_DWORD, 0),
|
_winAsyncRegSet(regKey, 'ProxyEnable', Registry.REG_DWORD, 0),
|
||||||
_winAsyncRegSet(regKey, 'ProxyServer', Registry.REG_SZ, '')
|
_winAsyncRegSet(regKey, 'ProxyServer', Registry.REG_SZ, '')
|
||||||
])
|
])
|
||||||
|
console.log('代理关闭成功,等待refresh')
|
||||||
await exec([refreshInternetPs], { type: 'ps' })
|
await exec(refreshInternetPs, { type: 'ps' })
|
||||||
|
console.log('代理关闭refresh完成')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ async function _winSetProxy (exec, ip, port) {
|
||||||
_winAsyncRegSet(regKey, 'ProxyOverride', Registry.REG_SZ, lanIpStr)
|
_winAsyncRegSet(regKey, 'ProxyOverride', Registry.REG_SZ, lanIpStr)
|
||||||
])
|
])
|
||||||
console.log('代理设置成功,等待refresh')
|
console.log('代理设置成功,等待refresh')
|
||||||
await exec([refreshInternetPs])
|
await exec(refreshInternetPs)
|
||||||
console.log('代理设置refresh完成')
|
console.log('代理设置refresh完成')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class WindowsSystemShell extends SystemShell {
|
||||||
static async exec (cmds, args = { }) {
|
static async exec (cmds, args = { }) {
|
||||||
let { type } = args
|
let { type } = args
|
||||||
type = type || 'ps'
|
type = type || 'ps'
|
||||||
if (cmds instanceof String) {
|
if (typeof cmds === 'string') {
|
||||||
cmds = [cmds]
|
cmds = [cmds]
|
||||||
}
|
}
|
||||||
if (type === 'ps') {
|
if (type === 'ps') {
|
||||||
|
|
|
@ -30,7 +30,7 @@ function registerProcessListener () {
|
||||||
// console.error(err.errno)
|
// console.error(err.errno)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.error(err)
|
console.error('uncaughtException:', err)
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('unhandledRejection', (reason, p) => {
|
process.on('unhandledRejection', (reason, p) => {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
const interceptors = require('./lib/interceptor')
|
const interceptors = require('./lib/interceptor')
|
||||||
const dnsUtil = require('./lib/dns')
|
const dnsUtil = require('./lib/dns')
|
||||||
const lodash = require('lodash')
|
const lodash = require('lodash')
|
||||||
function matchHostname (intercepts, hostname) {
|
function matchHostname (hostMap, hostname) {
|
||||||
const interceptOpts = intercepts[hostname]
|
const value = hostMap[hostname]
|
||||||
if (interceptOpts) {
|
if (value) {
|
||||||
return interceptOpts
|
return value
|
||||||
}
|
}
|
||||||
if (!interceptOpts) {
|
if (!value) {
|
||||||
for (const target in intercepts) {
|
for (const target in hostMap) {
|
||||||
if (target.indexOf('*') < 0) {
|
if (target.indexOf('*') < 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 正则表达式匹配
|
// 正则表达式匹配
|
||||||
if (hostname.match(target)) {
|
if (hostname.match(target)) {
|
||||||
return intercepts[target]
|
return hostMap[target]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,18 +27,23 @@ function domainRegexply (target) {
|
||||||
return target.replace(/\./g, '\\.').replace(/\*/g, '.*')
|
return target.replace(/\./g, '\\.').replace(/\*/g, '.*')
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (config) => {
|
function domainMapRegexply (hostMap) {
|
||||||
const regexpIntercepts = {}
|
const regexpMap = {}
|
||||||
lodash.each(config.intercepts, (value, domain) => {
|
lodash.each(hostMap, (value, domain) => {
|
||||||
if (domain.indexOf('*') >= 0) {
|
if (domain.indexOf('*') >= 0) {
|
||||||
const regDomain = domainRegexply(domain)
|
const regDomain = domainRegexply(domain)
|
||||||
regexpIntercepts[regDomain] = value
|
regexpMap[regDomain] = value
|
||||||
} else {
|
} else {
|
||||||
regexpIntercepts[domain] = value
|
regexpMap[domain] = value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return regexpMap
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = (config) => {
|
||||||
|
const intercepts = domainMapRegexply(config.intercepts)
|
||||||
|
const whiteList = domainMapRegexply(config.whiteList)
|
||||||
|
|
||||||
const intercepts = regexpIntercepts
|
|
||||||
const dnsMapping = config.dns.mapping
|
const dnsMapping = config.dns.mapping
|
||||||
const serverConfig = config
|
const serverConfig = config
|
||||||
|
|
||||||
|
@ -50,6 +55,11 @@ module.exports = (config) => {
|
||||||
},
|
},
|
||||||
sslConnectInterceptor: (req, cltSocket, head) => {
|
sslConnectInterceptor: (req, cltSocket, head) => {
|
||||||
const hostname = req.url.split(':')[0]
|
const hostname = req.url.split(':')[0]
|
||||||
|
const inWhiteList = matchHostname(whiteList, hostname) != null
|
||||||
|
if (inWhiteList) {
|
||||||
|
console.log('白名单域名,不拦截', hostname)
|
||||||
|
return false
|
||||||
|
}
|
||||||
return !!matchHostname(intercepts, hostname) // 配置了拦截的域名,将会被代理
|
return !!matchHostname(intercepts, hostname) // 配置了拦截的域名,将会被代理
|
||||||
},
|
},
|
||||||
requestInterceptor: (rOptions, req, res, ssl, next) => {
|
requestInterceptor: (rOptions, req, res, ssl, next) => {
|
||||||
|
|
Loading…
Reference in New Issue