Browse Source

feature: 监听 `HTTP` 和 `HTTPS` 的端口分离,为了在 connect 阶段更好的判断协议

pull/375/head
王良 1 month ago
parent
commit
5901a2e5d1
  1. 20
      packages/core/src/shell/scripts/set-system-proxy/index.js
  2. 67
      packages/mitmproxy/src/index.js
  3. 116
      packages/mitmproxy/src/lib/proxy/mitmproxy/index.js

20
packages/core/src/shell/scripts/set-system-proxy/index.js

@ -224,7 +224,7 @@ async function _winSetProxy (exec, ip, port, setEnv) {
let proxyAddr = `https=http://${ip}:${port}` let proxyAddr = `https=http://${ip}:${port}`
// http // http
if (config.get().proxy.proxyHttp) { if (config.get().proxy.proxyHttp) {
proxyAddr = `http=http://${ip}:${port};` + proxyAddr proxyAddr = `http=http://${ip}:${port - 1};` + proxyAddr
} }
// 读取排除域名 // 读取排除域名
@ -234,16 +234,18 @@ async function _winSetProxy (exec, ip, port, setEnv) {
await execFile(proxyPath, [execFun, proxyAddr, excludeIpStr]) await execFile(proxyPath, [execFun, proxyAddr, excludeIpStr])
if (setEnv) { if (setEnv) {
log.info(`开启系统代理的同时设置环境变量:HTTPS_PROXY = "http://${ip}:${port}/"`) // 设置全局代理所需的环境变量
if (config.get().proxy.proxyHttp) {
log.info(`开启系统代理的同时设置环境变量:HTTP_PROXY = "http://${ip}:${port}/"`)
}
try { try {
await exec('echo \'设置环境变量 HTTPS_PROXY、HTTP_PROXY\'') await exec(`echo '设置环境变量 HTTPS_PROXY${config.get().proxy.proxyHttp ? '、HTTP_PROXY' : ''}'`)
log.info(`开启系统代理的同时设置环境变量:HTTPS_PROXY = "http://${ip}:${port}/"`)
await exec(`setx HTTPS_PROXY "http://${ip}:${port}/"`) await exec(`setx HTTPS_PROXY "http://${ip}:${port}/"`)
if (config.get().proxy.proxyHttp) { if (config.get().proxy.proxyHttp) {
await exec(`setx HTTP_PROXY "http://${ip}:${port}/"`) log.info(`开启系统代理的同时设置环境变量:HTTP_PROXY = "http://${ip}:${port - 1}/"`)
await exec(`setx HTTP_PROXY "http://${ip}:${port - 1}/"`)
} }
// await addClearScriptIni() // await addClearScriptIni()
} catch (e) { } catch (e) {
log.error('设置环境变量 HTTPS_PROXY、HTTP_PROXY 失败:', e) log.error('设置环境变量 HTTPS_PROXY、HTTP_PROXY 失败:', e)
@ -279,7 +281,7 @@ const executor = {
// http // http
if (config.get().proxy.proxyHttp) { if (config.get().proxy.proxyHttp) {
setProxyCmd.push(`gsettings set org.gnome.system.proxy.http host ${ip}`) setProxyCmd.push(`gsettings set org.gnome.system.proxy.http host ${ip}`)
setProxyCmd.push(`gsettings set org.gnome.system.proxy.http port ${port}`) setProxyCmd.push(`gsettings set org.gnome.system.proxy.http port ${port - 1}`)
} else { } else {
setProxyCmd.push("gsettings set org.gnome.system.proxy.http host ''") setProxyCmd.push("gsettings set org.gnome.system.proxy.http host ''")
setProxyCmd.push('gsettings set org.gnome.system.proxy.http port 0') setProxyCmd.push('gsettings set org.gnome.system.proxy.http port 0')
@ -311,7 +313,7 @@ const executor = {
await exec(`networksetup -setsecurewebproxy "${wifiAdaptor}" ${ip} ${port}`) await exec(`networksetup -setsecurewebproxy "${wifiAdaptor}" ${ip} ${port}`)
// http // http
if (config.get().proxy.proxyHttp) { if (config.get().proxy.proxyHttp) {
await exec(`networksetup -setwebproxy "${wifiAdaptor}" ${ip} ${port}`) await exec(`networksetup -setwebproxy "${wifiAdaptor}" ${ip} ${port - 1}`)
} else { } else {
await exec(`networksetup -setwebproxystate "${wifiAdaptor}" off`) await exec(`networksetup -setwebproxystate "${wifiAdaptor}" off`)
} }

67
packages/mitmproxy/src/index.js

@ -4,7 +4,7 @@ const proxyConfig = require('./lib/proxy/common/config')
const log = require('./utils/util.log') const log = require('./utils/util.log')
const { fireError, fireStatus } = require('./utils/util.process') const { fireError, fireStatus } = require('./utils/util.process')
const speedTest = require('./lib/speed/index.js') const speedTest = require('./lib/speed/index.js')
let server let servers = []
function registerProcessListener () { function registerProcessListener () {
process.on('message', function (msg) { process.on('message', function (msg) {
@ -64,44 +64,51 @@ const api = {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1' process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'
} }
// log.info('启动代理服务时的配置:', JSON.stringify(proxyOptions, null, '\t')) // log.info('启动代理服务时的配置:', JSON.stringify(proxyOptions, null, '\t'))
const newServer = mitmproxy.createProxy(proxyOptions, () => { const newServers = mitmproxy.createProxy(proxyOptions, (server, port, host, ssl) => {
fireStatus(true) fireStatus(true)
log.info(`代理服务已启动:${proxyOptions.host}:${proxyOptions.port}`) log.info(`代理服务已启动:${host}:${port}, ssl: ${ssl}`)
}) })
newServer.on('close', () => { for (const newServer of newServers) {
log.info('server will closed ') newServer.on('close', () => {
if (server === newServer) { log.info('server will closed ')
server = null if (servers.includes(newServer)) {
fireStatus(false) servers = servers.filter(item => item !== newServer)
} if (servers.length === 0) {
}) fireStatus(false)
newServer.on('error', (e) => { }
log.info('server error', e) }
// newServer = null })
fireError(e) newServer.on('error', (e) => {
}) log.info('server error', e)
server = newServer // newServer = null
fireError(e)
})
}
servers = newServers
registerProcessListener() registerProcessListener()
}, },
async close () { async close () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (server) { if (servers && servers.length > 0) {
server.close((err) => { for (const server of servers) {
if (err && err.code !== 'ERR_SERVER_NOT_RUNNING') { server.close((err) => {
if (err.code === 'ERR_SERVER_NOT_RUNNING') { if (err && err.code !== 'ERR_SERVER_NOT_RUNNING') {
log.info('代理服务未运行,无需关闭') if (err.code === 'ERR_SERVER_NOT_RUNNING') {
resolve() log.info('代理服务未运行,无需关闭')
} else { resolve()
log.error('代理服务关闭失败:', err) } else {
reject(err) log.error('代理服务关闭失败:', err)
reject(err)
}
return
} }
return
}
log.info('代理服务关闭成功') log.info('代理服务关闭成功')
resolve() resolve()
}) })
}
servers = []
} else { } else {
log.info('server is null, no need to close.') log.info('server is null, no need to close.')
fireStatus(false) fireStatus(false)

116
packages/mitmproxy/src/lib/proxy/mitmproxy/index.js

@ -20,7 +20,8 @@ module.exports = {
middlewares = [], middlewares = [],
externalProxy, externalProxy,
dnsConfig, dnsConfig,
setting setting,
compatibleConfig
}, callback) { }, callback) {
// Don't reject unauthorized // Don't reject unauthorized
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' // process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
@ -57,7 +58,8 @@ module.exports = {
middlewares, middlewares,
externalProxy, externalProxy,
dnsConfig, dnsConfig,
setting setting,
compatibleConfig
) )
const upgradeHandler = createUpgradeHandler(setting) const upgradeHandler = createUpgradeHandler(setting)
@ -75,65 +77,75 @@ module.exports = {
sslConnectInterceptor, sslConnectInterceptor,
middlewares, middlewares,
fakeServersCenter, fakeServersCenter,
dnsConfig dnsConfig,
compatibleConfig
) )
const server = new http.Server() // 创建监听方法,用于监听 http 和 https 两个端口
server.listen(port, host, () => { const serverListen = (server, ssl, port, host) => {
log.info(`dev-sidecar启动端口: ${host}:${port}`) server.listen(port, host, () => {
server.on('request', (req, res) => { log.info(`dev-sidecar启动 ${ssl ? 'https' : 'http'} 端口: ${host}:${port}`)
const ssl = false server.on('request', (req, res) => {
log.debug('【server request】\r\n----- req -----\r\n', req, '\r\n----- res -----\r\n', res) log.debug(`【server request, ssl: ${ssl}\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
requestHandler(req, res, ssl) requestHandler(req, res, ssl)
})
// tunneling for https
server.on('connect', (req, cltSocket, head) => {
log.debug('【server connect】\r\n----- req -----\r\n', req, '\r\n----- cltSocket -----\r\n', cltSocket, '\r\n----- head -----\r\n', head)
connectHandler(req, cltSocket, head)
})
// TODO: handler WebSocket
server.on('upgrade', function (req, cltSocket, head) {
const ssl = false
log.debug('【server upgrade】\r\n----- req -----\r\n', req)
upgradeHandler(req, cltSocket, head, ssl)
})
server.on('error', (err) => {
log.error('【server error】\r\n----- error -----\r\n', err)
})
server.on('clientError', (err, cltSocket) => {
// log.error('【server clientError】\r\n----- error -----\r\n', err, '\r\n----- cltSocket -----\r\n', cltSocket)
log.error('【server clientError】\r\n', err)
cltSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n')
})
// 其他事件:仅记录debug日志
if (process.env.NODE_ENV === 'development') {
server.on('close', () => {
log.debug('【server close】no arguments...')
}) })
server.on('connection', (cltSocket) => { // tunneling for https
log.debug('【server connection】\r\n----- cltSocket -----\r\n', cltSocket) server.on('connect', (req, cltSocket, head) => {
log.debug(`【server connect, ssl: ${ssl}\r\n----- req -----\r\n`, req, '\r\n----- cltSocket -----\r\n', cltSocket, '\r\n----- head -----\r\n', head)
connectHandler(req, cltSocket, head, ssl)
}) })
server.on('listening', () => { // TODO: handler WebSocket
log.debug('【server listening】no arguments...') server.on('upgrade', function (req, cltSocket, head) {
log.debug(`【server upgrade, ssl: ${ssl}\r\n----- req -----\r\n`, req)
upgradeHandler(req, cltSocket, head, ssl)
}) })
server.on('checkContinue', (req, res) => { server.on('error', (err) => {
log.debug('【server checkContinue】\r\n----- req -----\r\n', req, '\r\n----- res -----\r\n', res) log.error(`【server error, ssl: ${ssl}\r\n----- error -----\r\n`, err)
}) })
server.on('checkExpectation', (req, res) => { server.on('clientError', (err, cltSocket) => {
log.debug('【server checkExpectation】\r\n----- req -----\r\n', req, '\r\n----- res -----\r\n', res) // log.error(`【server clientError, ssl: ${ssl}】\r\n----- error -----\r\n`, err, '\r\n----- cltSocket -----\r\n', cltSocket)
log.error(`【server clientError, ssl: ${ssl}】socket.localPort = ${cltSocket.localPort}\r\n`, err)
cltSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n')
}) })
server.on('dropRequest', (req, cltSocket) => {
log.debug('【server checkExpectation】\r\n----- req -----\r\n', req, '\r\n----- cltSocket -----\r\n', cltSocket)
})
}
if (callback) { // 其他事件:仅记录debug日志
callback(server) if (process.env.NODE_ENV === 'development') {
} server.on('close', () => {
}) log.debug(`【server close, ssl: ${ssl}】no arguments...`)
})
server.on('connection', (cltSocket) => {
log.debug(`【server connection, ssl: ${ssl}\r\n----- cltSocket -----\r\n`, cltSocket)
})
server.on('listening', () => {
log.debug(`【server listening, ssl: ${ssl}】no arguments...`)
})
server.on('checkContinue', (req, res) => {
log.debug(`【server checkContinue, ssl: ${ssl}\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
})
server.on('checkExpectation', (req, res) => {
log.debug(`【server checkExpectation, ssl: ${ssl}\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
})
server.on('dropRequest', (req, cltSocket) => {
log.debug(`【server checkExpectation, ssl: ${ssl}\r\n----- req -----\r\n`, req, '\r\n----- cltSocket -----\r\n', cltSocket)
})
}
if (callback) {
callback(server, port, host, ssl)
}
})
}
const httpsServer = new http.Server()
const httpServer = new http.Server()
// `http端口` 比 `https端口` 要小1
const httpsPort = port
const httpPort = port - 1
serverListen(httpsServer, true, httpsPort, host)
serverListen(httpServer, false, httpPort, host)
return server return [httpsServer, httpServer]
}, },
createCA (caPaths) { createCA (caPaths) {
return tlsUtils.initCA(caPaths) return tlsUtils.initCA(caPaths)

Loading…
Cancel
Save