diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 83927706..8e13a4a2 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -179,6 +179,9 @@ module.exports = { 'pay.weixin.qq.com': true, 'www.baidu.com': true }, + // sniList: { + // 'github.com': 'abaidu.com' + // }, dns: { providers: { aliyun: { @@ -219,7 +222,7 @@ module.exports = { }, speedTest: { enabled: true, - interval: 60000, + interval: 160000, hostnameList: ['github.com'], dnsProviders: ['usa', 'quad9', 'rubyfish'] } diff --git a/packages/core/src/shell/scripts/set-system-proxy/index.js b/packages/core/src/shell/scripts/set-system-proxy/index.js index b09b3020..d593877f 100644 --- a/packages/core/src/shell/scripts/set-system-proxy/index.js +++ b/packages/core/src/shell/scripts/set-system-proxy/index.js @@ -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 diff --git a/packages/core/src/shell/scripts/setup-ca.js b/packages/core/src/shell/scripts/setup-ca.js index b283d6ca..4af30f42 100644 --- a/packages/core/src/shell/scripts/setup-ca.js +++ b/packages/core/src/shell/scripts/setup-ca.js @@ -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 }) { diff --git a/packages/core/src/shell/shell.js b/packages/core/src/shell/shell.js index 73037337..80699c7d 100644 --- a/packages/core/src/shell/shell.js +++ b/packages/core/src/shell/shell.js @@ -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': diff --git a/packages/core/start/mitmproxy.js b/packages/core/start/mitmproxy.js index d284a370..bbbb823d 100644 --- a/packages/core/start/mitmproxy.js +++ b/packages/core/start/mitmproxy.js @@ -2,7 +2,7 @@ const server = require('@docmirror/mitmproxy') const JSON5 = require('json5') const path = require('path') -const home = process.env.HOME +const home = process.env.USER_HOME || process.env.HOME || 'C:/Users/xiaoj/' let configPath = path.join(home, '.dev-sidecar/running.json') if (process.argv && process.argv.length > 3) { configPath = process.argv[2] @@ -11,9 +11,9 @@ if (process.argv && process.argv.length > 3) { const fs = require('fs') const configJson = fs.readFileSync(configPath) const config = JSON5.parse(configJson) -const scriptDir = '../../gui/extra/scripts/' -config.setting.script.defaultDir = path.join(__dirname, scriptDir) -const pacFilePath = '../../gui/extra/pac/pac.txt' -config.plugin.overwall.pac.customPacFilePath = path.join(__dirname, pacFilePath) - +// const scriptDir = '../../gui/extra/scripts/' +// config.setting.script.defaultDir = path.join(__dirname, scriptDir) +// const pacFilePath = '../../gui/extra/pac/pac.txt' +// config.plugin.overwall.pac.customPacFilePath = path.join(__dirname, pacFilePath) +config.setting.rootDir = path.join(__dirname, '../../gui/') server.start(config) diff --git a/packages/core/start/user_config.json5 b/packages/core/start/user_config.json5 index 0d7f5def..b745d13c 100644 --- a/packages/core/start/user_config.json5 +++ b/packages/core/start/user_config.json5 @@ -1,24 +1,31 @@ { - server: { - intercepts: { - 'github1.githubassets.com': { - '.*': { - redirect: 'assets.fastgit.org', - test: 'https://github.githubassets.com/favicons/favicon.svg', - desc: '静态资源加速' - } - }, - 'github.githubassets.com': null, - 'notify3.note.youdao.com': { - '/pushserver3/.*': { - abort: true - }, - } + app: { + autoStart: { + enabled: true, }, + mode: 'safe', }, plugin: { node: { - enabled: true - } - } -} + setting: { + yarnRegistry: null, + }, + }, + git: { + enabled: true, + }, + overwall: { + targets: { + '*yonsz.net': true, + '*bootstrapcdn.com': true, + '*cloudflare.com': true, + 'help.yonsz.net': true, + }, + }, + }, + server: { + intercept: { + enabled: false, + }, + }, +} \ No newline at end of file diff --git a/packages/core/yarn.lock b/packages/core/yarn.lock index ea6eb7c6..5c88eb2e 100644 --- a/packages/core/yarn.lock +++ b/packages/core/yarn.lock @@ -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" diff --git a/packages/gui/package.json b/packages/gui/package.json index 131f3a14..13c7636f 100644 --- a/packages/gui/package.json +++ b/packages/gui/package.json @@ -79,4 +79,4 @@ ], "__npminstall_done": false, "gitHead": "3566cd6d33cbe782d91e408d6f174dd826b2790f" -} +} \ No newline at end of file diff --git a/packages/gui/public/setup-linux.png b/packages/gui/public/setup-linux.png new file mode 100755 index 00000000..64d49ed7 Binary files /dev/null and b/packages/gui/public/setup-linux.png differ diff --git a/packages/gui/src/background.js b/packages/gui/src/background.js index 0c7411bb..20871792 100644 --- a/packages/gui/src/background.js +++ b/packages/gui/src/background.js @@ -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() } }) } diff --git a/packages/gui/src/view/components/setup-ca.vue b/packages/gui/src/view/components/setup-ca.vue index 282f3845..a379fbf9 100644 --- a/packages/gui/src/view/components/setup-ca.vue +++ b/packages/gui/src/view/components/setup-ca.vue @@ -21,13 +21,16 @@ 2、然后按如下图步骤将随机生成的根证书设置为始终信任 3、可能需要重新启动应用和浏览器才能生效 + + 1、点击右上角“点此去安装按钮”,将自动安装到系统证书库中 + 2、火狐、chrome等浏览器不走系统证书,需要手动安装(下图以chrome为例安装根证书) + 1、点击右上角“点此去安装按钮”,打开证书 2、然后按如下图步骤将根证书添加到信任的根证书颁发机构 - @@ -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('根证书已成功安装到系统证书库(注意:浏览器仍然需要手动安装)') + } } } } diff --git a/packages/gui/src/view/pages/server.vue b/packages/gui/src/view/pages/server.vue index f8877163..287338d1 100644 --- a/packages/gui/src/view/pages/server.vue +++ b/packages/gui/src/view/pages/server.vue @@ -80,11 +80,9 @@ - - 这里配置哪些域名需要通过国外DNS服务器获取IP进行访问 @@ -110,10 +108,31 @@ @click="restoreDefDnsMapping(item,index)"> - - + + + + + + + + + + + + + + + + + + + + + + + @@ -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/') diff --git a/packages/gui/yarn.lock b/packages/gui/yarn.lock index 711b89fa..67400b4a 100644 --- a/packages/gui/yarn.lock +++ b/packages/gui/yarn.lock @@ -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: diff --git a/packages/mitmproxy/src/index.js b/packages/mitmproxy/src/index.js index aede43e9..010c9393 100644 --- a/packages/mitmproxy/src/index.js +++ b/packages/mitmproxy/src/index.js @@ -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 = { diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js index 53598371..671eb122 100644 --- a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js +++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js @@ -5,9 +5,9 @@ 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') - +const sniExtract = require('../tls/sniUtil.js') function isSslConnect (sslConnectInterceptors, req, cltSocket, head) { for (const intercept of sslConnectInterceptors) { const ret = intercept(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,16 +43,18 @@ 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) try { const options = { port, @@ -90,6 +95,33 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig) { proxySocket.pipe(cltSocket) cltSocket.pipe(proxySocket) + // let sniReplaced = false + // cltSocket.on('data', (chunk) => { + // // if (replaceSni && sniReplaced === false) { + // // const sniPackage = sniExtract(chunk) + // // if (sniPackage != null) { + // // sniReplaced = true + // // const bytes = Buffer.from(replaceSni) + // // const start = sniPackage.start + // // const length = sniPackage.length + // // for (let i = 0; i < length; i++) { + // // let char = 97 // a 的ascii + // // if (bytes.length > i) { + // // char = bytes[i] + // // } + // // chunk[start + i] = char + // // } + // // } + // // } + // if (sniReplaced === false) { + // sniReplaced = true + // chunk[chunk.length - 1] = 1 + // } + // proxySocket.write(chunk) + // }) + // cltSocket.on('end', () => { + // proxySocket.end() + // }) }) cltSocket.on('error', (e) => { diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/index.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/index.js index 0edb114d..933cfe08 100644 --- a/packages/mitmproxy/src/lib/proxy/mitmproxy/index.js +++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/index.js @@ -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() diff --git a/packages/mitmproxy/src/lib/proxy/tls/sniUtil.js b/packages/mitmproxy/src/lib/proxy/tls/sniUtil.js new file mode 100644 index 00000000..88269b49 --- /dev/null +++ b/packages/mitmproxy/src/lib/proxy/tls/sniUtil.js @@ -0,0 +1,169 @@ +module.exports = function extractSNI (data) { + /* + From https://tools.ietf.org/html/rfc5246: + enum { + hello_request(0), client_hello(1), server_hello(2), + certificate(11), server_key_exchange (12), + certificate_request(13), server_hello_done(14), + certificate_verify(15), client_key_exchange(16), + finished(20) + (255) + } HandshakeType; + struct { + HandshakeType msg_type; + uint24 length; + select (HandshakeType) { + case hello_request: HelloRequest; + case client_hello: ClientHello; + case server_hello: ServerHello; + case certificate: Certificate; + case server_key_exchange: ServerKeyExchange; + case certificate_request: CertificateRequest; + case server_hello_done: ServerHelloDone; + case certificate_verify: CertificateVerify; + case client_key_exchange: ClientKeyExchange; + case finished: Finished; + } body; + } Handshake; + struct { + uint8 major; + uint8 minor; + } ProtocolVersion; + struct { + uint32 gmt_unix_time; + opaque random_bytes[28]; + } Random; + opaque SessionID<0..32>; + uint8 CipherSuite[2]; + enum { null(0), (255) } CompressionMethod; + struct { + ProtocolVersion client_version; + Random random; + SessionID session_id; + CipherSuite cipher_suites<2..2^16-2>; + CompressionMethod compression_methods<1..2^8-1>; + select (extensions_present) { + case false: + struct {}; + case true: + Extension extensions<0..2^16-1>; + }; + } ClientHello; + */ + + var end = data.length + + // skip the record header + var pos = 5 + + // skip HandshakeType (you should already have verified this) + pos += 1 + + // skip handshake length + pos += 3 + + // skip protocol version (you should already have verified this) + pos += 2 + + // skip Random + pos += 32 + + // skip SessionID + if (pos > end - 1) return null + var sessionIdLength = data[pos] + pos += 1 + sessionIdLength + + // skip CipherSuite + if (pos > end - 2) return null + var cipherSuiteLength = data[pos] << 8 | data[pos + 1] + pos += 2 + cipherSuiteLength + + // skip CompressionMethod + if (pos > end - 1) return null + var compressionMethodLength = data[pos] + pos += 1 + compressionMethodLength + + // verify extensions exist + if (pos > end - 2) return null + var extensionsLength = data[pos] << 8 | data[pos + 1] + pos += 2 + + // verify the extensions fit + var extensionsEnd = pos + extensionsLength + if (extensionsEnd > end) return null + end = extensionsEnd + + /* + From https://tools.ietf.org/html/rfc5246 + and http://tools.ietf.org/html/rfc6066: + struct { + ExtensionType extension_type; + opaque extension_data<0..2^16-1>; + } Extension; + enum { + signature_algorithms(13), (65535) + } ExtensionType; + enum { + server_name(0), max_fragment_length(1), + client_certificate_url(2), trusted_ca_keys(3), + truncated_hmac(4), status_request(5), (65535) + } ExtensionType; + struct { + NameType name_type; + select (name_type) { + case host_name: HostName; + } name; + } ServerName; + enum { + host_name(0), (255) + } NameType; + opaque HostName<1..2^16-1>; + struct { + ServerName server_name_list<1..2^16-1> + } ServerNameList; + */ + + while (pos <= end - 4) { + var extensionType = data[pos] << 8 | data[pos + 1] + var extensionSize = data[pos + 2] << 8 | data[pos + 3] + pos += 4 + if (extensionType === 0) { // ExtensionType was server_name(0) + // read ServerNameList length + if (pos > end - 2) return null + var nameListLength = data[pos] << 8 | data[pos + 1] + pos += 2 + + // verify we have enough bytes and loop over SeverNameList + var n = pos + pos += nameListLength + if (pos > end) return null + while (n < pos - 3) { + var nameType = data[n] + var nameLength = data[n + 1] << 8 | data[n + 2] + n += 3 + + // check if NameType is host_name(0) + if (nameType === 0) { + // verify we have enough bytes + if (n > end - nameLength) return null + + // decode as ascii and return + + const sniName = data.toString('ascii', n, n + nameLength) + return { + sniName, + start: n, + end: n + nameLength, + length: nameLength + } + } else { + n += nameLength + } + } + } else { // ExtensionType was something we are not interested in + pos += extensionSize + } + } + + return null +} diff --git a/packages/mitmproxy/src/lib/proxy/tls/tlsUtils.js b/packages/mitmproxy/src/lib/proxy/tls/tlsUtils.js index 2d43ff2e..d0b42ede 100644 --- a/packages/mitmproxy/src/lib/proxy/tls/tlsUtils.js +++ b/packages/mitmproxy/src/lib/proxy/tls/tlsUtils.js @@ -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: [{ diff --git a/packages/mitmproxy/src/options.js b/packages/mitmproxy/src/options.js index 8721ab59..7dcfd171 100644 --- a/packages/mitmproxy/src/options.js +++ b/packages/mitmproxy/src/options.js @@ -13,10 +13,14 @@ module.exports = (config) => { const serverConfig = config const setting = serverConfig.setting - setting.script.dirAbsolutePath = path.join(setting.rootDir, setting.script.defaultDir) + if (!setting.script.dirAbsolutePath) { + setting.script.dirAbsolutePath = path.join(setting.rootDir, setting.script.defaultDir) + } const overwallConfig = serverConfig.plugin.overwall - overwallConfig.pac.pacFileAbsolutePath = path.join(setting.rootDir, overwallConfig.pac.pacFilePath) + if (!overwallConfig.pac.pacFileAbsolutePath) { + overwallConfig.pac.pacFileAbsolutePath = path.join(setting.rootDir, overwallConfig.pac.pacFilePath) + } const overwallMiddleware = createOverwallMiddleware(overwallConfig) const middlewares = [] if (overwallMiddleware) { @@ -30,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] diff --git a/packages/mitmproxy/src/utils/util.match.js b/packages/mitmproxy/src/utils/util.match.js index 0d4807ae..eaaed087 100644 --- a/packages/mitmproxy/src/utils/util.match.js +++ b/packages/mitmproxy/src/utils/util.match.js @@ -24,6 +24,9 @@ function domainMapRegexply (hostMap) { } function matchHostname (hostMap, hostname) { + if (hostMap == null) { + return null + } const value = hostMap[hostname] if (value) { return value