Merge remote-tracking branch 'origin/master'
commit
a0812d4bbf
|
@ -157,6 +157,9 @@ module.exports = {
|
|||
'pay.weixin.qq.com': true,
|
||||
'www.baidu.com': true
|
||||
},
|
||||
sniList: {
|
||||
'github.com': 'baidu.com'
|
||||
},
|
||||
dns: {
|
||||
providers: {
|
||||
aliyun: {
|
||||
|
|
|
@ -122,7 +122,26 @@ const executor = {
|
|||
}
|
||||
},
|
||||
async linux (exec, params) {
|
||||
throw Error('暂未实现此功能')
|
||||
if (params != null) {
|
||||
const { ip, port } = params
|
||||
// const local = 'localhost, 127.0.0.0/8, ::1'
|
||||
|
||||
const setProxyCmd = [
|
||||
'gsettings set org.gnome.system.proxy mode manual',
|
||||
`gsettings set org.gnome.system.proxy.https port ${port}`,
|
||||
`gsettings set org.gnome.system.proxy.https host ${ip}`,
|
||||
`gsettings set org.gnome.system.proxy.http port ${port}`,
|
||||
`gsettings set org.gnome.system.proxy.http host ${ip}`
|
||||
// `gsettings set org.gnome.system.proxy ignore-hosts "${local}"`
|
||||
]
|
||||
|
||||
await exec(setProxyCmd)
|
||||
} else {
|
||||
const setProxyCmd = [
|
||||
'gsettings set org.gnome.system.proxy mode none'
|
||||
]
|
||||
await exec(setProxyCmd)
|
||||
}
|
||||
},
|
||||
async mac (exec, params) {
|
||||
// exec = _exec
|
||||
|
|
|
@ -8,9 +8,9 @@ const executor = {
|
|||
return true
|
||||
},
|
||||
async linux (exec, { certPath }) {
|
||||
const cmds = ['open "' + certPath + '"']
|
||||
const cmds = [`sudo cp ${certPath} /usr/local/share/ca-certificates`, 'sudo update-ca-certificates ']
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds, { type: 'cmd' })
|
||||
const ret = await exec(cmds)
|
||||
return true
|
||||
},
|
||||
async mac (exec, { certPath }) {
|
||||
|
|
|
@ -21,7 +21,7 @@ class LinuxSystemShell extends SystemShell {
|
|||
cmds = [cmds]
|
||||
}
|
||||
for (const cmd of cmds) {
|
||||
await childExec(cmd)
|
||||
await _childExec(cmd, { shell: '/bin/bash' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class DarwinSystemShell extends SystemShell {
|
|||
}
|
||||
let ret
|
||||
for (const cmd of cmds) {
|
||||
ret = await childExec(cmd)
|
||||
ret = await _childExec(cmd)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
@ -76,13 +76,31 @@ class WindowsSystemShell extends SystemShell {
|
|||
}
|
||||
}
|
||||
|
||||
function _childExec (composeCmds, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const childProcess = require('child_process')
|
||||
log.info('shell:', composeCmds)
|
||||
childProcess.exec(composeCmds, options, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
log.error('cmd 命令执行错误:', composeCmds, stderr)
|
||||
reject(new Error(stderr))
|
||||
} else {
|
||||
// log.info('cmd 命令完成:', stdout)
|
||||
resolve(stdout)
|
||||
}
|
||||
// log.info('关闭 cmd')
|
||||
// ps.kill('SIGINT')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function childExec (composeCmds) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
var encoding = 'cp936'
|
||||
var binaryEncoding = 'binary'
|
||||
|
||||
const childProcess = require('child_process')
|
||||
log.info('shell:', composeCmds)
|
||||
childProcess.exec(composeCmds, { encoding: binaryEncoding }, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
// console.log('------', decoder.decode(stderr))
|
||||
|
@ -120,6 +138,7 @@ function getSystemPlatform () {
|
|||
case 'linux':
|
||||
return 'linux'
|
||||
case 'win32':
|
||||
return 'windows'
|
||||
case 'win64':
|
||||
return 'windows'
|
||||
case 'unknown os':
|
||||
|
|
|
@ -93,10 +93,10 @@
|
|||
lodash "^4.17.19"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@docmirror/mitmproxy@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.npmjs.org/@docmirror/mitmproxy/-/mitmproxy-1.5.0.tgz#16b9a956542a56f9889cd0c69c08a33d06d77ab8"
|
||||
integrity sha512-H17TAqKmvzCMSTO6VGTC6kKQskjk1gEJZYsU2ijziZU0XEC96ObG0TWOnsdKh2PhmwDLwxS9cUyb1hpYilLreQ==
|
||||
"@docmirror/mitmproxy@^1.5.1":
|
||||
version "1.5.1"
|
||||
resolved "https://registry.nlark.com/@docmirror/mitmproxy/download/@docmirror/mitmproxy-1.5.1.tgz#357142a41b89266491c3519a7528b9b83dc30c85"
|
||||
integrity sha1-NXFCpBuJJmSRw1GadSi5uD3DDIU=
|
||||
dependencies:
|
||||
agentkeepalive "^2.1.1"
|
||||
axios "^0.21.1"
|
||||
|
|
|
@ -79,4 +79,4 @@
|
|||
],
|
||||
"__npminstall_done": false,
|
||||
"gitHead": "3566cd6d33cbe782d91e408d6f174dd826b2790f"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 212 KiB |
|
@ -75,6 +75,21 @@ function setTray (app) {
|
|||
return appTray
|
||||
}
|
||||
|
||||
function isLinux () {
|
||||
const platform = DevSidecar.api.shell.getSystemPlatform()
|
||||
return platform === 'linux'
|
||||
}
|
||||
|
||||
function hideWin () {
|
||||
if (win) {
|
||||
if (isLinux()) {
|
||||
win.minimize()
|
||||
} else {
|
||||
win.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
|
||||
|
@ -113,7 +128,7 @@ function createWindow () {
|
|||
}
|
||||
|
||||
if (startHideWindow) {
|
||||
win.hide()
|
||||
hideWin()
|
||||
}
|
||||
|
||||
win.on('closed', async (e) => {
|
||||
|
@ -124,7 +139,7 @@ function createWindow () {
|
|||
win.on('close', (e) => {
|
||||
if (!forceClose) {
|
||||
e.preventDefault()
|
||||
win.hide()
|
||||
hideWin()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -21,13 +21,16 @@
|
|||
2、然后按如下图步骤将随机生成的根证书设置为始终信任<br/>
|
||||
3、可能需要重新启动应用和浏览器才能生效<br/>
|
||||
</template>
|
||||
<template v-else-if="this.systemPlatform === 'linux'">
|
||||
1、点击右上角“点此去安装按钮”,将自动安装到系统证书库中<br/>
|
||||
2、火狐、chrome等浏览器不走系统证书,需要手动安装(下图以chrome为例安装根证书)<br/>
|
||||
</template>
|
||||
<template v-else>
|
||||
1、点击右上角“点此去安装按钮”,打开证书<br/>
|
||||
2、然后按如下图步骤将根证书添加到<b>信任的根证书颁发机构</b><br/>
|
||||
</template>
|
||||
</div>
|
||||
<img width="100%" :src="setupImage" />
|
||||
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
|
@ -59,6 +62,8 @@ export default {
|
|||
setupImage () {
|
||||
if (this.systemPlatform === 'mac') {
|
||||
return '/setup-mac.png'
|
||||
} else if (this.systemPlatform === 'linux') {
|
||||
return '/setup-linux.png'
|
||||
} else {
|
||||
return '/setup.png'
|
||||
}
|
||||
|
@ -75,6 +80,9 @@ export default {
|
|||
},
|
||||
async doSetup () {
|
||||
this.$emit('setup')
|
||||
if (this.systemPlatform === 'linux') {
|
||||
this.$message.success('根证书已成功安装到系统证书库(注意:浏览器仍然需要手动安装)')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,11 +80,9 @@
|
|||
<a-button v-if="item.value!==false" type="danger" icon="minus" @click="deleteWhiteList(item,index)"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="DNS设置" key="4">
|
||||
<div>
|
||||
|
||||
<a-row style="margin-top:10px">
|
||||
<a-col span="19">
|
||||
<div>这里配置哪些域名需要通过国外DNS服务器获取IP进行访问</div>
|
||||
|
@ -110,10 +108,31 @@
|
|||
@click="restoreDefDnsMapping(item,index)"></a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="IP测速" key="5">
|
||||
<a-tab-pane tab="SNI" key="5">
|
||||
<a-row style="margin-top:10px">
|
||||
<a-col span="19">
|
||||
<div>这里配置哪些域名要修改sni</div>
|
||||
</a-col>
|
||||
<a-col span="3">
|
||||
<a-button style="margin-left:8px" type="primary" icon="plus" @click="addSniList()"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" style="margin-top: 10px" v-for="(item,index) of sniList" :key='index'>
|
||||
<a-col :span="14">
|
||||
<a-input v-model="item.key"></a-input>
|
||||
</a-col>
|
||||
<a-col :span="5">
|
||||
<a-input v-model="item.value"></a-input>
|
||||
</a-col>
|
||||
<a-col :span="3">
|
||||
<a-button type="danger" icon="minus" @click="deleteSniList(item,index)"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="IP测速" key="6">
|
||||
<div>
|
||||
<a-alert type="info" message="对从dns获取到的ip进行测速,使用速度最快的ip进行访问。(对使用增强功能的域名没啥用)"></a-alert>
|
||||
<a-form-item label="开启dns测速" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
|
@ -207,7 +226,8 @@ export default {
|
|||
wrapperCol: { span: 20 },
|
||||
dnsMappings: [],
|
||||
speedTestList: [],
|
||||
whiteList: []
|
||||
whiteList: [],
|
||||
sniList: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
@ -249,6 +269,7 @@ export default {
|
|||
ready () {
|
||||
this.initDnsMapping()
|
||||
this.initWhiteList()
|
||||
this.initSniList()
|
||||
if (this.config.server.dns.speedTest.dnsProviders) {
|
||||
this.speedDns = this.config.server.dns.speedTest.dnsProviders
|
||||
}
|
||||
|
@ -256,6 +277,7 @@ export default {
|
|||
async applyBefore () {
|
||||
this.submitDnsMapping()
|
||||
this.submitWhiteList()
|
||||
this.submitSniList()
|
||||
},
|
||||
async applyAfter () {
|
||||
if (this.status.server.enabled) {
|
||||
|
@ -320,6 +342,35 @@ export default {
|
|||
this.whiteList.unshift({ key: '', value: true })
|
||||
},
|
||||
|
||||
// sniList
|
||||
initSniList () {
|
||||
this.sniList = []
|
||||
for (const key in this.config.server.sniList) {
|
||||
const value = this.config.server.sniList[key]
|
||||
this.sniList.push({
|
||||
key, value
|
||||
})
|
||||
}
|
||||
},
|
||||
submitSniList () {
|
||||
const sniList = {}
|
||||
for (const item of this.sniList) {
|
||||
if (item.key) {
|
||||
sniList[item.key] = item.value
|
||||
}
|
||||
}
|
||||
this.config.server.sniList = sniList
|
||||
},
|
||||
deleteSniList (item, index) {
|
||||
this.sniList.splice(index, 1)
|
||||
},
|
||||
restoreDefSniList (item, index) {
|
||||
|
||||
},
|
||||
addSniList () {
|
||||
this.sniList.unshift({ key: '', value: true })
|
||||
},
|
||||
|
||||
async openLog () {
|
||||
const dir = await this.$api.info.getConfigDir()
|
||||
this.$api.ipc.openPath(dir + '/logs/')
|
||||
|
|
|
@ -1507,10 +1507,10 @@
|
|||
resolved "https://registry.npm.taobao.org/@types/node/download/@types/node-14.11.8.tgz"
|
||||
integrity sha1-/iAS8jVeTOCLykSus6u7Ic+I0z8=
|
||||
|
||||
"@types/node@^12.0.12":
|
||||
version "12.20.6"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.20.6.tgz"
|
||||
integrity sha512-sRVq8d+ApGslmkE9e3i+D3gFGk7aZHAT+G4cIpIEdLJYPsWiSPwcAnJEjddLQQDqV3Ra2jOclX/Sv6YrvGYiWA==
|
||||
"@types/node@^14.6.2":
|
||||
version "14.17.9"
|
||||
resolved "https://registry.nlark.com/@types/node/download/@types/node-14.17.9.tgz?cache=0&sync_timestamp=1628719497956&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-14.17.9.tgz#b97c057e6138adb7b720df2bd0264b03c9f504fd"
|
||||
integrity sha1-uXwFfmE4rbe3IN8r0CZLA8n1BP0=
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.0"
|
||||
|
@ -4651,13 +4651,13 @@ electron-updater@^4.3.5:
|
|||
lodash.isequal "^4.5.0"
|
||||
semver "^7.3.2"
|
||||
|
||||
electron@10.4.2:
|
||||
version "10.4.2"
|
||||
resolved "https://registry.nlark.com/electron/download/electron-10.4.2.tgz?cache=0&sync_timestamp=1620442447118&other_urls=https%3A%2F%2Fregistry.nlark.com%2Felectron%2Fdownload%2Felectron-10.4.2.tgz#2322a72f1e653e023250be91f3dd8d27662e3805"
|
||||
integrity sha1-IyKnLx5lPgIyUL6R892NJ2YuOAU=
|
||||
electron@^13.1.9:
|
||||
version "13.1.9"
|
||||
resolved "https://registry.nlark.com/electron/download/electron-13.1.9.tgz#668e2632b81e9fa21edfd32876282d3e2ff7fd76"
|
||||
integrity sha1-Zo4mMrgen6Ie39ModigtPi/3/XY=
|
||||
dependencies:
|
||||
"@electron/get" "^1.0.1"
|
||||
"@types/node" "^12.0.12"
|
||||
"@types/node" "^14.6.2"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
elliptic@^6.5.3:
|
||||
|
|
|
@ -34,6 +34,10 @@ function registerProcessListener () {
|
|||
log.info('Unhandled Rejection at: Promise', p, 'err:', err)
|
||||
// application specific logging, throwing an error, or other logic here
|
||||
})
|
||||
|
||||
process.on('exit', function (code) {
|
||||
log.info('代理服务进程被关闭:', code)
|
||||
})
|
||||
}
|
||||
|
||||
const api = {
|
||||
|
|
|
@ -5,7 +5,7 @@ const log = require('../../../utils/util.log')
|
|||
const DnsUtil = require('../../dns/index')
|
||||
const localIP = '127.0.0.1'
|
||||
const defaultDns = require('dns')
|
||||
|
||||
const matchUtil = require('../../../utils/util.match')
|
||||
const speedTest = require('../../speed/index.js')
|
||||
|
||||
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
||||
|
@ -19,7 +19,7 @@ function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
|||
}
|
||||
|
||||
// create connectHandler function
|
||||
module.exports = function createConnectHandler (sslConnectInterceptor, middlewares, fakeServerCenter, dnsConfig) {
|
||||
module.exports = function createConnectHandler (sslConnectInterceptor, middlewares, fakeServerCenter, dnsConfig, sniConfig) {
|
||||
// return
|
||||
const sslConnectInterceptors = []
|
||||
sslConnectInterceptors.push(sslConnectInterceptor)
|
||||
|
@ -28,6 +28,9 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
|||
sslConnectInterceptors.push(middleware.sslConnectInterceptor)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('sni config', sniConfig)
|
||||
const sniRegexpMap = matchUtil.domainMapRegexply(sniConfig)
|
||||
return function connectHandler (req, cltSocket, head) {
|
||||
// eslint-disable-next-line node/no-deprecated-api
|
||||
const srvUrl = url.parse(`https://${req.url}`)
|
||||
|
@ -40,21 +43,28 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
|||
log.error('getServerPromise', e)
|
||||
})
|
||||
} else {
|
||||
connect(req, cltSocket, head, hostname, srvUrl.port, dnsConfig)
|
||||
connect(req, cltSocket, head, hostname, srvUrl.port, dnsConfig, sniRegexpMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function connect (req, cltSocket, head, hostname, port, dnsConfig) {
|
||||
function connect (req, cltSocket, head, hostname, port, dnsConfig, sniRegexpMap) {
|
||||
// tunneling https
|
||||
// log.info('connect:', hostname, port)
|
||||
const start = new Date().getTime()
|
||||
let isDnsIntercept = null
|
||||
const replaceSni = matchUtil.matchHostname(sniRegexpMap, hostname)
|
||||
console.log('replaceSni', replaceSni, sniRegexpMap)
|
||||
let servername = null
|
||||
if (replaceSni) {
|
||||
servername = replaceSni
|
||||
}
|
||||
try {
|
||||
const options = {
|
||||
port,
|
||||
host: hostname,
|
||||
connectTimeout: 10000
|
||||
connectTimeout: 10000,
|
||||
servername
|
||||
}
|
||||
if (dnsConfig) {
|
||||
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
||||
|
|
|
@ -21,7 +21,8 @@ module.exports = {
|
|||
middlewares = [],
|
||||
externalProxy,
|
||||
dnsConfig,
|
||||
setting
|
||||
setting,
|
||||
sniConfig
|
||||
}, callback) {
|
||||
// Don't reject unauthorized
|
||||
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
||||
|
@ -39,25 +40,6 @@ module.exports = {
|
|||
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
|
||||
|
||||
const speedTestConfig = dnsConfig.speedTest
|
||||
|
@ -95,7 +77,8 @@ module.exports = {
|
|||
sslConnectInterceptor,
|
||||
middlewares,
|
||||
fakeServersCenter,
|
||||
dnsConfig
|
||||
dnsConfig,
|
||||
sniConfig
|
||||
)
|
||||
|
||||
const server = new http.Server()
|
||||
|
|
|
@ -51,11 +51,13 @@ utils.createCA = function (CN) {
|
|||
name: 'basicConstraints',
|
||||
critical: true,
|
||||
cA: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'keyUsage',
|
||||
critical: true,
|
||||
keyCertSign: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'subjectKeyIdentifier'
|
||||
}])
|
||||
|
||||
|
@ -111,19 +113,19 @@ utils.createFakeCertificateByDomain = function (caKey, caCert, domain) {
|
|||
critical: true,
|
||||
cA: false
|
||||
},
|
||||
{
|
||||
name: 'keyUsage',
|
||||
critical: true,
|
||||
digitalSignature: true,
|
||||
contentCommitment: true,
|
||||
keyEncipherment: true,
|
||||
dataEncipherment: true,
|
||||
keyAgreement: true,
|
||||
keyCertSign: true,
|
||||
cRLSign: true,
|
||||
encipherOnly: true,
|
||||
decipherOnly: true
|
||||
},
|
||||
// {
|
||||
// name: 'keyUsage',
|
||||
// critical: true,
|
||||
// digitalSignature: true,
|
||||
// contentCommitment: true,
|
||||
// keyEncipherment: true,
|
||||
// dataEncipherment: true,
|
||||
// keyAgreement: true,
|
||||
// keyCertSign: true,
|
||||
// cRLSign: true,
|
||||
// encipherOnly: true,
|
||||
// decipherOnly: true
|
||||
// },
|
||||
{
|
||||
name: 'subjectAltName',
|
||||
altNames: [{
|
||||
|
|
|
@ -34,6 +34,7 @@ module.exports = (config) => {
|
|||
speedTest: config.dns.speedTest
|
||||
},
|
||||
setting,
|
||||
sniConfig: serverConfig.sniList,
|
||||
middlewares,
|
||||
sslConnectInterceptor: (req, cltSocket, head) => {
|
||||
const hostname = req.url.split(':')[0]
|
||||
|
|
Loading…
Reference in New Issue