diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 3d9114b1..26baaac9 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -157,9 +157,9 @@ module.exports = { 'pay.weixin.qq.com': true, 'www.baidu.com': true }, - sniList: { - 'github.com': 'baidu.com' - }, + // sniList: { + // 'github.com': 'abaidu.com' + // }, dns: { providers: { aliyun: { 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/gui/src/view/pages/server.vue b/packages/gui/src/view/pages/server.vue index faa94808..287338d1 100644 --- a/packages/gui/src/view/pages/server.vue +++ b/packages/gui/src/view/pages/server.vue @@ -110,28 +110,28 @@ - - - -
这里配置哪些域名要修改sni
-
- - - -
- - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + -
+
diff --git a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js index 514c61a2..671eb122 100644 --- a/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js +++ b/packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js @@ -7,7 +7,7 @@ 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) @@ -55,16 +55,11 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig, sniRegexpMap) 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, - servername + connectTimeout: 10000 } if (dnsConfig) { const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname) @@ -100,6 +95,33 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig, sniRegexpMap) 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/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/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