代码格式调整:packages/mitmproxy/**/*.js
parent
48132c39b0
commit
3e586bfd9b
|
@ -1,13 +1,14 @@
|
||||||
const mitmproxy = require('./lib/proxy')
|
const mitmproxy = require('./lib/proxy')
|
||||||
const ProxyOptions = require('./options')
|
|
||||||
const proxyConfig = require('./lib/proxy/common/config')
|
const proxyConfig = require('./lib/proxy/common/config')
|
||||||
|
const speedTest = require('./lib/speed/index.js')
|
||||||
|
const ProxyOptions = require('./options')
|
||||||
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')
|
|
||||||
let servers = []
|
let servers = []
|
||||||
|
|
||||||
function registerProcessListener () {
|
function registerProcessListener () {
|
||||||
process.on('message', function (msg) {
|
process.on('message', (msg) => {
|
||||||
log.info('child get msg:', JSON.stringify(msg))
|
log.info('child get msg:', JSON.stringify(msg))
|
||||||
if (msg.type === 'action') {
|
if (msg.type === 'action') {
|
||||||
api[msg.event.key](msg.event.params)
|
api[msg.event.key](msg.event.params)
|
||||||
|
@ -22,7 +23,7 @@ function registerProcessListener () {
|
||||||
})
|
})
|
||||||
|
|
||||||
// 避免异常崩溃
|
// 避免异常崩溃
|
||||||
process.on('uncaughtException', function (err) {
|
process.on('uncaughtException', (err) => {
|
||||||
if (err.code === 'ECONNABORTED') {
|
if (err.code === 'ECONNABORTED') {
|
||||||
// log.error(err.errno)
|
// log.error(err.errno)
|
||||||
return
|
return
|
||||||
|
@ -37,7 +38,7 @@ function registerProcessListener () {
|
||||||
process.on('uncaughtExceptionMonitor', (err, origin) => {
|
process.on('uncaughtExceptionMonitor', (err, origin) => {
|
||||||
log.info('Process uncaughtExceptionMonitor:', err, origin)
|
log.info('Process uncaughtExceptionMonitor:', err, origin)
|
||||||
})
|
})
|
||||||
process.on('exit', function (code, signal) {
|
process.on('exit', (code, signal) => {
|
||||||
log.info('代理服务进程被关闭:', code, signal)
|
log.info('代理服务进程被关闭:', code, signal)
|
||||||
})
|
})
|
||||||
process.on('beforeExit', (code, signal) => {
|
process.on('beforeExit', (code, signal) => {
|
||||||
|
@ -115,12 +116,12 @@ const api = {
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...api,
|
...api,
|
||||||
config: proxyConfig,
|
config: proxyConfig,
|
||||||
log,
|
log,
|
||||||
speedTest
|
speedTest,
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,5 @@ module.exports = {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const LRU = require('lru-cache')
|
const LRU = require('lru-cache')
|
||||||
const cacheSize = 1024
|
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
|
|
||||||
|
const cacheSize = 1024
|
||||||
|
|
||||||
class ChoiceCache {
|
class ChoiceCache {
|
||||||
constructor () {
|
constructor () {
|
||||||
this.cache = new LRU(cacheSize)
|
this.cache = new LRU(cacheSize)
|
||||||
|
@ -126,5 +128,5 @@ class DynamicChoice {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
DynamicChoice,
|
DynamicChoice,
|
||||||
ChoiceCache
|
ChoiceCache,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
const LRU = require('lru-cache')
|
const LRU = require('lru-cache')
|
||||||
// const { isIP } = require('validator')
|
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
const { DynamicChoice } = require('../choice/index')
|
const { DynamicChoice } = require('../choice/index')
|
||||||
|
|
||||||
const cacheSize = 1024
|
const cacheSize = 1024
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
// function _isIP (v) {
|
|
||||||
// return v && isIP(v)
|
|
||||||
// }
|
|
||||||
|
|
||||||
class IpCache extends DynamicChoice {
|
class IpCache extends DynamicChoice {
|
||||||
constructor (hostname) {
|
constructor (hostname) {
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
const { promisify } = require('util')
|
const { promisify } = require('util')
|
||||||
const doh = require('dns-over-http')
|
const doh = require('dns-over-http')
|
||||||
const BaseDNS = require('./base')
|
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
const dohQueryAsync = promisify(doh.query)
|
|
||||||
const matchUtil = require('../../utils/util.match')
|
const matchUtil = require('../../utils/util.match')
|
||||||
|
const BaseDNS = require('./base')
|
||||||
|
|
||||||
|
const dohQueryAsync = promisify(doh.query)
|
||||||
|
|
||||||
function mapToList (ipMap) {
|
function mapToList (ipMap) {
|
||||||
const ipList = []
|
const ipList = []
|
||||||
for (const key in ipMap) {
|
for (const key in ipMap) {
|
||||||
if (!ipMap[key]) continue
|
if (!ipMap[key]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ipList.push(ipMap[key])
|
ipList.push(ipMap[key])
|
||||||
}
|
}
|
||||||
return ipList
|
return ipList
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const DNSOverTLS = require('./tls.js')
|
const matchUtil = require('../../utils/util.match')
|
||||||
const DNSOverHTTPS = require('./https.js')
|
const DNSOverHTTPS = require('./https.js')
|
||||||
const DNSOverIpAddress = require('./ipaddress.js')
|
const DNSOverIpAddress = require('./ipaddress.js')
|
||||||
const DNSOverPreSetIpList = require('./preset.js')
|
const DNSOverPreSetIpList = require('./preset.js')
|
||||||
const matchUtil = require('../../utils/util.match')
|
const DNSOverTLS = require('./tls.js')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initDNS (dnsProviders, preSetIpList) {
|
initDNS (dnsProviders, preSetIpList) {
|
||||||
|
@ -50,5 +50,5 @@ module.exports = {
|
||||||
if (providerName) {
|
if (providerName) {
|
||||||
return dnsConfig.dnsMap[providerName]
|
return dnsConfig.dnsMap[providerName]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const BaseDNS = require('./base')
|
|
||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
|
const BaseDNS = require('./base')
|
||||||
|
|
||||||
module.exports = class DNSOverIpAddress extends BaseDNS {
|
module.exports = class DNSOverIpAddress extends BaseDNS {
|
||||||
async _lookup (hostname) {
|
async _lookup (hostname) {
|
||||||
const url = `https://${hostname}.ipaddress.com`
|
const url = `https://${hostname}.ipaddress.com`
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
lookup () {
|
lookup () {
|
||||||
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
const BaseDNS = require('./base')
|
|
||||||
const matchUtil = require('../../utils/util.match')
|
const matchUtil = require('../../utils/util.match')
|
||||||
|
const BaseDNS = require('./base')
|
||||||
|
|
||||||
function mapToList (ipMap) {
|
function mapToList (ipMap) {
|
||||||
const ipList = []
|
const ipList = []
|
||||||
for (const key in ipMap) {
|
for (const key in ipMap) {
|
||||||
if (!ipMap[key]) continue
|
if (!ipMap[key]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ipList.push(ipMap[key])
|
ipList.push(ipMap[key])
|
||||||
}
|
}
|
||||||
return ipList
|
return ipList
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const dnstls = require('dns-over-tls')
|
const dnstls = require('dns-over-tls')
|
||||||
const BaseDNS = require('./base')
|
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
|
const BaseDNS = require('./base')
|
||||||
|
|
||||||
module.exports = class DNSOverTLS extends BaseDNS {
|
module.exports = class DNSOverTLS extends BaseDNS {
|
||||||
async _lookup (hostname) {
|
async _lookup (hostname) {
|
||||||
const { answers } = await dnstls.query(hostname)
|
const { answers } = await dnstls.query(hostname)
|
||||||
|
|
|
@ -34,7 +34,7 @@ module.exports = {
|
||||||
'Access-Control-Allow-Headers': allowHeaders,
|
'Access-Control-Allow-Headers': allowHeaders,
|
||||||
'Access-Control-Allow-Methods': allowMethods,
|
'Access-Control-Allow-Methods': allowMethods,
|
||||||
'Access-Control-Max-Age': interceptOpt.optionsMaxAge > 0 ? interceptOpt.optionsMaxAge : 2592000, // 默认有效一个月
|
'Access-Control-Max-Age': interceptOpt.optionsMaxAge > 0 ? interceptOpt.optionsMaxAge : 2592000, // 默认有效一个月
|
||||||
Date: new Date().toUTCString()
|
'Date': new Date().toUTCString(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否允许
|
// 判断是否允许
|
||||||
|
@ -50,5 +50,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.options
|
return !!interceptOpt.options
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@ module.exports = {
|
||||||
|
|
||||||
res.writeHead(403, {
|
res.writeHead(403, {
|
||||||
'Content-Type': 'text/plain; charset=utf-8',
|
'Content-Type': 'text/plain; charset=utf-8',
|
||||||
'DS-Interceptor': 'abort'
|
'DS-Interceptor': 'abort',
|
||||||
})
|
})
|
||||||
res.write(
|
res.write(
|
||||||
'DevSidecar 403: Request abort.\r\n\r\n' +
|
'DevSidecar 403: Request abort.\n\n'
|
||||||
' This request is matched by abort intercept.\r\n' +
|
+ ' This request is matched by abort intercept.\n'
|
||||||
' 因配置abort拦截器,本请求直接返回403禁止访问。'
|
+ ' 因配置abort拦截器,本请求直接返回403禁止访问。',
|
||||||
)
|
)
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.abort
|
return !!interceptOpt.abort
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ function getTomorrow () {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const AipOcrClient = require('baidu-aip-sdk').ocr
|
const AipOcrClient = require('baidu-aip-sdk').ocr
|
||||||
|
|
||||||
const AipOcrClientMap = {}
|
const AipOcrClientMap = {}
|
||||||
const apis = [
|
const apis = [
|
||||||
'accurateBasic', // 调用通用文字识别(高精度版)
|
'accurateBasic', // 调用通用文字识别(高精度版)
|
||||||
'accurate', // 调用通用文字识别(含位置高精度版)
|
'accurate', // 调用通用文字识别(含位置高精度版)
|
||||||
'handwriting' // 手写文字识别
|
'handwriting', // 手写文字识别
|
||||||
]
|
]
|
||||||
|
|
||||||
const limitMap = {}
|
const limitMap = {}
|
||||||
|
|
||||||
function createBaiduOcrClient (config) {
|
function createBaiduOcrClient (config) {
|
||||||
|
@ -57,7 +57,9 @@ function getConfig (interceptOpt, tryCount, log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 避免count值过大,造成问题
|
// 避免count值过大,造成问题
|
||||||
if (count >= 100000) count = 0
|
if (count >= 100000) {
|
||||||
|
count = 0
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
config = interceptOpt.baiduOcr
|
config = interceptOpt.baiduOcr
|
||||||
tryCount = null // 将tryCount设置为null代表只有一个配置
|
tryCount = null // 将tryCount设置为null代表只有一个配置
|
||||||
|
@ -95,13 +97,13 @@ function getConfig (interceptOpt, tryCount, log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function limitConfig (id, api) {
|
function limitConfig (id, api) {
|
||||||
const key = id + '_' + api
|
const key = `${id}_${api}`
|
||||||
limitMap[key] = getTomorrow()
|
limitMap[key] = getTomorrow()
|
||||||
// limitMap[key] = Date.now() + 5000 // 测试用,5秒后解禁
|
// limitMap[key] = Date.now() + 5000 // 测试用,5秒后解禁
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIsLimitConfig (id, api) {
|
function checkIsLimitConfig (id, api) {
|
||||||
const key = id + '_' + api
|
const key = `${id}_${api}`
|
||||||
const limitTime = limitMap[key]
|
const limitTime = limitMap[key]
|
||||||
return limitTime && limitTime > Date.now()
|
return limitTime && limitTime > Date.now()
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,7 @@ module.exports = {
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
'Access-Control-Allow-Origin': '*'
|
'Access-Control-Allow-Origin': '*',
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取配置
|
// 获取配置
|
||||||
|
@ -151,10 +153,10 @@ module.exports = {
|
||||||
detect_direction: 'false',
|
detect_direction: 'false',
|
||||||
paragraph: 'false',
|
paragraph: 'false',
|
||||||
probability: 'false',
|
probability: 'false',
|
||||||
...(config.options || {})
|
...(config.options || {}),
|
||||||
}
|
}
|
||||||
log.info('发起百度ocr请求', req.hostname)
|
log.info('发起百度ocr请求', req.hostname)
|
||||||
client[config.api || apis[0]](imageBase64, options).then(function (result) {
|
client[config.api || apis[0]](imageBase64, options).then((result) => {
|
||||||
if (result.error_code != null) {
|
if (result.error_code != null) {
|
||||||
log.error('baiduOcr error:', result)
|
log.error('baiduOcr error:', result)
|
||||||
if (result.error_code === 17) {
|
if (result.error_code === 17) {
|
||||||
|
@ -170,12 +172,14 @@ module.exports = {
|
||||||
res.write(JSON.stringify(result)) // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
res.write(JSON.stringify(result)) // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
||||||
res.end()
|
res.end()
|
||||||
if (next) next() // 异步执行完继续next
|
if (next) next() // 异步执行完继续next
|
||||||
}).catch(function (err) {
|
}).catch((err) => {
|
||||||
log.info('baiduOcr error:', err)
|
log.info('baiduOcr error:', err)
|
||||||
res.writeHead(200, headers)
|
res.writeHead(200, headers)
|
||||||
res.write('{"error_code": 999500, "error_msg": "' + err + '"}') // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
res.write(`{"error_code": 999500, "error_msg": "${err}"}`) // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
||||||
res.end()
|
res.end()
|
||||||
if (next) next() // 异步执行完继续next
|
if (next) {
|
||||||
|
next() // 异步执行完继续next
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
log.info('proxy baiduOcr: hostname:', req.hostname)
|
log.info('proxy baiduOcr: hostname:', req.hostname)
|
||||||
|
@ -184,5 +188,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.baiduOcr
|
return !!interceptOpt.baiduOcr
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ function getLastModifiedTimeFromIfModifiedSince (rOptions, log) {
|
||||||
return new Date(lastModified).getTime()
|
return new Date(lastModified).getTime()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 为数字时,直接返回
|
// 为数字时,直接返回
|
||||||
if (/\\d+/g.test(lastModified)) {
|
if (/\\d+/.test(lastModified)) {
|
||||||
return lastModified - 0
|
return lastModified - 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,12 +66,12 @@ module.exports = {
|
||||||
|
|
||||||
// 获取 Cache-Control 用于判断是否禁用缓存
|
// 获取 Cache-Control 用于判断是否禁用缓存
|
||||||
const cacheControl = rOptions.headers['cache-control']
|
const cacheControl = rOptions.headers['cache-control']
|
||||||
if (cacheControl && (cacheControl.indexOf('no-cache') >= 0 || cacheControl.indexOf('no-store') >= 0)) {
|
if (cacheControl && (cacheControl.includes('no-cache') || cacheControl.includes('no-store'))) {
|
||||||
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
||||||
}
|
}
|
||||||
// 获取 Pragma 用于判断是否禁用缓存
|
// 获取 Pragma 用于判断是否禁用缓存
|
||||||
const pragma = rOptions.headers.pragma
|
const pragma = rOptions.headers.pragma
|
||||||
if (pragma && (pragma.indexOf('no-cache') >= 0 || pragma.indexOf('no-store') >= 0)) {
|
if (pragma && (pragma.includes('no-cache') || pragma.includes('no-store'))) {
|
||||||
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ module.exports = {
|
||||||
|
|
||||||
// 缓存未过期,直接拦截请求并响应304
|
// 缓存未过期,直接拦截请求并响应304
|
||||||
res.writeHead(304, {
|
res.writeHead(304, {
|
||||||
'DS-Interceptor': 'cache: ' + maxAge
|
'DS-Interceptor': `cache: ${maxAge}`,
|
||||||
})
|
})
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
|
@ -103,5 +103,5 @@ module.exports = {
|
||||||
const maxAge = getMaxAge(interceptOpt)
|
const maxAge = getMaxAge(interceptOpt)
|
||||||
return maxAge != null && maxAge > 0
|
return maxAge != null && maxAge > 0
|
||||||
},
|
},
|
||||||
getMaxAge
|
getMaxAge,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,20 @@ const lodash = require('lodash')
|
||||||
|
|
||||||
// 替换占位符
|
// 替换占位符
|
||||||
function replacePlaceholder (url, rOptions, matched) {
|
function replacePlaceholder (url, rOptions, matched) {
|
||||||
if (url.indexOf('${') >= 0) {
|
if (url.includes('${')) {
|
||||||
// eslint-disable-next-line
|
|
||||||
// no-template-curly-in-string
|
// no-template-curly-in-string
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
url = url.replace('${host}', rOptions.hostname)
|
url = url.replace('${host}', rOptions.hostname)
|
||||||
|
|
||||||
if (matched && url.indexOf('${') >= 0) {
|
if (matched && url.includes('${')) {
|
||||||
for (let i = 0; i < matched.length; i++) {
|
for (let i = 0; i < matched.length; i++) {
|
||||||
url = url.replace('${m[' + i + ']}', matched[i] == null ? '' : matched[i])
|
url = url.replace(`\${m[${i}]}`, matched[i] == null ? '' : matched[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除多余的占位符
|
// 移除多余的占位符
|
||||||
if (url.indexOf('${') >= 0) {
|
if (url.includes('${')) {
|
||||||
url = url.replace(/\$\{[^}]+}/g, '')
|
url = url.replace(/\$\{[^}]+\}/g, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ function buildTargetUrl (rOptions, urlConf, interceptOpt, matched) {
|
||||||
targetUrl = replacePlaceholder(targetUrl, rOptions, matched)
|
targetUrl = replacePlaceholder(targetUrl, rOptions, matched)
|
||||||
|
|
||||||
// 拼接协议
|
// 拼接协议
|
||||||
targetUrl = targetUrl.indexOf('http:') === 0 || targetUrl.indexOf('https:') === 0 ? targetUrl : rOptions.protocol + '//' + targetUrl
|
targetUrl = targetUrl.indexOf('http:') === 0 || targetUrl.indexOf('https:') === 0 ? targetUrl : `${rOptions.protocol}//${targetUrl}`
|
||||||
|
|
||||||
return targetUrl
|
return targetUrl
|
||||||
}
|
}
|
||||||
|
@ -90,7 +89,7 @@ module.exports = {
|
||||||
for (const bk of interceptOpt.backup) {
|
for (const bk of interceptOpt.backup) {
|
||||||
backupList.push(bk)
|
backupList.push(bk)
|
||||||
}
|
}
|
||||||
const key = rOptions.hostname + '/' + interceptOpt.key
|
const key = `${rOptions.hostname}/${interceptOpt.key}`
|
||||||
const count = RequestCounter.getOrCreate(key, backupList)
|
const count = RequestCounter.getOrCreate(key, backupList)
|
||||||
if (count.value == null) {
|
if (count.value == null) {
|
||||||
count.doRank()
|
count.doRank()
|
||||||
|
@ -103,7 +102,7 @@ module.exports = {
|
||||||
context.requestCount = {
|
context.requestCount = {
|
||||||
key,
|
key,
|
||||||
value: count.value,
|
value: count.value,
|
||||||
count
|
count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,5 +134,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.proxy
|
return !!interceptOpt.proxy
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ module.exports = {
|
||||||
const redirect = proxyApi.buildTargetUrl(rOptions, interceptOpt.redirect, interceptOpt, matched)
|
const redirect = proxyApi.buildTargetUrl(rOptions, interceptOpt.redirect, interceptOpt, matched)
|
||||||
|
|
||||||
res.writeHead(302, {
|
res.writeHead(302, {
|
||||||
Location: redirect,
|
'Location': redirect,
|
||||||
'DS-Interceptor': 'redirect'
|
'DS-Interceptor': 'redirect',
|
||||||
})
|
})
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return interceptOpt.redirect // 如果配置中有redirect,那么这个配置是需要redirect拦截的
|
return interceptOpt.redirect // 如果配置中有redirect,那么这个配置是需要redirect拦截的
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ module.exports = {
|
||||||
// 替换请求头
|
// 替换请求头
|
||||||
if (requestReplaceConfig.headers) {
|
if (requestReplaceConfig.headers) {
|
||||||
replaceRequestHeaders(rOptions, requestReplaceConfig.headers, log)
|
replaceRequestHeaders(rOptions, requestReplaceConfig.headers, log)
|
||||||
actions += (actions ? ',' : '') + 'headers'
|
actions += `${actions ? ',' : ''}headers`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换下载文件请求的请求地址(此功能主要是为了方便拦截配置)
|
// 替换下载文件请求的请求地址(此功能主要是为了方便拦截配置)
|
||||||
|
@ -40,7 +40,7 @@ module.exports = {
|
||||||
if (requestReplaceConfig.doDownload && rOptions.path.match(/DS_DOWNLOAD/i)) {
|
if (requestReplaceConfig.doDownload && rOptions.path.match(/DS_DOWNLOAD/i)) {
|
||||||
rOptions.doDownload = true
|
rOptions.doDownload = true
|
||||||
rOptions.path = rOptions.path.replace(/[?&/]?DS_DOWNLOAD(=[^?&/]+)?$/gi, '')
|
rOptions.path = rOptions.path.replace(/[?&/]?DS_DOWNLOAD(=[^?&/]+)?$/gi, '')
|
||||||
actions += (actions ? ',' : '') + 'path:remove-DS_DOWNLOAD'
|
actions += `${actions ? ',' : ''}path:remove-DS_DOWNLOAD`
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('DS-RequestReplace-Interceptor', actions)
|
res.setHeader('DS-RequestReplace-Interceptor', actions)
|
||||||
|
@ -50,5 +50,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.requestReplace
|
return !!interceptOpt.requestReplace
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.sni && !interceptOpt.proxy // proxy生效时,sni不需要生效,因为proxy中也会使用sni覆盖 rOptions.servername
|
return !!interceptOpt.sni && !interceptOpt.proxy // proxy生效时,sni不需要生效,因为proxy中也会使用sni覆盖 rOptions.servername
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@ module.exports = {
|
||||||
|
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
'Content-Type': 'text/plain; charset=utf-8',
|
'Content-Type': 'text/plain; charset=utf-8',
|
||||||
'DS-Interceptor': 'success'
|
'DS-Interceptor': 'success',
|
||||||
})
|
})
|
||||||
res.write(
|
res.write(
|
||||||
'DevSidecar 200: Request success.\n\n' +
|
'DevSidecar 200: Request success.\n\n'
|
||||||
' This request is matched by success intercept.\n\n' +
|
+ ' This request is matched by success intercept.\n\n'
|
||||||
' 因配置success拦截器,本请求直接返回200成功。'
|
+ ' 因配置success拦截器,本请求直接返回200成功。',
|
||||||
)
|
)
|
||||||
res.end()
|
res.end()
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.success
|
return !!interceptOpt.success
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
'Access-Control-Allow-Origin': rOptions.headers.origin
|
'Access-Control-Allow-Origin': rOptions.headers.origin,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换响应头
|
// 替换响应头
|
||||||
|
@ -23,5 +23,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.options
|
return !!interceptOpt.options
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断当前响应码是否不使用缓存
|
// 判断当前响应码是否不使用缓存
|
||||||
if (interceptOpt.cacheExcludeStatusCodeList && interceptOpt.cacheExcludeStatusCodeList[proxyRes.statusCode + '']) {
|
if (interceptOpt.cacheExcludeStatusCodeList && interceptOpt.cacheExcludeStatusCodeList[`${proxyRes.statusCode}`]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ module.exports = {
|
||||||
// 获取maxAge配置
|
// 获取maxAge配置
|
||||||
let maxAge = cacheReq.getMaxAge(interceptOpt)
|
let maxAge = cacheReq.getMaxAge(interceptOpt)
|
||||||
// public 或 private
|
// public 或 private
|
||||||
const cacheControlType = (interceptOpt.cacheControlType || 'public') + ', '
|
const cacheControlType = `${interceptOpt.cacheControlType || 'public'}, `
|
||||||
// immutable属性
|
// immutable属性
|
||||||
const cacheImmutable = interceptOpt.cacheImmutable !== false ? ', immutable' : ''
|
const cacheImmutable = interceptOpt.cacheImmutable !== false ? ', immutable' : ''
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ module.exports = {
|
||||||
cacheControl: null,
|
cacheControl: null,
|
||||||
lastModified: null,
|
lastModified: null,
|
||||||
expires: null,
|
expires: null,
|
||||||
etag: null
|
etag: null,
|
||||||
}
|
}
|
||||||
for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) {
|
for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) {
|
||||||
// 尝试修改rawHeaders中的cache-control、last-modified、expires
|
// 尝试修改rawHeaders中的cache-control、last-modified、expires
|
||||||
|
@ -65,7 +65,7 @@ module.exports = {
|
||||||
if (originalHeaders.cacheControl) {
|
if (originalHeaders.cacheControl) {
|
||||||
const maxAgeMatch = originalHeaders.cacheControl.value.match(/max-age=(\d+)/)
|
const maxAgeMatch = originalHeaders.cacheControl.value.match(/max-age=(\d+)/)
|
||||||
if (maxAgeMatch && maxAgeMatch[1] > maxAge) {
|
if (maxAgeMatch && maxAgeMatch[1] > maxAge) {
|
||||||
if (interceptOpt.cacheImmutable !== false && originalHeaders.cacheControl.value.indexOf('immutable') < 0) {
|
if (interceptOpt.cacheImmutable !== false && !originalHeaders.cacheControl.value.includes('immutable')) {
|
||||||
maxAge = maxAgeMatch[1]
|
maxAge = maxAgeMatch[1]
|
||||||
} else {
|
} else {
|
||||||
const url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${req.url}`
|
const url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${req.url}`
|
||||||
|
@ -81,7 +81,7 @@ module.exports = {
|
||||||
const replaceHeaders = {
|
const replaceHeaders = {
|
||||||
cacheControl: `${cacheControlType}max-age=${maxAge + 1}${cacheImmutable}`,
|
cacheControl: `${cacheControlType}max-age=${maxAge + 1}${cacheImmutable}`,
|
||||||
lastModified: now.toUTCString(),
|
lastModified: now.toUTCString(),
|
||||||
expires: new Date(now.getTime() + maxAge * 1000).toUTCString()
|
expires: new Date(now.getTime() + maxAge * 1000).toUTCString(),
|
||||||
}
|
}
|
||||||
// 开始替换
|
// 开始替换
|
||||||
// 替换cache-control
|
// 替换cache-control
|
||||||
|
@ -108,5 +108,5 @@ module.exports = {
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
const maxAge = cacheReq.getMaxAge(interceptOpt)
|
const maxAge = cacheReq.getMaxAge(interceptOpt)
|
||||||
return maxAge != null && maxAge > 0
|
return maxAge != null && maxAge > 0
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const lodash = require('lodash')
|
const lodash = require('lodash')
|
||||||
const cacheReq = require('../req/cacheReq')
|
const cacheReq = require('../req/cacheReq')
|
||||||
|
|
||||||
const REMOVE = '[remove]'
|
const REMOVE = '[remove]'
|
||||||
|
|
||||||
// 替换响应头
|
// 替换响应头
|
||||||
|
@ -96,20 +97,20 @@ module.exports = {
|
||||||
replaceHeaders.expires = '[remove]'
|
replaceHeaders.expires = '[remove]'
|
||||||
}
|
}
|
||||||
|
|
||||||
actions += (actions ? ',' : '') + 'download:' + filename
|
actions += `${actions ? ',' : ''}download:${filename}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 替换响应头
|
// 替换响应头
|
||||||
if (replaceResponseHeaders(replaceHeaders, res, proxyRes)) {
|
if (replaceResponseHeaders(replaceHeaders, res, proxyRes)) {
|
||||||
actions += (actions ? ',' : '') + 'headers'
|
actions += `${actions ? ',' : ''}headers`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actions) {
|
if (actions) {
|
||||||
res.setHeader('DS-ResponseReplace-Interceptor', actions)
|
res.setHeader('DS-ResponseReplace-Interceptor', actions)
|
||||||
log.info('response intercept: ' + actions)
|
log.info(`response intercept: ${actions}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
is (interceptOpt) {
|
is (interceptOpt) {
|
||||||
return !!interceptOpt.responseReplace
|
return !!interceptOpt.responseReplace
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有响应头 'content-type',或其值不是 'text/html',则不处理
|
// 如果没有响应头 'content-type',或其值不是 'text/html',则不处理
|
||||||
if (!proxyRes.headers['content-type'] || proxyRes.headers['content-type'].indexOf('text/html') < 0) {
|
if (!proxyRes.headers['content-type'] || !proxyRes.headers['content-type'].includes('text/html')) {
|
||||||
res.setHeader('DS-Script-Interceptor', 'Not text/html')
|
res.setHeader('DS-Script-Interceptor', 'Not text/html')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ module.exports = {
|
||||||
|
|
||||||
let scriptTag
|
let scriptTag
|
||||||
|
|
||||||
if (key.indexOf('/') >= 0) {
|
if (key.includes('/')) {
|
||||||
scriptTag = getScriptByUrlOrPath(key) // 1.绝对地址或相对地址(注意:当目标站点限制跨域脚本时,可使用相对地址,再结合proxy拦截器进行代理,可规避掉限制跨域脚本问题。)
|
scriptTag = getScriptByUrlOrPath(key) // 1.绝对地址或相对地址(注意:当目标站点限制跨域脚本时,可使用相对地址,再结合proxy拦截器进行代理,可规避掉限制跨域脚本问题。)
|
||||||
} else {
|
} else {
|
||||||
const script = scripts[key]
|
const script = scripts[key]
|
||||||
|
@ -60,7 +60,7 @@ module.exports = {
|
||||||
scriptTag = getScript(key, script.script) // 2.DS内置脚本
|
scriptTag = getScript(key, script.script) // 2.DS内置脚本
|
||||||
}
|
}
|
||||||
|
|
||||||
tags += '\r\n\t' + scriptTag
|
tags += `\r\n\t${scriptTag}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果脚本为空,则不插入
|
// 如果脚本为空,则不插入
|
||||||
|
@ -70,15 +70,15 @@ module.exports = {
|
||||||
|
|
||||||
// 插入油猴脚本浏览器扩展
|
// 插入油猴脚本浏览器扩展
|
||||||
if (typeof interceptOpt.tampermonkeyScript === 'string') {
|
if (typeof interceptOpt.tampermonkeyScript === 'string') {
|
||||||
tags = '\r\n\t' + getScriptByUrlOrPath(interceptOpt.tampermonkeyScript) + tags
|
tags = `\r\n\t${getScriptByUrlOrPath(interceptOpt.tampermonkeyScript)}${tags}`
|
||||||
} else {
|
} else {
|
||||||
tags = '\r\n\t' + getScript('tampermonkey', scripts.tampermonkey.script) + tags
|
tags = `\r\n\t${getScript('tampermonkey', scripts.tampermonkey.script)}${tags}`
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('DS-Script-Interceptor', 'true')
|
res.setHeader('DS-Script-Interceptor', 'true')
|
||||||
log.info(`script response intercept: insert script ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`, ', head:', tags)
|
log.info(`script response intercept: insert script ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`, ', head:', tags)
|
||||||
return {
|
return {
|
||||||
head: tags + '\r\n'
|
head: `${tags}\r\n`,
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
try {
|
try {
|
||||||
|
@ -102,10 +102,12 @@ module.exports = {
|
||||||
const handleScriptUrl = (scriptUrl, name, replaceScriptUrlFun) => {
|
const handleScriptUrl = (scriptUrl, name, replaceScriptUrlFun) => {
|
||||||
if (scriptUrl.indexOf('https:') === 0 || scriptUrl.indexOf('http:') === 0) {
|
if (scriptUrl.indexOf('https:') === 0 || scriptUrl.indexOf('http:') === 0) {
|
||||||
// 绝对地址
|
// 绝对地址
|
||||||
const scriptKey = SCRIPT_PROXY_URL_PRE + scriptUrl.replace('.js', '').replace(/[\W_]+/g, '_') + '.js' // 伪脚本地址:移除 script 中可能存在的特殊字符,并转为相对地址
|
const scriptKey = `${SCRIPT_PROXY_URL_PRE + scriptUrl.replace('.js', '').replace(/[\W_]+/g, '_')}.js` // 伪脚本地址:移除 script 中可能存在的特殊字符,并转为相对地址
|
||||||
scriptProxy[scriptKey] = scriptUrl
|
scriptProxy[scriptKey] = scriptUrl
|
||||||
log.info(`替换${name}配置值:'${scriptUrl}' -> '${scriptKey}'`)
|
log.info(`替换${name}配置值:'${scriptUrl}' -> '${scriptKey}'`)
|
||||||
if (typeof replaceScriptUrlFun === 'function') replaceScriptUrlFun(scriptKey)
|
if (typeof replaceScriptUrlFun === 'function') {
|
||||||
|
replaceScriptUrlFun(scriptKey)
|
||||||
|
}
|
||||||
} else if (scriptUrl.indexOf('/') === 0) {
|
} else if (scriptUrl.indexOf('/') === 0) {
|
||||||
// 相对地址
|
// 相对地址
|
||||||
scriptProxy[scriptUrl] = scriptUrl
|
scriptProxy[scriptUrl] = scriptUrl
|
||||||
|
@ -154,19 +156,19 @@ module.exports = {
|
||||||
headers: {
|
headers: {
|
||||||
host: REMOVE,
|
host: REMOVE,
|
||||||
referer: REMOVE,
|
referer: REMOVE,
|
||||||
cookie: REMOVE
|
cookie: REMOVE,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// 替换和移除部分响应头,避免触发目标站点的阻止脚本加载策略
|
// 替换和移除部分响应头,避免触发目标站点的阻止脚本加载策略
|
||||||
responseReplace: {
|
responseReplace: {
|
||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/javascript; charset=utf-8',
|
'content-type': 'application/javascript; charset=utf-8',
|
||||||
'set-cookie': REMOVE,
|
'set-cookie': REMOVE,
|
||||||
server: REMOVE
|
'server': REMOVE,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
cacheDays: 7,
|
cacheDays: 7,
|
||||||
desc: "为伪脚本文件设置代理地址,并设置响应头 `content-type: 'application/javascript; charset=utf-8'`,同时缓存7天。"
|
desc: '为伪脚本文件设置代理地址,并设置响应头 `content-type: \'application/javascript; charset=utf-8\'`,同时缓存7天。',
|
||||||
}
|
}
|
||||||
|
|
||||||
const obj = {}
|
const obj = {}
|
||||||
|
@ -181,11 +183,11 @@ module.exports = {
|
||||||
hostnameConfig[scriptKey] = {
|
hostnameConfig[scriptKey] = {
|
||||||
responseReplace: {
|
responseReplace: {
|
||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/javascript; charset=utf-8'
|
'content-type': 'application/javascript; charset=utf-8',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
cacheDays: 7,
|
cacheDays: 7,
|
||||||
desc: "为脚本设置响应头 `content-type: 'application/javascript; charset=utf-8'`,同时缓存7天。"
|
desc: '为脚本设置响应头 `content-type: \'application/javascript; charset=utf-8\'`,同时缓存7天。',
|
||||||
}
|
}
|
||||||
|
|
||||||
const obj = {}
|
const obj = {}
|
||||||
|
@ -195,5 +197,5 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const log = require('../../utils/util.log')
|
const log = require('../../utils/util.log')
|
||||||
|
|
||||||
let scripts
|
let scripts
|
||||||
|
|
||||||
function buildScript (sc, content, scriptName) {
|
function buildScript (sc, content, scriptName) {
|
||||||
const scriptKey = `ds_${scriptName}${sc.version ? ('_' + sc.version) : ''}:`
|
const scriptKey = `ds_${scriptName}${sc.version ? (`_${sc.version}`) : ''}:`
|
||||||
|
|
||||||
// 代码1:监听事件
|
// 代码1:监听事件
|
||||||
const runAt = sc['run-at'] || 'document-end'
|
const runAt = sc['run-at'] || 'document-end'
|
||||||
|
@ -19,7 +20,7 @@ function buildScript (sc, content, scriptName) {
|
||||||
const options = {
|
const options = {
|
||||||
name: sc.name,
|
name: sc.name,
|
||||||
version: sc.version,
|
version: sc.version,
|
||||||
icon: sc.icon
|
icon: sc.icon,
|
||||||
}
|
}
|
||||||
const initStr = `
|
const initStr = `
|
||||||
const DS_init = (window.__ds_global__ || {})['DS_init']
|
const DS_init = (window.__ds_global__ || {})['DS_init']
|
||||||
|
@ -45,21 +46,21 @@ if (!((window.__ds_global__ || {}).GM_getValue || (() => true))("ds_enabled", tr
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.indexOf('.') > 0) {
|
if (item.indexOf('.') > 0) {
|
||||||
grantStr += item + ' = (window.__ds_global__ || {})[\'' + item + '\'];'
|
grantStr += `${item} = (window.__ds_global__ || {})['${item}'];`
|
||||||
} else {
|
} else {
|
||||||
grantStr += 'const ' + item + ' = (window.__ds_global__ || {})[\'' + item + '\'] || (() => {});'
|
grantStr += `const ${item} = (window.__ds_global__ || {})['${item}'] || (() => {});`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拼接脚本
|
// 拼接脚本
|
||||||
return eventStr + ', () => {' +
|
return `${eventStr}, () => {${
|
||||||
initStr + '\r\n' +
|
initStr}\r\n${
|
||||||
checkEnabledStr + '\r\n\r\n' +
|
checkEnabledStr}\r\n\r\n${
|
||||||
(grantStr ? (grantStr + '\r\n\r\n') : '') +
|
grantStr ? (`${grantStr}\r\n\r\n`) : ''
|
||||||
content +
|
}${content
|
||||||
`\r\nconsole.log("${scriptKey} completed")` +
|
}\r\nconsole.log("${scriptKey} completed")`
|
||||||
'\r\n})' +
|
+ `\r\n})`
|
||||||
`\r\nconsole.log("${scriptKey} loaded")`
|
+ `\r\nconsole.log("${scriptKey} loaded")`
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadScript (content, scriptName) {
|
function loadScript (content, scriptName) {
|
||||||
|
@ -78,10 +79,10 @@ function loadScript (content, scriptName) {
|
||||||
const sc = {
|
const sc = {
|
||||||
grant: [],
|
grant: [],
|
||||||
match: [],
|
match: [],
|
||||||
script: ''
|
script: '',
|
||||||
}
|
}
|
||||||
for (const string of confItemArr) {
|
for (const string of confItemArr) {
|
||||||
const reg = new RegExp('.*@([^\\s]+)\\s(.+)')
|
const reg = new RegExp('.*@(\\S+)\\s(.+)')
|
||||||
const ret = string.match(reg)
|
const ret = string.match(reg)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
const key = ret[1].trim()
|
const key = ret[1].trim()
|
||||||
|
@ -103,7 +104,7 @@ function loadScript (content, scriptName) {
|
||||||
|
|
||||||
function readFile (rootDir, script) {
|
function readFile (rootDir, script) {
|
||||||
log.info('read script, script root location:', path.resolve('./'))
|
log.info('read script, script root location:', path.resolve('./'))
|
||||||
const location = path.join(rootDir, './' + script)
|
const location = path.join(rootDir, `./${script}`)
|
||||||
log.info('read script, the script location:', location)
|
log.info('read script, the script location:', location)
|
||||||
return fs.readFileSync(location).toString()
|
return fs.readFileSync(location).toString()
|
||||||
}
|
}
|
||||||
|
@ -123,7 +124,7 @@ const api = {
|
||||||
scripts.tampermonkey = { script: readFile(rootDir, 'tampermonkey.script') }
|
scripts.tampermonkey = { script: readFile(rootDir, 'tampermonkey.script') }
|
||||||
return scripts
|
return scripts
|
||||||
},
|
},
|
||||||
loadScript
|
loadScript,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = api
|
module.exports = api
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
const config = exports
|
const config = exports
|
||||||
|
|
||||||
config.defaultHost = '127.0.0.1'
|
config.defaultHost = '127.0.0.1'
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
const Agent = require('./ProxyHttpAgent')
|
|
||||||
const HttpsAgent = require('./ProxyHttpsAgent')
|
|
||||||
const tunnelAgent = require('tunnel-agent')
|
const tunnelAgent = require('tunnel-agent')
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
const matchUtil = require('../../../utils/util.match')
|
const matchUtil = require('../../../utils/util.match')
|
||||||
|
const Agent = require('./ProxyHttpAgent')
|
||||||
|
const HttpsAgent = require('./ProxyHttpsAgent')
|
||||||
|
|
||||||
const util = exports
|
const util = exports
|
||||||
|
|
||||||
const httpsAgentCache = {}
|
const httpsAgentCache = {}
|
||||||
|
@ -25,7 +26,7 @@ function getTimeoutConfig (hostname, serverSetting) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createHttpsAgent (timeoutConfig, verifySsl) {
|
function createHttpsAgent (timeoutConfig, verifySsl) {
|
||||||
const key = timeoutConfig.timeout + '-' + timeoutConfig.keepAliveTimeout
|
const key = `${timeoutConfig.timeout}-${timeoutConfig.keepAliveTimeout}`
|
||||||
if (!httpsAgentCache[key]) {
|
if (!httpsAgentCache[key]) {
|
||||||
verifySsl = !!verifySsl
|
verifySsl = !!verifySsl
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ function createHttpsAgent (timeoutConfig, verifySsl) {
|
||||||
timeout: timeoutConfig.timeout,
|
timeout: timeoutConfig.timeout,
|
||||||
keepAliveTimeout: timeoutConfig.keepAliveTimeout,
|
keepAliveTimeout: timeoutConfig.keepAliveTimeout,
|
||||||
checkServerIdentity,
|
checkServerIdentity,
|
||||||
rejectUnauthorized: verifySsl
|
rejectUnauthorized: verifySsl,
|
||||||
})
|
})
|
||||||
|
|
||||||
agent.unVerifySslAgent = new HttpsAgent({
|
agent.unVerifySslAgent = new HttpsAgent({
|
||||||
|
@ -47,7 +48,7 @@ function createHttpsAgent (timeoutConfig, verifySsl) {
|
||||||
timeout: timeoutConfig.timeout,
|
timeout: timeoutConfig.timeout,
|
||||||
keepAliveTimeout: timeoutConfig.keepAliveTimeout,
|
keepAliveTimeout: timeoutConfig.keepAliveTimeout,
|
||||||
checkServerIdentity,
|
checkServerIdentity,
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
httpsAgentCache[key] = agent
|
httpsAgentCache[key] = agent
|
||||||
|
@ -57,12 +58,12 @@ function createHttpsAgent (timeoutConfig, verifySsl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createHttpAgent (timeoutConfig) {
|
function createHttpAgent (timeoutConfig) {
|
||||||
const key = timeoutConfig.timeout + '-' + timeoutConfig.keepAliveTimeout
|
const key = `${timeoutConfig.timeout}-${timeoutConfig.keepAliveTimeout}`
|
||||||
if (!httpAgentCache[key]) {
|
if (!httpAgentCache[key]) {
|
||||||
httpAgentCache[key] = new Agent({
|
httpAgentCache[key] = new Agent({
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
timeout: timeoutConfig.timeout,
|
timeout: timeoutConfig.timeout,
|
||||||
keepAliveTimeout: timeoutConfig.keepAliveTimeout
|
keepAliveTimeout: timeoutConfig.keepAliveTimeout,
|
||||||
})
|
})
|
||||||
log.info('创建 HttpAgent 成功, timeoutConfig:', timeoutConfig)
|
log.info('创建 HttpAgent 成功, timeoutConfig:', timeoutConfig)
|
||||||
}
|
}
|
||||||
|
@ -80,12 +81,12 @@ util.parseHostnameAndPort = (host, defaultPort) => {
|
||||||
if (arr) {
|
if (arr) {
|
||||||
arr = arr.slice(1)
|
arr = arr.slice(1)
|
||||||
if (arr[1]) {
|
if (arr[1]) {
|
||||||
arr[1] = parseInt(arr[1], 10)
|
arr[1] = Number.parseInt(arr[1], 10)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arr = host.split(':')
|
arr = host.split(':')
|
||||||
if (arr.length > 1) {
|
if (arr.length > 1) {
|
||||||
arr[1] = parseInt(arr[1], 10)
|
arr[1] = Number.parseInt(arr[1], 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ util.getOptionsFromRequest = (req, ssl, externalProxy = null, serverSetting, com
|
||||||
path: urlObject.path,
|
path: urlObject.path,
|
||||||
headers: req.headers,
|
headers: req.headers,
|
||||||
agent,
|
agent,
|
||||||
compatibleConfig
|
compatibleConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line node/no-deprecated-api
|
// eslint-disable-next-line node/no-deprecated-api
|
||||||
|
@ -188,8 +189,8 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
||||||
httpsOverHttpAgent = tunnelAgent.httpsOverHttp({
|
httpsOverHttpAgent = tunnelAgent.httpsOverHttp({
|
||||||
proxy: {
|
proxy: {
|
||||||
host: hostname,
|
host: hostname,
|
||||||
port: port
|
port,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return httpsOverHttpAgent
|
return httpsOverHttpAgent
|
||||||
|
@ -198,8 +199,8 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
||||||
httpsOverHttpsAgent = tunnelAgent.httpsOverHttps({
|
httpsOverHttpsAgent = tunnelAgent.httpsOverHttps({
|
||||||
proxy: {
|
proxy: {
|
||||||
host: hostname,
|
host: hostname,
|
||||||
port: port
|
port,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return httpsOverHttpsAgent
|
return httpsOverHttpsAgent
|
||||||
|
@ -220,8 +221,8 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
||||||
httpOverHttpsAgent = tunnelAgent.httpOverHttps({
|
httpOverHttpsAgent = tunnelAgent.httpOverHttps({
|
||||||
proxy: {
|
proxy: {
|
||||||
host: hostname,
|
host: hostname,
|
||||||
port: port
|
port,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return httpOverHttpsAgent
|
return httpOverHttpsAgent
|
||||||
|
|
|
@ -25,7 +25,7 @@ const defaultConfig = {
|
||||||
// 'xxx.xxx.xxx.xxx:443': {
|
// 'xxx.xxx.xxx.xxx:443': {
|
||||||
// rejectUnauthorized: false
|
// rejectUnauthorized: false
|
||||||
// }
|
// }
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = _loadFromFile(defaultConfig)
|
const config = _loadFromFile(defaultConfig)
|
||||||
|
@ -63,8 +63,12 @@ function _loadFromFile (defaultConfig) {
|
||||||
log.info('读取 automaticCompatibleConfig.json 成功:', configPath)
|
log.info('读取 automaticCompatibleConfig.json 成功:', configPath)
|
||||||
const fileStr = file.toString()
|
const fileStr = file.toString()
|
||||||
config = fileStr && fileStr.length > 2 ? jsonApi.parse(fileStr) : defaultConfig
|
config = fileStr && fileStr.length > 2 ? jsonApi.parse(fileStr) : defaultConfig
|
||||||
if (config.connect == null) config.connect = defaultConfig.connect
|
if (config.connect == null) {
|
||||||
if (config.request == null) config.request = defaultConfig.request
|
config.connect = defaultConfig.connect
|
||||||
|
}
|
||||||
|
if (config.request == null) {
|
||||||
|
config.request = defaultConfig.request
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
@ -108,7 +112,9 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置保存到文件
|
// 配置保存到文件
|
||||||
if (autoSave) _saveConfigToFile()
|
if (autoSave) {
|
||||||
|
_saveConfigToFile()
|
||||||
|
}
|
||||||
|
|
||||||
log.info(`【自动兼容程序】${hostname}:${port}: 设置 connect.ssl = ${ssl}`)
|
log.info(`【自动兼容程序】${hostname}:${port}: 设置 connect.ssl = ${ssl}`)
|
||||||
},
|
},
|
||||||
|
@ -138,8 +144,10 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置保存到文件
|
// 配置保存到文件
|
||||||
if (autoSave) _saveConfigToFile()
|
if (autoSave) {
|
||||||
|
_saveConfigToFile()
|
||||||
|
}
|
||||||
|
|
||||||
log.info(`【自动兼容程序】${rOptions.hostname}:${rOptions.port}: 设置 request.rejectUnauthorized = ${rejectUnauthorized}`)
|
log.info(`【自动兼容程序】${rOptions.hostname}:${rOptions.port}: 设置 request.rejectUnauthorized = ${rejectUnauthorized}`)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
const log = require('../../../utils/util.log')
|
|
||||||
const through = require('through2')
|
|
||||||
const zlib = require('zlib')
|
const zlib = require('zlib')
|
||||||
|
const through = require('through2')
|
||||||
|
const log = require('../../../utils/util.log')
|
||||||
|
|
||||||
// 编解码器
|
// 编解码器
|
||||||
const codecMap = {
|
const codecMap = {
|
||||||
gzip: {
|
gzip: {
|
||||||
createCompressor: () => zlib.createGzip(),
|
createCompressor: () => zlib.createGzip(),
|
||||||
createDecompressor: () => zlib.createGunzip()
|
createDecompressor: () => zlib.createGunzip(),
|
||||||
},
|
},
|
||||||
deflate: {
|
deflate: {
|
||||||
createCompressor: () => zlib.createDeflate(),
|
createCompressor: () => zlib.createDeflate(),
|
||||||
createDecompressor: () => zlib.createInflate()
|
createDecompressor: () => zlib.createInflate(),
|
||||||
},
|
},
|
||||||
br: {
|
br: {
|
||||||
createCompressor: () => zlib.createBrotliCompress(),
|
createCompressor: () => zlib.createBrotliCompress(),
|
||||||
createDecompressor: () => zlib.createBrotliDecompress()
|
createDecompressor: () => zlib.createBrotliDecompress(),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
const supportedEncodings = Object.keys(codecMap)
|
const supportedEncodings = Object.keys(codecMap)
|
||||||
const supportedEncodingsStr = supportedEncodings.join(', ')
|
const supportedEncodingsStr = supportedEncodings.join(', ')
|
||||||
|
@ -41,7 +41,7 @@ const httpUtil = {
|
||||||
isHtml (res) {
|
isHtml (res) {
|
||||||
const contentType = res.headers['content-type']
|
const contentType = res.headers['content-type']
|
||||||
return (typeof contentType !== 'undefined') && /text\/html|application\/xhtml\+xml/.test(contentType)
|
return (typeof contentType !== 'undefined') && /text\/html|application\/xhtml\+xml/.test(contentType)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
const HEAD = Buffer.from('</head>')
|
const HEAD = Buffer.from('</head>')
|
||||||
const HEAD_UP = Buffer.from('</HEAD>')
|
const HEAD_UP = Buffer.from('</HEAD>')
|
||||||
|
@ -84,7 +84,7 @@ function injectScriptIntoHtml (tags, chunk, script) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleResponseHeaders (res, proxyRes) {
|
function handleResponseHeaders (res, proxyRes) {
|
||||||
Object.keys(proxyRes.headers).forEach(function (key) {
|
Object.keys(proxyRes.headers).forEach((key) => {
|
||||||
if (proxyRes.headers[key] !== undefined) {
|
if (proxyRes.headers[key] !== undefined) {
|
||||||
// let newkey = key.replace(/^[a-z]|-[a-z]/g, (match) => {
|
// let newkey = key.replace(/^[a-z]|-[a-z]/g, (match) => {
|
||||||
// return match.toUpperCase()
|
// return match.toUpperCase()
|
||||||
|
@ -100,7 +100,7 @@ function handleResponseHeaders (res, proxyRes) {
|
||||||
const reg = /script-src ([^:]*);/i
|
const reg = /script-src ([^:]*);/i
|
||||||
const matched = policy.match(reg)
|
const matched = policy.match(reg)
|
||||||
if (matched) {
|
if (matched) {
|
||||||
if (matched[1].indexOf('self') < 0) {
|
if (!matched[1].includes('self')) {
|
||||||
policy = policy.replace('script-src', 'script-src \'self\' ')
|
policy = policy.replace('script-src', 'script-src \'self\' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,7 @@ function handleResponseHeaders (res, proxyRes) {
|
||||||
|
|
||||||
const contextPath = '/____ds_script____/'
|
const contextPath = '/____ds_script____/'
|
||||||
const monkey = require('../../monkey')
|
const monkey = require('../../monkey')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
requestIntercept (context, req, res, ssl, next) {
|
requestIntercept (context, req, res, ssl, next) {
|
||||||
const { rOptions, log, setting } = context
|
const { rOptions, log, setting } = context
|
||||||
|
@ -141,8 +142,8 @@ module.exports = {
|
||||||
'Content-Type': 'application/javascript; charset=utf-8',
|
'Content-Type': 'application/javascript; charset=utf-8',
|
||||||
'Cache-Control': 'public, max-age=86401, immutable', // 缓存1天
|
'Cache-Control': 'public, max-age=86401, immutable', // 缓存1天
|
||||||
'Last-Modified': now.toUTCString(),
|
'Last-Modified': now.toUTCString(),
|
||||||
Expires: new Date(now.getTime() + 86400000).toUTCString(), // 缓存1天
|
'Expires': new Date(now.getTime() + 86400000).toUTCString(), // 缓存1天
|
||||||
Date: new Date().toUTCString()
|
'Date': new Date().toUTCString(),
|
||||||
})
|
})
|
||||||
res.write(script.script)
|
res.write(script.script)
|
||||||
res.end()
|
res.end()
|
||||||
|
@ -194,5 +195,5 @@ module.exports = {
|
||||||
next()
|
next()
|
||||||
},
|
},
|
||||||
httpUtil,
|
httpUtil,
|
||||||
handleResponseHeaders
|
handleResponseHeaders,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const url = require('url')
|
|
||||||
const request = require('request')
|
|
||||||
const lodash = require('lodash')
|
|
||||||
const pac = require('./source/pac')
|
|
||||||
const matchUtil = require('../../../utils/util.match')
|
|
||||||
const log = require('../../../utils/util.log')
|
|
||||||
const path = require('path')
|
|
||||||
const fs = require('fs')
|
|
||||||
const { Buffer } = require('buffer')
|
const { Buffer } = require('buffer')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const url = require('url')
|
||||||
|
const lodash = require('lodash')
|
||||||
|
const request = require('request')
|
||||||
|
const log = require('../../../utils/util.log')
|
||||||
|
const matchUtil = require('../../../utils/util.match')
|
||||||
|
const pac = require('./source/pac')
|
||||||
|
|
||||||
let pacClient = null
|
let pacClient = null
|
||||||
|
|
||||||
function matched (hostname, overWallTargetMap) {
|
function matched (hostname, overWallTargetMap) {
|
||||||
|
@ -23,7 +24,7 @@ function matched (hostname, overWallTargetMap) {
|
||||||
if (pacClient == null) {
|
if (pacClient == null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const ret = pacClient.FindProxyForURL('https://' + hostname, hostname)
|
const ret = pacClient.FindProxyForURL(`https://${hostname}`, hostname)
|
||||||
if (ret && ret.indexOf('PROXY ') === 0) {
|
if (ret && ret.indexOf('PROXY ') === 0) {
|
||||||
log.info(`matchHostname: matched overwall: '${hostname}' -> '${ret}' in pac.txt`)
|
log.info(`matchHostname: matched overwall: '${hostname}' -> '${ret}' in pac.txt`)
|
||||||
return 'in pac.txt'
|
return 'in pac.txt'
|
||||||
|
@ -113,12 +114,12 @@ async function downloadPacAsync (pacConfig) {
|
||||||
// 尝试解析Base64(注:https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt 下载下来的是Base64格式)
|
// 尝试解析Base64(注:https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt 下载下来的是Base64格式)
|
||||||
let pacTxt = body
|
let pacTxt = body
|
||||||
try {
|
try {
|
||||||
if (pacTxt.indexOf('!---------------------EOF') < 0) {
|
if (!pacTxt.includes('!---------------------EOF')) {
|
||||||
pacTxt = Buffer.from(pacTxt, 'base64').toString('utf8')
|
pacTxt = Buffer.from(pacTxt, 'base64').toString('utf8')
|
||||||
// log.debug('解析 base64 后的 pax:', pacTxt)
|
// log.debug('解析 base64 后的 pax:', pacTxt)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (pacTxt.indexOf('!---------------------EOF') < 0) {
|
if (!pacTxt.includes('!---------------------EOF')) {
|
||||||
log.error(`远程 pac.txt 文件内容即不是base64格式,也不是要求的格式,url: ${remotePacFileUrl},body: ${body}`)
|
log.error(`远程 pac.txt 文件内容即不是base64格式,也不是要求的格式,url: ${remotePacFileUrl},body: ${body}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -181,7 +182,7 @@ function createOverwallMiddleware (overWallConfig) {
|
||||||
context.requestCount = {
|
context.requestCount = {
|
||||||
key: cacheKey,
|
key: cacheKey,
|
||||||
value: count.value,
|
value: count.value,
|
||||||
count
|
count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,10 +191,10 @@ function createOverwallMiddleware (overWallConfig) {
|
||||||
const port = server[domain].port
|
const port = server[domain].port
|
||||||
const path = server[domain].path
|
const path = server[domain].path
|
||||||
const password = server[domain].password
|
const password = server[domain].password
|
||||||
const proxyTarget = domain + '/' + path + '/' + hostname + req.url
|
const proxyTarget = `${domain}/${path}/${hostname}${req.url}`
|
||||||
|
|
||||||
// const backup = interceptOpt.backup
|
// const backup = interceptOpt.backup
|
||||||
const proxy = proxyTarget.indexOf('http:') === 0 || proxyTarget.indexOf('https:') === 0 ? proxyTarget : (rOptions.protocol + '//' + proxyTarget)
|
const proxy = proxyTarget.indexOf('http:') === 0 || proxyTarget.indexOf('https:') === 0 ? proxyTarget : (`${rOptions.protocol}//${proxyTarget}`)
|
||||||
// eslint-disable-next-line node/no-deprecated-api
|
// eslint-disable-next-line node/no-deprecated-api
|
||||||
const URL = url.parse(proxy)
|
const URL = url.parse(proxy)
|
||||||
rOptions.origional = lodash.cloneDeep(rOptions) // 备份原始请求参数
|
rOptions.origional = lodash.cloneDeep(rOptions) // 备份原始请求参数
|
||||||
|
@ -218,12 +219,12 @@ function createOverwallMiddleware (overWallConfig) {
|
||||||
res.setHeader('DS-Overwall', matchedResult)
|
res.setHeader('DS-Overwall', matchedResult)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getTmpPacFilePath,
|
getTmpPacFilePath,
|
||||||
downloadPacAsync,
|
downloadPacAsync,
|
||||||
createOverwallMiddleware
|
createOverwallMiddleware,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ function createPacClient (pacFilePath) {
|
||||||
|
|
||||||
const getRules = function (pacFilePath) {
|
const getRules = function (pacFilePath) {
|
||||||
let text = readFile(pacFilePath)
|
let text = readFile(pacFilePath)
|
||||||
if (text.indexOf('!---------------------EOF') < 0) {
|
if (!text.includes('!---------------------EOF')) {
|
||||||
text = Buffer.from(text, 'base64').toString()
|
text = Buffer.from(text, 'base64').toString()
|
||||||
}
|
}
|
||||||
const rules = []
|
const rules = []
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
const url = require('url')
|
const url = require('url')
|
||||||
|
const jsonApi = require('../../../json')
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
const DnsUtil = require('../../dns/index')
|
const DnsUtil = require('../../dns/index')
|
||||||
const localIP = '127.0.0.1'
|
|
||||||
const dnsLookup = require('./dnsLookup')
|
const dnsLookup = require('./dnsLookup')
|
||||||
const jsonApi = require('../../../json')
|
|
||||||
|
const localIP = '127.0.0.1'
|
||||||
|
|
||||||
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
||||||
for (const intercept of sslConnectInterceptors) {
|
for (const intercept of sslConnectInterceptors) {
|
||||||
|
@ -32,7 +33,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
||||||
return function connectHandler (req, cltSocket, head, ssl) {
|
return function connectHandler (req, cltSocket, head, ssl) {
|
||||||
// eslint-disable-next-line node/no-deprecated-api
|
// eslint-disable-next-line node/no-deprecated-api
|
||||||
let { hostname, port } = url.parse(`${ssl ? 'https' : 'http'}://${req.url}`)
|
let { hostname, port } = url.parse(`${ssl ? 'https' : 'http'}://${req.url}`)
|
||||||
port = parseInt(port)
|
port = Number.parseInt(port)
|
||||||
|
|
||||||
if (isSslConnect(sslConnectInterceptors, req, cltSocket, head)) {
|
if (isSslConnect(sslConnectInterceptors, req, cltSocket, head)) {
|
||||||
// 需要拦截,代替目标服务器,让客户端连接DS在本地启动的代理服务
|
// 需要拦截,代替目标服务器,让客户端连接DS在本地启动的代理服务
|
||||||
|
@ -104,7 +105,7 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig = null, isDire
|
||||||
const options = {
|
const options = {
|
||||||
port,
|
port,
|
||||||
host: hostname,
|
host: hostname,
|
||||||
connectTimeout: 10000
|
connectTimeout: 10000,
|
||||||
}
|
}
|
||||||
if (dnsConfig && dnsConfig.dnsMap) {
|
if (dnsConfig && dnsConfig.dnsMap) {
|
||||||
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
const dns = DnsUtil.hasDnsLookup(dnsConfig, hostname)
|
||||||
|
@ -114,12 +115,15 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig = null, isDire
|
||||||
}
|
}
|
||||||
// 代理连接事件监听
|
// 代理连接事件监听
|
||||||
const proxySocket = net.connect(options, () => {
|
const proxySocket = net.connect(options, () => {
|
||||||
if (!isDirect) log.info('Proxy connect start:', hostport)
|
if (!isDirect) {
|
||||||
else log.debug('Direct connect start:', hostport)
|
log.info('Proxy connect start:', hostport)
|
||||||
|
} else {
|
||||||
|
log.debug('Direct connect start:', hostport)
|
||||||
|
}
|
||||||
|
|
||||||
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
|
cltSocket.write('HTTP/1.1 200 Connection Established\r\n'
|
||||||
'Proxy-agent: dev-sidecar\r\n' +
|
+ 'Proxy-agent: dev-sidecar\r\n'
|
||||||
'\r\n')
|
+ '\r\n')
|
||||||
proxySocket.write(head)
|
proxySocket.write(head)
|
||||||
proxySocket.pipe(cltSocket)
|
proxySocket.pipe(cltSocket)
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const forge = require('node-forge')
|
const forge = require('node-forge')
|
||||||
const FakeServersCenter = require('../tls/FakeServersCenter')
|
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
|
const FakeServersCenter = require('../tls/FakeServersCenter')
|
||||||
|
|
||||||
module.exports = function createFakeServerCenter ({
|
module.exports = function createFakeServerCenter ({
|
||||||
maxLength,
|
maxLength,
|
||||||
caCertPath,
|
caCertPath,
|
||||||
caKeyPath,
|
caKeyPath,
|
||||||
requestHandler,
|
requestHandler,
|
||||||
upgradeHandler,
|
upgradeHandler,
|
||||||
getCertSocketTimeout
|
getCertSocketTimeout,
|
||||||
}) {
|
}) {
|
||||||
let caCert
|
let caCert
|
||||||
let caKey
|
let caKey
|
||||||
|
@ -30,6 +31,6 @@ module.exports = function createFakeServerCenter ({
|
||||||
maxLength,
|
maxLength,
|
||||||
requestHandler,
|
requestHandler,
|
||||||
upgradeHandler,
|
upgradeHandler,
|
||||||
getCertSocketTimeout
|
getCertSocketTimeout,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const https = require('https')
|
const https = require('https')
|
||||||
const commonUtil = require('../common/util')
|
|
||||||
const jsonApi = require('../../../json')
|
const jsonApi = require('../../../json')
|
||||||
// const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i
|
|
||||||
const DnsUtil = require('../../dns/index')
|
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
const RequestCounter = require('../../choice/RequestCounter')
|
const RequestCounter = require('../../choice/RequestCounter')
|
||||||
|
const commonUtil = require('../common/util')
|
||||||
|
// const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i
|
||||||
|
const DnsUtil = require('../../dns/index')
|
||||||
|
const compatible = require('../compatible/compatible')
|
||||||
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
||||||
const dnsLookup = require('./dnsLookup')
|
const dnsLookup = require('./dnsLookup')
|
||||||
const compatible = require('../compatible/compatible')
|
|
||||||
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
||||||
|
|
||||||
// create requestHandler function
|
// create requestHandler function
|
||||||
|
@ -31,16 +32,16 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
rOptions,
|
rOptions,
|
||||||
log,
|
log,
|
||||||
RequestCounter,
|
RequestCounter,
|
||||||
setting
|
setting,
|
||||||
}
|
}
|
||||||
let interceptors = createIntercepts(context)
|
let interceptors = createIntercepts(context)
|
||||||
if (interceptors == null) {
|
if (interceptors == null) {
|
||||||
interceptors = []
|
interceptors = []
|
||||||
}
|
}
|
||||||
const reqIncpts = interceptors.filter(item => {
|
const reqIncpts = interceptors.filter((item) => {
|
||||||
return item.requestIntercept != null
|
return item.requestIntercept != null
|
||||||
})
|
})
|
||||||
const resIncpts = interceptors.filter(item => {
|
const resIncpts = interceptors.filter((item) => {
|
||||||
return item.responseIntercept != null
|
return item.responseIntercept != null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -63,7 +64,9 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
}
|
}
|
||||||
const goNext = reqIncpt.requestIntercept(context, req, res, ssl, next)
|
const goNext = reqIncpt.requestIntercept(context, req, res, ssl, next)
|
||||||
if (goNext) {
|
if (goNext) {
|
||||||
if (goNext !== 'no-next') next()
|
if (goNext !== 'no-next') {
|
||||||
|
next()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +110,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
function onFree () {
|
function onFree () {
|
||||||
url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`
|
url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`
|
||||||
const start = new Date()
|
const start = new Date()
|
||||||
log.info('发起代理请求:', url, (rOptions.servername ? ', sni: ' + rOptions.servername : ''), ', headers:', jsonApi.stringify2(rOptions.headers))
|
log.info('发起代理请求:', url, (rOptions.servername ? `, sni: ${rOptions.servername}` : ''), ', headers:', jsonApi.stringify2(rOptions.headers))
|
||||||
|
|
||||||
const isDnsIntercept = {}
|
const isDnsIntercept = {}
|
||||||
if (dnsConfig && dnsConfig.dnsMap) {
|
if (dnsConfig && dnsConfig.dnsMap) {
|
||||||
|
@ -181,7 +184,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
proxyReq.on('error', (e) => {
|
proxyReq.on('error', (e) => {
|
||||||
const cost = new Date() - start
|
const cost = new Date() - start
|
||||||
log.error(`代理请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
log.error(`代理请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||||
countSlow(isDnsIntercept, '代理请求错误: ' + e.message)
|
countSlow(isDnsIntercept, `代理请求错误: ${e.message}`)
|
||||||
reject(e)
|
reject(e)
|
||||||
|
|
||||||
// 自动兼容程序:2
|
// 自动兼容程序:2
|
||||||
|
@ -205,7 +208,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
})
|
})
|
||||||
|
|
||||||
// 原始请求的事件监听
|
// 原始请求的事件监听
|
||||||
req.on('aborted', function () {
|
req.on('aborted', () => {
|
||||||
const cost = new Date() - start
|
const cost = new Date() - start
|
||||||
const errorMsg = `请求被取消: ${url}, cost: ${cost} ms`
|
const errorMsg = `请求被取消: ${url}, cost: ${cost} ms`
|
||||||
log.error(errorMsg, ', rOptions:', jsonApi.stringify2(rOptions))
|
log.error(errorMsg, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||||
|
@ -215,7 +218,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
}
|
}
|
||||||
reject(new Error(errorMsg))
|
reject(new Error(errorMsg))
|
||||||
})
|
})
|
||||||
req.on('error', function (e, req, res) {
|
req.on('error', (e, req, res) => {
|
||||||
const cost = new Date() - start
|
const cost = new Date() - start
|
||||||
log.error(`请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
log.error(`请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||||
reject(e)
|
reject(e)
|
||||||
|
@ -246,7 +249,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
// // console.log('BODY: ')
|
// // console.log('BODY: ')
|
||||||
// })
|
// })
|
||||||
proxyRes.on('error', (error) => {
|
proxyRes.on('error', (error) => {
|
||||||
countSlow(null, 'error: ' + error.message)
|
countSlow(null, `error: ${error.message}`)
|
||||||
log.error(`proxy res error: ${url}, error:`, error)
|
log.error(`proxy res error: ${url}, error:`, error)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -287,7 +290,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
}
|
}
|
||||||
InsertScriptMiddleware.responseInterceptor(req, res, proxyReq, proxyRes, ssl, next, {
|
InsertScriptMiddleware.responseInterceptor(req, res, proxyReq, proxyRes, ssl, next, {
|
||||||
head,
|
head,
|
||||||
body
|
body,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
next()
|
next()
|
||||||
|
@ -300,7 +303,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
await responseInterceptorPromise
|
await responseInterceptorPromise
|
||||||
|
|
||||||
if (!res.headersSent) { // prevent duplicate set headers
|
if (!res.headersSent) { // prevent duplicate set headers
|
||||||
Object.keys(proxyRes.headers).forEach(function (key) {
|
Object.keys(proxyRes.headers).forEach((key) => {
|
||||||
if (proxyRes.headers[key] !== undefined) {
|
if (proxyRes.headers[key] !== undefined) {
|
||||||
// https://github.com/nodejitsu/node-http-proxy/issues/362
|
// https://github.com/nodejitsu/node-http-proxy/issues/362
|
||||||
if (/^www-authenticate$/i.test(key)) {
|
if (/^www-authenticate$/i.test(key)) {
|
||||||
|
@ -314,19 +317,19 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
})
|
})
|
||||||
|
|
||||||
if (proxyRes.statusCode >= 400) {
|
if (proxyRes.statusCode >= 400) {
|
||||||
countSlow(null, 'Status return: ' + proxyRes.statusCode)
|
countSlow(null, `Status return: ${proxyRes.statusCode}`)
|
||||||
}
|
}
|
||||||
res.writeHead(proxyRes.statusCode)
|
res.writeHead(proxyRes.statusCode)
|
||||||
proxyRes.pipe(res)
|
proxyRes.pipe(res)
|
||||||
}
|
}
|
||||||
})().catch(e => {
|
})().catch((e) => {
|
||||||
if (!res.writableEnded) {
|
if (!res.writableEnded) {
|
||||||
try {
|
try {
|
||||||
const status = e.status || 500
|
const status = e.status || 500
|
||||||
res.writeHead(status, { 'Content-Type': 'text/html;charset=UTF8' })
|
res.writeHead(status, { 'Content-Type': 'text/html;charset=UTF8' })
|
||||||
res.write(`DevSidecar Error:<br/>
|
res.write(`DevSidecar Error:<br/>
|
||||||
目标网站请求错误:【${e.code}】 ${e.message}<br/>
|
目标网站请求错误:【${e.code}】 ${e.message}<br/>
|
||||||
目标地址:${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`
|
目标地址:${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`,
|
||||||
)
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -343,7 +346,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
||||||
const ignoreErrors = [
|
const ignoreErrors = [
|
||||||
'代理请求错误: ',
|
'代理请求错误: ',
|
||||||
'代理请求超时: ',
|
'代理请求超时: ',
|
||||||
'代理请求被取消: '
|
'代理请求被取消: ',
|
||||||
]
|
]
|
||||||
for (const ignoreError of ignoreErrors) {
|
for (const ignoreError of ignoreErrors) {
|
||||||
if (e.message.startsWith(ignoreError)) {
|
if (e.message.startsWith(ignoreError)) {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const https = require('https')
|
const https = require('https')
|
||||||
const util = require('../common/util')
|
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
|
const util = require('../common/util')
|
||||||
|
|
||||||
// copy from node-http-proxy. ^_^
|
// copy from node-http-proxy. ^_^
|
||||||
|
|
||||||
// create connectHandler function
|
// create connectHandler function
|
||||||
|
@ -13,17 +14,19 @@ module.exports = function createUpgradeHandler (serverSetting) {
|
||||||
proxyReq.on('error', (e) => {
|
proxyReq.on('error', (e) => {
|
||||||
log.error('upgradeHandler error:', e)
|
log.error('upgradeHandler error:', e)
|
||||||
})
|
})
|
||||||
proxyReq.on('response', function (res) {
|
proxyReq.on('response', (res) => {
|
||||||
// if upgrade event isn't going to happen, close the socket
|
// if upgrade event isn't going to happen, close the socket
|
||||||
if (!res.upgrade) cltSocket.end()
|
if (!res.upgrade) {
|
||||||
|
cltSocket.end()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
proxyReq.on('upgrade', function (proxyRes, proxySocket, proxyHead) {
|
proxyReq.on('upgrade', (proxyRes, proxySocket, proxyHead) => {
|
||||||
proxySocket.on('error', (e) => {
|
proxySocket.on('error', (e) => {
|
||||||
log.error('upgrade error:', e)
|
log.error('upgrade error:', e)
|
||||||
})
|
})
|
||||||
|
|
||||||
cltSocket.on('error', function (e) {
|
cltSocket.on('error', (e) => {
|
||||||
log.error('upgrade socket error:', e)
|
log.error('upgrade socket error:', e)
|
||||||
proxySocket.end()
|
proxySocket.end()
|
||||||
})
|
})
|
||||||
|
@ -33,23 +36,24 @@ module.exports = function createUpgradeHandler (serverSetting) {
|
||||||
|
|
||||||
proxySocket.setKeepAlive(true, 0)
|
proxySocket.setKeepAlive(true, 0)
|
||||||
|
|
||||||
if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead)
|
if (proxyHead && proxyHead.length) {
|
||||||
|
proxySocket.unshift(proxyHead)
|
||||||
|
}
|
||||||
|
|
||||||
cltSocket.write(
|
cltSocket.write(
|
||||||
Object.keys(proxyRes.headers).reduce(function (head, key) {
|
`${Object.keys(proxyRes.headers).reduce((head, key) => {
|
||||||
const value = proxyRes.headers[key]
|
const value = proxyRes.headers[key]
|
||||||
|
|
||||||
if (!Array.isArray(value)) {
|
if (!Array.isArray(value)) {
|
||||||
head.push(key + ': ' + value)
|
head.push(`${key}: ${value}`)
|
||||||
return head
|
return head
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
head.push(key + ': ' + value[i])
|
head.push(`${key}: ${value[i]}`)
|
||||||
}
|
}
|
||||||
return head
|
return head
|
||||||
}, ['HTTP/1.1 101 Switching Protocols'])
|
}, ['HTTP/1.1 101 Switching Protocols']).join('\r\n')}\r\n\r\n`,
|
||||||
.join('\r\n') + '\r\n\r\n'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
proxySocket.pipe(cltSocket).pipe(proxySocket)
|
proxySocket.pipe(cltSocket).pipe(proxySocket)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const speedTest = require('../../speed')
|
|
||||||
const log = require('../../../utils/util.log')
|
|
||||||
const defaultDns = require('dns')
|
const defaultDns = require('dns')
|
||||||
|
const log = require('../../../utils/util.log')
|
||||||
|
const speedTest = require('../../speed')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createLookupFunc: function (res, dns, action, target, isDnsIntercept) {
|
createLookupFunc (res, dns, action, target, isDnsIntercept) {
|
||||||
target = target ? (', target: ' + target) : ''
|
target = target ? (`, target: ${target}`) : ''
|
||||||
|
|
||||||
return (hostname, options, callback) => {
|
return (hostname, options, callback) => {
|
||||||
const tester = speedTest.getSpeedTester(hostname)
|
const tester = speedTest.getSpeedTester(hostname)
|
||||||
|
@ -12,14 +12,16 @@ module.exports = {
|
||||||
const aliveIpObj = tester.pickFastAliveIpObj()
|
const aliveIpObj = tester.pickFastAliveIpObj()
|
||||||
if (aliveIpObj) {
|
if (aliveIpObj) {
|
||||||
log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`)
|
log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`)
|
||||||
if (res) res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`)
|
if (res) {
|
||||||
|
res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`)
|
||||||
|
}
|
||||||
callback(null, aliveIpObj.host, 4)
|
callback(null, aliveIpObj.host, 4)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`)
|
log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dns.lookup(hostname).then(ip => {
|
dns.lookup(hostname).then((ip) => {
|
||||||
if (isDnsIntercept) {
|
if (isDnsIntercept) {
|
||||||
isDnsIntercept.dns = dns
|
isDnsIntercept.dns = dns
|
||||||
isDnsIntercept.hostname = hostname
|
isDnsIntercept.hostname = hostname
|
||||||
|
@ -42,7 +44,9 @@ module.exports = {
|
||||||
}
|
}
|
||||||
if (isTestFailedIp === false) {
|
if (isTestFailedIp === false) {
|
||||||
log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.name}': ${ip}${target} -----`)
|
log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.name}': ${ip}${target} -----`)
|
||||||
if (res) res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.name === '预设IP' ? 'PreSet' : dns.name}`)
|
if (res) {
|
||||||
|
res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.name === '预设IP' ? 'PreSet' : dns.name}`)
|
||||||
|
}
|
||||||
callback(null, ip, 4)
|
callback(null, ip, 4)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,5 +60,5 @@ module.exports = {
|
||||||
defaultDns.lookup(hostname, options, callback)
|
defaultDns.lookup(hostname, options, callback)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const tlsUtils = require('../tls/tlsUtils')
|
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const config = require('../common/config')
|
|
||||||
const log = require('../../../utils/util.log')
|
const log = require('../../../utils/util.log')
|
||||||
const createRequestHandler = require('./createRequestHandler')
|
const speedTest = require('../../speed/index.js')
|
||||||
|
const config = require('../common/config')
|
||||||
|
const tlsUtils = require('../tls/tlsUtils')
|
||||||
const createConnectHandler = require('./createConnectHandler')
|
const createConnectHandler = require('./createConnectHandler')
|
||||||
const createFakeServerCenter = require('./createFakeServerCenter')
|
const createFakeServerCenter = require('./createFakeServerCenter')
|
||||||
|
const createRequestHandler = require('./createRequestHandler')
|
||||||
const createUpgradeHandler = require('./createUpgradeHandler')
|
const createUpgradeHandler = require('./createUpgradeHandler')
|
||||||
const speedTest = require('../../speed/index.js')
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createProxy ({
|
createProxy ({
|
||||||
host = config.defaultHost,
|
host = config.defaultHost,
|
||||||
|
@ -21,7 +22,7 @@ module.exports = {
|
||||||
externalProxy,
|
externalProxy,
|
||||||
dnsConfig,
|
dnsConfig,
|
||||||
setting,
|
setting,
|
||||||
compatibleConfig
|
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'
|
||||||
|
@ -59,7 +60,7 @@ module.exports = {
|
||||||
externalProxy,
|
externalProxy,
|
||||||
dnsConfig,
|
dnsConfig,
|
||||||
setting,
|
setting,
|
||||||
compatibleConfig
|
compatibleConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
const upgradeHandler = createUpgradeHandler(setting)
|
const upgradeHandler = createUpgradeHandler(setting)
|
||||||
|
@ -70,7 +71,7 @@ module.exports = {
|
||||||
caKeyPath,
|
caKeyPath,
|
||||||
requestHandler,
|
requestHandler,
|
||||||
upgradeHandler,
|
upgradeHandler,
|
||||||
getCertSocketTimeout
|
getCertSocketTimeout,
|
||||||
})
|
})
|
||||||
|
|
||||||
const connectHandler = createConnectHandler(
|
const connectHandler = createConnectHandler(
|
||||||
|
@ -78,7 +79,7 @@ module.exports = {
|
||||||
middlewares,
|
middlewares,
|
||||||
fakeServersCenter,
|
fakeServersCenter,
|
||||||
dnsConfig,
|
dnsConfig,
|
||||||
compatibleConfig
|
compatibleConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
// 创建监听方法,用于监听 http 和 https 两个端口
|
// 创建监听方法,用于监听 http 和 https 两个端口
|
||||||
|
@ -87,16 +88,20 @@ module.exports = {
|
||||||
server.listen(port, host, () => {
|
server.listen(port, host, () => {
|
||||||
log.info(`dev-sidecar启动 ${ssl ? 'https' : 'http'} 端口: ${host}:${port}`)
|
log.info(`dev-sidecar启动 ${ssl ? 'https' : 'http'} 端口: ${host}:${port}`)
|
||||||
server.on('request', (req, res) => {
|
server.on('request', (req, res) => {
|
||||||
if (printDebugLog) log.debug(`【server request, ssl: ${ssl}】\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
|
if (printDebugLog) {
|
||||||
|
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
|
// tunneling for https
|
||||||
server.on('connect', (req, cltSocket, head) => {
|
server.on('connect', (req, cltSocket, head) => {
|
||||||
if (printDebugLog) log.debug(`【server connect, ssl: ${ssl}】\r\n----- req -----\r\n`, req, '\r\n----- cltSocket -----\r\n', cltSocket, '\r\n----- head -----\r\n', head)
|
if (printDebugLog) {
|
||||||
|
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)
|
connectHandler(req, cltSocket, head, ssl)
|
||||||
})
|
})
|
||||||
// TODO: handler WebSocket
|
// TODO: handler WebSocket
|
||||||
server.on('upgrade', function (req, cltSocket, head) {
|
server.on('upgrade', (req, cltSocket, head) => {
|
||||||
if (printDebugLog) {
|
if (printDebugLog) {
|
||||||
log.debug(`【server upgrade, ssl: ${ssl}】\r\n----- req -----\r\n`, req)
|
log.debug(`【server upgrade, ssl: ${ssl}】\r\n----- req -----\r\n`, req)
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,5 +159,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
createCA (caPaths) {
|
createCA (caPaths) {
|
||||||
return tlsUtils.initCA(caPaths)
|
return tlsUtils.initCA(caPaths)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ module.exports = class CertAndKeyContainer {
|
||||||
maxLength = 1000,
|
maxLength = 1000,
|
||||||
getCertSocketTimeout = 2 * 1000,
|
getCertSocketTimeout = 2 * 1000,
|
||||||
caCert,
|
caCert,
|
||||||
caKey
|
caKey,
|
||||||
}) {
|
}) {
|
||||||
this.queue = []
|
this.queue = []
|
||||||
this.maxLength = maxLength
|
this.maxLength = maxLength
|
||||||
|
@ -50,7 +50,7 @@ module.exports = class CertAndKeyContainer {
|
||||||
|
|
||||||
const certPromiseObj = {
|
const certPromiseObj = {
|
||||||
port,
|
port,
|
||||||
mappingHostNames: [hostname] // temporary hostname
|
mappingHostNames: [hostname], // temporary hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
const https = require('https')
|
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const tlsUtils = require('./tlsUtils')
|
const https = require('https')
|
||||||
const CertAndKeyContainer = require('./CertAndKeyContainer')
|
|
||||||
const forge = require('node-forge')
|
const forge = require('node-forge')
|
||||||
|
const CertAndKeyContainer = require('./CertAndKeyContainer')
|
||||||
|
const tlsUtils = require('./tlsUtils')
|
||||||
|
|
||||||
const pki = forge.pki
|
const pki = forge.pki
|
||||||
// const colors = require('colors')
|
// const colors = require('colors')
|
||||||
const tls = require('tls')
|
const tls = require('tls')
|
||||||
|
@ -27,7 +28,7 @@ module.exports = class FakeServersCenter {
|
||||||
this.certAndKeyContainer = new CertAndKeyContainer({
|
this.certAndKeyContainer = new CertAndKeyContainer({
|
||||||
getCertSocketTimeout,
|
getCertSocketTimeout,
|
||||||
caCert,
|
caCert,
|
||||||
caKey
|
caKey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ module.exports = class FakeServersCenter {
|
||||||
const serverPromiseObj = {
|
const serverPromiseObj = {
|
||||||
port,
|
port,
|
||||||
ssl,
|
ssl,
|
||||||
mappingHostNames: [hostname] // temporary hostname
|
mappingHostNames: [hostname], // temporary hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
@ -99,10 +100,10 @@ module.exports = class FakeServersCenter {
|
||||||
log.info(`fakeServer SNICallback: ${hostname}:${port}`)
|
log.info(`fakeServer SNICallback: ${hostname}:${port}`)
|
||||||
done(null, tls.createSecureContext({
|
done(null, tls.createSecureContext({
|
||||||
key: pki.privateKeyToPem(certObj.key),
|
key: pki.privateKeyToPem(certObj.key),
|
||||||
cert: pki.certificateToPem(certObj.cert)
|
cert: pki.certificateToPem(certObj.cert),
|
||||||
}))
|
}))
|
||||||
})()
|
})()
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
fakeServer = new http.Server()
|
fakeServer = new http.Server()
|
||||||
|
@ -111,7 +112,7 @@ module.exports = class FakeServersCenter {
|
||||||
cert,
|
cert,
|
||||||
key,
|
key,
|
||||||
server: fakeServer,
|
server: fakeServer,
|
||||||
port: 0 // if port === 0 ,should listen server's `listening` event.
|
port: 0, // if port === 0 ,should listen server's `listening` event.
|
||||||
}
|
}
|
||||||
serverPromiseObj.serverObj = serverObj
|
serverPromiseObj.serverObj = serverObj
|
||||||
|
|
||||||
|
@ -121,12 +122,16 @@ module.exports = class FakeServersCenter {
|
||||||
serverObj.port = address.port
|
serverObj.port = address.port
|
||||||
})
|
})
|
||||||
fakeServer.on('request', (req, res) => {
|
fakeServer.on('request', (req, res) => {
|
||||||
if (printDebugLog) log.debug(`【fakeServer request - ${hostname}:${port}】\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
|
if (printDebugLog) {
|
||||||
|
log.debug(`【fakeServer request - ${hostname}:${port}】\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
|
||||||
|
}
|
||||||
this.requestHandler(req, res, ssl)
|
this.requestHandler(req, res, ssl)
|
||||||
})
|
})
|
||||||
let once = true
|
let once = true
|
||||||
fakeServer.on('listening', () => {
|
fakeServer.on('listening', () => {
|
||||||
if (printDebugLog) log.debug(`【fakeServer listening - ${hostname}:${port}】no arguments...`)
|
if (printDebugLog) {
|
||||||
|
log.debug(`【fakeServer listening - ${hostname}:${port}】no arguments...`)
|
||||||
|
}
|
||||||
if (cert && once) {
|
if (cert && once) {
|
||||||
once = false
|
once = false
|
||||||
let newMappingHostNames = tlsUtils.getMappingHostNamesFromCert(cert)
|
let newMappingHostNames = tlsUtils.getMappingHostNamesFromCert(cert)
|
||||||
|
|
|
@ -69,28 +69,38 @@ module.exports = function extractSNI (data) {
|
||||||
pos += 32
|
pos += 32
|
||||||
|
|
||||||
// skip SessionID
|
// skip SessionID
|
||||||
if (pos > end - 1) return null
|
if (pos > end - 1) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const sessionIdLength = data[pos]
|
const sessionIdLength = data[pos]
|
||||||
pos += 1 + sessionIdLength
|
pos += 1 + sessionIdLength
|
||||||
|
|
||||||
// skip CipherSuite
|
// skip CipherSuite
|
||||||
if (pos > end - 2) return null
|
if (pos > end - 2) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const cipherSuiteLength = data[pos] << 8 | data[pos + 1]
|
const cipherSuiteLength = data[pos] << 8 | data[pos + 1]
|
||||||
pos += 2 + cipherSuiteLength
|
pos += 2 + cipherSuiteLength
|
||||||
|
|
||||||
// skip CompressionMethod
|
// skip CompressionMethod
|
||||||
if (pos > end - 1) return null
|
if (pos > end - 1) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const compressionMethodLength = data[pos]
|
const compressionMethodLength = data[pos]
|
||||||
pos += 1 + compressionMethodLength
|
pos += 1 + compressionMethodLength
|
||||||
|
|
||||||
// verify extensions exist
|
// verify extensions exist
|
||||||
if (pos > end - 2) return null
|
if (pos > end - 2) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const extensionsLength = data[pos] << 8 | data[pos + 1]
|
const extensionsLength = data[pos] << 8 | data[pos + 1]
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
// verify the extensions fit
|
// verify the extensions fit
|
||||||
const extensionsEnd = pos + extensionsLength
|
const extensionsEnd = pos + extensionsLength
|
||||||
if (extensionsEnd > end) return null
|
if (extensionsEnd > end) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
end = extensionsEnd
|
end = extensionsEnd
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -129,14 +139,18 @@ module.exports = function extractSNI (data) {
|
||||||
pos += 4
|
pos += 4
|
||||||
if (extensionType === 0) { // ExtensionType was server_name(0)
|
if (extensionType === 0) { // ExtensionType was server_name(0)
|
||||||
// read ServerNameList length
|
// read ServerNameList length
|
||||||
if (pos > end - 2) return null
|
if (pos > end - 2) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
const nameListLength = data[pos] << 8 | data[pos + 1]
|
const nameListLength = data[pos] << 8 | data[pos + 1]
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
// verify we have enough bytes and loop over SeverNameList
|
// verify we have enough bytes and loop over SeverNameList
|
||||||
let n = pos
|
let n = pos
|
||||||
pos += nameListLength
|
pos += nameListLength
|
||||||
if (pos > end) return null
|
if (pos > end) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
while (n < pos - 3) {
|
while (n < pos - 3) {
|
||||||
const nameType = data[n]
|
const nameType = data[n]
|
||||||
const nameLength = data[n + 1] << 8 | data[n + 2]
|
const nameLength = data[n + 1] << 8 | data[n + 2]
|
||||||
|
@ -145,7 +159,9 @@ module.exports = function extractSNI (data) {
|
||||||
// check if NameType is host_name(0)
|
// check if NameType is host_name(0)
|
||||||
if (nameType === 0) {
|
if (nameType === 0) {
|
||||||
// verify we have enough bytes
|
// verify we have enough bytes
|
||||||
if (n > end - nameLength) return null
|
if (n > end - nameLength) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
// decode as ascii and return
|
// decode as ascii and return
|
||||||
|
|
||||||
|
@ -154,7 +170,7 @@ module.exports = function extractSNI (data) {
|
||||||
sniName,
|
sniName,
|
||||||
start: n,
|
start: n,
|
||||||
end: n + nameLength,
|
end: n + nameLength,
|
||||||
length: nameLength
|
length: nameLength,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n += nameLength
|
n += nameLength
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const forge = require('node-forge')
|
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const log = require('../../../utils/util.log')
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const config = require('../common/config')
|
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const mkdirp = require('mkdirp')
|
const mkdirp = require('mkdirp')
|
||||||
|
const forge = require('node-forge')
|
||||||
|
const log = require('../../../utils/util.log')
|
||||||
|
const config = require('../common/config')
|
||||||
// const colors = require('colors')
|
// const colors = require('colors')
|
||||||
|
|
||||||
const utils = exports
|
const utils = exports
|
||||||
|
@ -23,43 +23,41 @@ utils.createCA = function (CN) {
|
||||||
const keys = pki.rsa.generateKeyPair(2048)
|
const keys = pki.rsa.generateKeyPair(2048)
|
||||||
const cert = pki.createCertificate()
|
const cert = pki.createCertificate()
|
||||||
cert.publicKey = keys.publicKey
|
cert.publicKey = keys.publicKey
|
||||||
cert.serialNumber = (new Date()).getTime() + ''
|
cert.serialNumber = `${(new Date()).getTime()}`
|
||||||
cert.validity.notBefore = new Date(new Date() - (60 * 60 * 1000))
|
cert.validity.notBefore = new Date(new Date() - (60 * 60 * 1000))
|
||||||
cert.validity.notAfter = new Date()
|
cert.validity.notAfter = new Date()
|
||||||
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20)
|
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20)
|
||||||
const attrs = [{
|
const attrs = [{
|
||||||
name: 'commonName',
|
name: 'commonName',
|
||||||
value: CN
|
value: CN,
|
||||||
}, {
|
}, {
|
||||||
name: 'countryName',
|
name: 'countryName',
|
||||||
value: 'CN'
|
value: 'CN',
|
||||||
}, {
|
}, {
|
||||||
shortName: 'ST',
|
shortName: 'ST',
|
||||||
value: 'GuangDong'
|
value: 'GuangDong',
|
||||||
}, {
|
}, {
|
||||||
name: 'localityName',
|
name: 'localityName',
|
||||||
value: 'ShenZhen'
|
value: 'ShenZhen',
|
||||||
}, {
|
}, {
|
||||||
name: 'organizationName',
|
name: 'organizationName',
|
||||||
value: 'dev-sidecar'
|
value: 'dev-sidecar',
|
||||||
}, {
|
}, {
|
||||||
shortName: 'OU',
|
shortName: 'OU',
|
||||||
value: 'https://github.com/docmirror/dev-sidecar'
|
value: 'https://github.com/docmirror/dev-sidecar',
|
||||||
}]
|
}]
|
||||||
cert.setSubject(attrs)
|
cert.setSubject(attrs)
|
||||||
cert.setIssuer(attrs)
|
cert.setIssuer(attrs)
|
||||||
cert.setExtensions([{
|
cert.setExtensions([{
|
||||||
name: 'basicConstraints',
|
name: 'basicConstraints',
|
||||||
critical: true,
|
critical: true,
|
||||||
cA: true
|
cA: true,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
name: 'keyUsage',
|
name: 'keyUsage',
|
||||||
critical: true,
|
critical: true,
|
||||||
keyCertSign: true
|
keyCertSign: true,
|
||||||
},
|
}, {
|
||||||
{
|
name: 'subjectKeyIdentifier',
|
||||||
name: 'subjectKeyIdentifier'
|
|
||||||
}])
|
}])
|
||||||
|
|
||||||
// self-sign certificate
|
// self-sign certificate
|
||||||
|
@ -67,7 +65,7 @@ utils.createCA = function (CN) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: keys.privateKey,
|
key: keys.privateKey,
|
||||||
cert: cert
|
cert,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,29 +79,29 @@ utils.createFakeCertificateByDomain = function (caKey, caCert, domain) {
|
||||||
const cert = pki.createCertificate()
|
const cert = pki.createCertificate()
|
||||||
cert.publicKey = keys.publicKey
|
cert.publicKey = keys.publicKey
|
||||||
|
|
||||||
cert.serialNumber = (new Date()).getTime() + ''
|
cert.serialNumber = `${(new Date()).getTime()}`
|
||||||
cert.validity.notBefore = new Date()
|
cert.validity.notBefore = new Date()
|
||||||
cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1)
|
cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1)
|
||||||
cert.validity.notAfter = new Date()
|
cert.validity.notAfter = new Date()
|
||||||
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 1)
|
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 1)
|
||||||
const attrs = [{
|
const attrs = [{
|
||||||
name: 'commonName',
|
name: 'commonName',
|
||||||
value: domain
|
value: domain,
|
||||||
}, {
|
}, {
|
||||||
name: 'countryName',
|
name: 'countryName',
|
||||||
value: 'CN'
|
value: 'CN',
|
||||||
}, {
|
}, {
|
||||||
shortName: 'ST',
|
shortName: 'ST',
|
||||||
value: 'GuangDong'
|
value: 'GuangDong',
|
||||||
}, {
|
}, {
|
||||||
name: 'localityName',
|
name: 'localityName',
|
||||||
value: 'ShenZhen'
|
value: 'ShenZhen',
|
||||||
}, {
|
}, {
|
||||||
name: 'organizationName',
|
name: 'organizationName',
|
||||||
value: 'dev-sidecar'
|
value: 'dev-sidecar',
|
||||||
}, {
|
}, {
|
||||||
shortName: 'OU',
|
shortName: 'OU',
|
||||||
value: 'https://github.com/docmirror/dev-sidecar'
|
value: 'https://github.com/docmirror/dev-sidecar',
|
||||||
}]
|
}]
|
||||||
|
|
||||||
cert.setIssuer(caCert.subject.attributes)
|
cert.setIssuer(caCert.subject.attributes)
|
||||||
|
@ -112,7 +110,7 @@ utils.createFakeCertificateByDomain = function (caKey, caCert, domain) {
|
||||||
cert.setExtensions([{
|
cert.setExtensions([{
|
||||||
name: 'basicConstraints',
|
name: 'basicConstraints',
|
||||||
critical: true,
|
critical: true,
|
||||||
cA: false
|
cA: false,
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// name: 'keyUsage',
|
// name: 'keyUsage',
|
||||||
|
@ -131,28 +129,25 @@ utils.createFakeCertificateByDomain = function (caKey, caCert, domain) {
|
||||||
name: 'subjectAltName',
|
name: 'subjectAltName',
|
||||||
altNames: [{
|
altNames: [{
|
||||||
type: 2,
|
type: 2,
|
||||||
value: domain
|
value: domain,
|
||||||
}]
|
}],
|
||||||
},
|
}, {
|
||||||
{
|
name: 'subjectKeyIdentifier',
|
||||||
name: 'subjectKeyIdentifier'
|
}, {
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extKeyUsage',
|
name: 'extKeyUsage',
|
||||||
serverAuth: true,
|
serverAuth: true,
|
||||||
clientAuth: true,
|
clientAuth: true,
|
||||||
codeSigning: true,
|
codeSigning: true,
|
||||||
emailProtection: true,
|
emailProtection: true,
|
||||||
timeStamping: true
|
timeStamping: true,
|
||||||
},
|
}, {
|
||||||
{
|
name: 'authorityKeyIdentifier',
|
||||||
name: 'authorityKeyIdentifier'
|
|
||||||
}])
|
}])
|
||||||
cert.sign(caKey, forge.md.sha256.create())
|
cert.sign(caKey, forge.md.sha256.create())
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: keys.privateKey,
|
key: keys.privateKey,
|
||||||
cert: cert
|
cert,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,9 +173,8 @@ utils.createFakeCertificateByCA = function (caKey, caCert, originCertificate) {
|
||||||
cert.setExtensions([{
|
cert.setExtensions([{
|
||||||
name: 'basicConstraints',
|
name: 'basicConstraints',
|
||||||
critical: true,
|
critical: true,
|
||||||
cA: false
|
cA: false,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
name: 'keyUsage',
|
name: 'keyUsage',
|
||||||
critical: true,
|
critical: true,
|
||||||
digitalSignature: true,
|
digitalSignature: true,
|
||||||
|
@ -191,31 +185,27 @@ utils.createFakeCertificateByCA = function (caKey, caCert, originCertificate) {
|
||||||
keyCertSign: true,
|
keyCertSign: true,
|
||||||
cRLSign: true,
|
cRLSign: true,
|
||||||
encipherOnly: true,
|
encipherOnly: true,
|
||||||
decipherOnly: true
|
decipherOnly: true,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
name: 'subjectAltName',
|
name: 'subjectAltName',
|
||||||
altNames: subjectAltName.altNames
|
altNames: subjectAltName.altNames,
|
||||||
},
|
}, {
|
||||||
{
|
name: 'subjectKeyIdentifier',
|
||||||
name: 'subjectKeyIdentifier'
|
}, {
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'extKeyUsage',
|
name: 'extKeyUsage',
|
||||||
serverAuth: true,
|
serverAuth: true,
|
||||||
clientAuth: true,
|
clientAuth: true,
|
||||||
codeSigning: true,
|
codeSigning: true,
|
||||||
emailProtection: true,
|
emailProtection: true,
|
||||||
timeStamping: true
|
timeStamping: true,
|
||||||
},
|
}, {
|
||||||
{
|
name: 'authorityKeyIdentifier',
|
||||||
name: 'authorityKeyIdentifier'
|
|
||||||
}])
|
}])
|
||||||
cert.sign(caKey, forge.md.sha256.create())
|
cert.sign(caKey, forge.md.sha256.create())
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: keys.privateKey,
|
key: keys.privateKey,
|
||||||
cert: cert
|
cert,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +221,7 @@ utils.isMappingHostName = function (DNSName, hostname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let reg = DNSName.replace(/\./g, '\\.').replace(/\*/g, '[^.]+')
|
let reg = DNSName.replace(/\./g, '\\.').replace(/\*/g, '[^.]+')
|
||||||
reg = '^' + reg + '$'
|
reg = `^${reg}$`
|
||||||
return (new RegExp(reg)).test(hostname)
|
return (new RegExp(reg)).test(hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +243,7 @@ utils.initCA = function ({ caCertPath, caKeyPath }) {
|
||||||
return {
|
return {
|
||||||
caCertPath,
|
caCertPath,
|
||||||
caKeyPath,
|
caKeyPath,
|
||||||
create: false
|
create: false,
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const caObj = utils.createCA(config.caName)
|
const caObj = utils.createCA(config.caName)
|
||||||
|
@ -272,6 +262,6 @@ utils.initCA = function ({ caCertPath, caKeyPath }) {
|
||||||
return {
|
return {
|
||||||
caCertPath,
|
caCertPath,
|
||||||
caKeyPath,
|
caKeyPath,
|
||||||
create: true
|
create: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// 1个小时不访问,取消获取
|
// 1个小时不访问,取消获取
|
||||||
const _ = require('lodash')
|
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
const config = require('./config.js')
|
const _ = require('lodash')
|
||||||
const log = require('../../utils/util.log.js')
|
const log = require('../../utils/util.log.js')
|
||||||
|
const config = require('./config.js')
|
||||||
|
|
||||||
const DISABLE_TIMEOUT = 60 * 60 * 1000
|
const DISABLE_TIMEOUT = 60 * 60 * 1000
|
||||||
class SpeedTester {
|
class SpeedTester {
|
||||||
constructor ({ hostname }) {
|
constructor ({ hostname }) {
|
||||||
|
@ -60,7 +61,7 @@ class SpeedTester {
|
||||||
const promiseList = []
|
const promiseList = []
|
||||||
for (const dnsKey in dnsMap) {
|
for (const dnsKey in dnsMap) {
|
||||||
const dns = dnsMap[dnsKey]
|
const dns = dnsMap[dnsKey]
|
||||||
const one = this.getFromOneDns(dns).then(ipList => {
|
const one = this.getFromOneDns(dns).then((ipList) => {
|
||||||
if (ipList) {
|
if (ipList) {
|
||||||
for (const ip of ipList) {
|
for (const ip of ipList) {
|
||||||
ips[ip] = { dns: ipList.isPreSet === true ? '预设IP' : dnsKey }
|
ips[ip] = { dns: ipList.isPreSet === true ? '预设IP' : dnsKey }
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const config = {
|
const config = {
|
||||||
notify () {},
|
notify () {},
|
||||||
dnsMap: {}
|
dnsMap: {},
|
||||||
}
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getConfig () {
|
getConfig () {
|
||||||
return config
|
return config
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
const SpeedTester = require('./SpeedTester.js')
|
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const config = require('./config')
|
|
||||||
const log = require('../../utils/util.log.js')
|
const log = require('../../utils/util.log.js')
|
||||||
const SpeedTestPool = {
|
const config = require('./config')
|
||||||
|
const SpeedTester = require('./SpeedTester.js')
|
||||||
|
|
||||||
|
const SpeedTestPool = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initSpeedTest (runtimeConfig) {
|
function initSpeedTest (runtimeConfig) {
|
||||||
const { enabled, hostnameList } = runtimeConfig
|
const { enabled, hostnameList } = runtimeConfig
|
||||||
const conf = config.getConfig()
|
const conf = config.getConfig()
|
||||||
|
@ -27,7 +28,7 @@ function getAllSpeedTester () {
|
||||||
allSpeed[key] = {
|
allSpeed[key] = {
|
||||||
hostname: key,
|
hostname: key,
|
||||||
alive: item.alive,
|
alive: item.alive,
|
||||||
backupList: item.backupList
|
backupList: item.backupList,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return allSpeed
|
return allSpeed
|
||||||
|
@ -70,5 +71,5 @@ module.exports = {
|
||||||
getAllSpeedTester,
|
getAllSpeedTester,
|
||||||
registerNotify,
|
registerNotify,
|
||||||
reSpeedTest,
|
reSpeedTest,
|
||||||
action
|
action,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
const interceptorImpls = require('./lib/interceptor')
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const lodash = require('lodash')
|
||||||
|
const jsonApi = require('./json')
|
||||||
const dnsUtil = require('./lib/dns')
|
const dnsUtil = require('./lib/dns')
|
||||||
|
const interceptorImpls = require('./lib/interceptor')
|
||||||
|
const scriptInterceptor = require('./lib/interceptor/impl/res/script')
|
||||||
|
const { getTmpPacFilePath, downloadPacAsync, createOverwallMiddleware } = require('./lib/proxy/middleware/overwall')
|
||||||
const log = require('./utils/util.log')
|
const log = require('./utils/util.log')
|
||||||
const matchUtil = require('./utils/util.match')
|
const matchUtil = require('./utils/util.match')
|
||||||
const path = require('path')
|
|
||||||
const fs = require('fs')
|
|
||||||
const lodash = require('lodash')
|
|
||||||
const scriptInterceptor = require('./lib/interceptor/impl/res/script')
|
|
||||||
const jsonApi = require('./json')
|
|
||||||
|
|
||||||
const { getTmpPacFilePath, downloadPacAsync, createOverwallMiddleware } = require('./lib/proxy/middleware/overwall')
|
|
||||||
|
|
||||||
// 处理拦截配置
|
// 处理拦截配置
|
||||||
function buildIntercepts (intercepts) {
|
function buildIntercepts (intercepts) {
|
||||||
|
@ -97,12 +96,12 @@ module.exports = (serverConfig) => {
|
||||||
preSetIpList,
|
preSetIpList,
|
||||||
dnsMap: dnsUtil.initDNS(serverConfig.dns.providers, preSetIpList),
|
dnsMap: dnsUtil.initDNS(serverConfig.dns.providers, preSetIpList),
|
||||||
mapping: matchUtil.domainMapRegexply(dnsMapping),
|
mapping: matchUtil.domainMapRegexply(dnsMapping),
|
||||||
speedTest: serverConfig.dns.speedTest
|
speedTest: serverConfig.dns.speedTest,
|
||||||
},
|
},
|
||||||
setting,
|
setting,
|
||||||
compatibleConfig: {
|
compatibleConfig: {
|
||||||
connect: serverConfig.compatible ? matchUtil.domainMapRegexply(serverConfig.compatible.connect) : {},
|
connect: serverConfig.compatible ? matchUtil.domainMapRegexply(serverConfig.compatible.connect) : {},
|
||||||
request: serverConfig.compatible ? matchUtil.domainMapRegexply(serverConfig.compatible.request) : {}
|
request: serverConfig.compatible ? matchUtil.domainMapRegexply(serverConfig.compatible.request) : {},
|
||||||
},
|
},
|
||||||
middlewares,
|
middlewares,
|
||||||
sslConnectInterceptor: (req, cltSocket, head) => {
|
sslConnectInterceptor: (req, cltSocket, head) => {
|
||||||
|
@ -205,7 +204,7 @@ module.exports = (serverConfig) => {
|
||||||
}
|
}
|
||||||
matchInterceptsOpts[impl.name] = {
|
matchInterceptsOpts[impl.name] = {
|
||||||
order: interceptOpt.order || 0,
|
order: interceptOpt.order || 0,
|
||||||
index: matchIntercepts.length - 1
|
index: matchIntercepts.length - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +216,7 @@ module.exports = (serverConfig) => {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return matchIntercepts
|
return matchIntercepts
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setting.rootCaFile) {
|
if (setting.rootCaFile) {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// const os = require('os')
|
// const os = require('os')
|
||||||
const log = require('util.log')
|
const log = require('util.log')
|
||||||
|
|
||||||
const util = {
|
const util = {
|
||||||
getNodeVersion () {
|
getNodeVersion () {
|
||||||
const version = process.version
|
const version = process.version
|
||||||
log.info(version)
|
log.info(version)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
util.getNodeVersion()
|
util.getNodeVersion()
|
||||||
module.exports = util
|
module.exports = util
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
const path = require('path')
|
||||||
const log4js = require('log4js')
|
const log4js = require('log4js')
|
||||||
const proxyConfig = require('../lib/proxy/common/config')
|
const proxyConfig = require('../lib/proxy/common/config')
|
||||||
|
|
||||||
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
||||||
const path = require('path')
|
|
||||||
const filename = path.join(proxyConfig.getDefaultCABasePath(), '/logs/server.log')
|
const filename = path.join(proxyConfig.getDefaultCABasePath(), '/logs/server.log')
|
||||||
log4js.configure({
|
log4js.configure({
|
||||||
appenders: { std: { type: 'stdout', level: 'debug' }, file: { level: 'debug', type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
|
appenders: { std: { type: 'stdout', level: 'debug' }, file: { level: 'debug', type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
|
||||||
categories: { default: { appenders: ['file', 'std'], level } }
|
categories: { default: { appenders: ['file', 'std'], level } },
|
||||||
})
|
})
|
||||||
const logger = log4js.getLogger('server')
|
const logger = log4js.getLogger('server')
|
||||||
module.exports = logger
|
module.exports = logger
|
||||||
|
|
|
@ -9,7 +9,7 @@ function isMatched (url, regexp) {
|
||||||
try {
|
try {
|
||||||
let urlRegexp = regexp
|
let urlRegexp = regexp
|
||||||
if (regexp[0] === '*' || regexp[0] === '?' || regexp[0] === '+') {
|
if (regexp[0] === '*' || regexp[0] === '?' || regexp[0] === '+') {
|
||||||
urlRegexp = '.' + regexp
|
urlRegexp = `.${regexp}`
|
||||||
}
|
}
|
||||||
return url.match(urlRegexp)
|
return url.match(urlRegexp)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -22,7 +22,7 @@ function domainRegexply (target) {
|
||||||
if (target === '.*' || target === '*' || target === 'true' || target === true) {
|
if (target === '.*' || target === '*' || target === 'true' || target === true) {
|
||||||
return '^.*$'
|
return '^.*$'
|
||||||
}
|
}
|
||||||
return '^' + target.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$'
|
return `^${target.replace(/\./g, '\\.').replace(/\*/g, '.*')}$`
|
||||||
}
|
}
|
||||||
|
|
||||||
function domainMapRegexply (hostMap) {
|
function domainMapRegexply (hostMap) {
|
||||||
|
@ -32,7 +32,7 @@ function domainMapRegexply (hostMap) {
|
||||||
const regexpMap = {}
|
const regexpMap = {}
|
||||||
const origin = {} // 用于快速匹配,见matchHostname、matchHostnameAll方法
|
const origin = {} // 用于快速匹配,见matchHostname、matchHostnameAll方法
|
||||||
lodash.each(hostMap, (value, domain) => {
|
lodash.each(hostMap, (value, domain) => {
|
||||||
if (domain.indexOf('*') >= 0 || domain[0] === '^') {
|
if (domain.includes('*') || domain[0] === '^') {
|
||||||
const regDomain = domain[0] !== '^' ? domainRegexply(domain) : domain
|
const regDomain = domain[0] !== '^' ? domainRegexply(domain) : domain
|
||||||
regexpMap[regDomain] = value
|
regexpMap[regDomain] = value
|
||||||
|
|
||||||
|
@ -65,12 +65,12 @@ function matchHostname (hostMap, hostname, action) {
|
||||||
log.info(`matchHostname: ${action}: '${hostname}' -> { "${hostname}": ${JSON.stringify(value)} }`)
|
log.info(`matchHostname: ${action}: '${hostname}' -> { "${hostname}": ${JSON.stringify(value)} }`)
|
||||||
return value // 快速匹配成功
|
return value // 快速匹配成功
|
||||||
}
|
}
|
||||||
value = hostMap.origin['*' + hostname]
|
value = hostMap.origin[`*${hostname}`]
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
log.info(`matchHostname: ${action}: '${hostname}' -> { "*${hostname}": ${JSON.stringify(value)} }`)
|
log.info(`matchHostname: ${action}: '${hostname}' -> { "*${hostname}": ${JSON.stringify(value)} }`)
|
||||||
return value // 快速匹配成功
|
return value // 快速匹配成功
|
||||||
}
|
}
|
||||||
value = hostMap.origin['*.' + hostname]
|
value = hostMap.origin[`*.${hostname}`]
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
log.info(`matchHostname: ${action}: '${hostname}' -> { "*.${hostname}": ${JSON.stringify(value)} }`)
|
log.info(`matchHostname: ${action}: '${hostname}' -> { "*.${hostname}": ${JSON.stringify(value)} }`)
|
||||||
return value // 快速匹配成功
|
return value // 快速匹配成功
|
||||||
|
@ -94,7 +94,7 @@ function matchHostname (hostMap, hostname, action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge (oldObj, newObj) {
|
function merge (oldObj, newObj) {
|
||||||
return lodash.mergeWith(oldObj, newObj, function (objValue, srcValue) {
|
return lodash.mergeWith(oldObj, newObj, (objValue, srcValue) => {
|
||||||
if (lodash.isArray(objValue)) {
|
if (lodash.isArray(objValue)) {
|
||||||
return srcValue
|
return srcValue
|
||||||
}
|
}
|
||||||
|
@ -146,13 +146,13 @@ function matchHostnameAll (hostMap, hostname, action) {
|
||||||
|
|
||||||
// 域名快速匹配:直接匹配 或者 两种前缀通配符匹配
|
// 域名快速匹配:直接匹配 或者 两种前缀通配符匹配
|
||||||
// 优先级:2
|
// 优先级:2
|
||||||
value = hostMap.origin['*' + hostname]
|
value = hostMap.origin[`*${hostname}`]
|
||||||
if (value) {
|
if (value) {
|
||||||
log.debug(`matchHostname-one: ${action}: '${hostname}' -> { "*${hostname}": ${JSON.stringify(value)} }`)
|
log.debug(`matchHostname-one: ${action}: '${hostname}' -> { "*${hostname}": ${JSON.stringify(value)} }`)
|
||||||
values = merge(values, value)
|
values = merge(values, value)
|
||||||
}
|
}
|
||||||
// 优先级:3
|
// 优先级:3
|
||||||
value = hostMap.origin['*.' + hostname]
|
value = hostMap.origin[`*.${hostname}`]
|
||||||
if (value) {
|
if (value) {
|
||||||
log.debug(`matchHostname-one: ${action}: '${hostname}' -> { "*.${hostname}": ${JSON.stringify(value)} }`)
|
log.debug(`matchHostname-one: ${action}: '${hostname}' -> { "*.${hostname}": ${JSON.stringify(value)} }`)
|
||||||
values = merge(values, value)
|
values = merge(values, value)
|
||||||
|
@ -178,5 +178,5 @@ module.exports = {
|
||||||
domainRegexply,
|
domainRegexply,
|
||||||
domainMapRegexply,
|
domainMapRegexply,
|
||||||
matchHostname,
|
matchHostname,
|
||||||
matchHostnameAll
|
matchHostnameAll,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,5 @@ module.exports = {
|
||||||
if (process.send) {
|
if (process.send) {
|
||||||
process.send({ type: 'status', event: status })
|
process.send({ type: 'status', event: status })
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ options.paragraph = 'false'
|
||||||
options.probability = 'false'
|
options.probability = 'false'
|
||||||
|
|
||||||
// 调用通用文字识别(高精度版)(异步)
|
// 调用通用文字识别(高精度版)(异步)
|
||||||
client.accurateBasic(imageBase64, options).then(function (result) {
|
client.accurateBasic(imageBase64, options).then((result) => {
|
||||||
console.log(JSON.stringify(result))
|
console.log(JSON.stringify(result))
|
||||||
}).catch(function (err) {
|
}).catch((err) => {
|
||||||
// 如果发生网络错误
|
// 如果发生网络错误
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const SpeedTester = require('../src/lib/speed/SpeedTester.js')
|
|
||||||
const SpeedTest = require('../src/lib/speed/index.js')
|
|
||||||
const dns = require('../src/lib/dns/index.js')
|
const dns = require('../src/lib/dns/index.js')
|
||||||
|
const SpeedTest = require('../src/lib/speed/index.js')
|
||||||
|
const SpeedTester = require('../src/lib/speed/SpeedTester.js')
|
||||||
|
|
||||||
const dnsMap = dns.initDNS({
|
const dnsMap = dns.initDNS({
|
||||||
// ipaddress: {
|
// ipaddress: {
|
||||||
|
@ -11,8 +11,8 @@ const dnsMap = dns.initDNS({
|
||||||
cloudflare: {
|
cloudflare: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://1.1.1.1/dns-query',
|
server: 'https://1.1.1.1/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
}
|
},
|
||||||
// py233: { //污染
|
// py233: { //污染
|
||||||
// type: 'https',
|
// type: 'https',
|
||||||
// server: ' https://i.233py.com/dns-query',
|
// server: ' https://i.233py.com/dns-query',
|
||||||
|
@ -33,6 +33,6 @@ const dnsMap = dns.initDNS({
|
||||||
SpeedTest.initSpeedTest({ hostnameList: {}, dnsMap })
|
SpeedTest.initSpeedTest({ hostnameList: {}, dnsMap })
|
||||||
|
|
||||||
const tester = new SpeedTester({ hostname: 'github.com' })
|
const tester = new SpeedTester({ hostname: 'github.com' })
|
||||||
tester.test().then(ret => {
|
tester.test().then((ret) => {
|
||||||
console.log(tester.alive)
|
console.log(tester.alive)
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,33 +4,33 @@ const dnsProviders = dns.initDNS({
|
||||||
aliyun: {
|
aliyun: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://dns.alidns.com/dns-query',
|
server: 'https://dns.alidns.com/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
},
|
},
|
||||||
cloudflare: {
|
cloudflare: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://1.1.1.1/dns-query',
|
server: 'https://1.1.1.1/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
},
|
},
|
||||||
ipaddress: {
|
ipaddress: {
|
||||||
type: 'ipaddress',
|
type: 'ipaddress',
|
||||||
server: 'ipaddress',
|
server: 'ipaddress',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
},
|
},
|
||||||
quad9: {
|
quad9: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://9.9.9.9/dns-query',
|
server: 'https://9.9.9.9/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
},
|
},
|
||||||
rubyfish: {
|
rubyfish: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: 'https://rubyfish.cn/dns-query',
|
server: 'https://rubyfish.cn/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
},
|
},
|
||||||
py233: {
|
py233: {
|
||||||
type: 'https',
|
type: 'https',
|
||||||
server: ' https://i.233py.com/dns-query',
|
server: ' https://i.233py.com/dns-query',
|
||||||
cacheSize: 1000
|
cacheSize: 1000,
|
||||||
}
|
},
|
||||||
|
|
||||||
// sb: {
|
// sb: {
|
||||||
// type: 'https',
|
// type: 'https',
|
||||||
|
|
|
@ -4,7 +4,7 @@ const headers = {}
|
||||||
const res = {
|
const res = {
|
||||||
setHeader: (key, value) => {
|
setHeader: (key, value) => {
|
||||||
headers[key] = value
|
headers[key] = value
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyRes = {
|
const proxyRes = {
|
||||||
|
@ -20,9 +20,9 @@ const proxyRes = {
|
||||||
const newHeaders = {
|
const newHeaders = {
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
'Content-Length': '3',
|
'Content-Length': '3',
|
||||||
xxx: 1,
|
'xxx': 1,
|
||||||
Date: '[remove]',
|
'Date': '[remove]',
|
||||||
yyy: '[remove]'
|
'yyy': '[remove]',
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = responseReplace.replaceResponseHeaders(newHeaders, res, proxyRes)
|
const result = responseReplace.replaceResponseHeaders(newHeaders, res, proxyRes)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
const monkey = require('../../../src/lib/monkey/index')
|
const monkey = require('../../../src/lib/monkey/index')
|
||||||
|
|
||||||
const scripts = monkey.load()
|
const scripts = monkey.load()
|
||||||
console.log(scripts[0])
|
console.log(scripts[0])
|
||||||
|
|
|
@ -5,7 +5,7 @@ const hostMap = matchUtil.domainMapRegexply({
|
||||||
'*bbb.com': true,
|
'*bbb.com': true,
|
||||||
'*.ccc.com': true,
|
'*.ccc.com': true,
|
||||||
'^.{1,3}ddd.com$': true,
|
'^.{1,3}ddd.com$': true,
|
||||||
'*.cn': true
|
'*.cn': true,
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(hostMap)
|
console.log(hostMap)
|
||||||
|
|
|
@ -2,21 +2,21 @@ const http = require('http')
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
|
||||||
},
|
},
|
||||||
lookup (hostname, options, callback) {
|
lookup (hostname, options, callback) {
|
||||||
const ip = '106.52.191.148'
|
const ip = '106.52.191.148'
|
||||||
console.log('lookup')
|
console.log('lookup')
|
||||||
callback(null, ip, 4)
|
callback(null, ip, 4)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = http.get('http://test.target/', options, function (response) {
|
const request = http.get('http://test.target/', options, (response) => {
|
||||||
response.on('data', function (data) {
|
response.on('data', (data) => {
|
||||||
process.stdout.write(data)
|
process.stdout.write(data)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
request.on('error', function (error) {
|
request.on('error', (error) => {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const CryptoJs = require('crypto-js')
|
const CryptoJs = require('crypto-js')
|
||||||
|
|
||||||
const ret = CryptoJs.SHA256('111111111111')
|
const ret = CryptoJs.SHA256('111111111111')
|
||||||
console.log(ret.toString(CryptoJs.enc.Base64))
|
console.log(ret.toString(CryptoJs.enc.Base64))
|
||||||
console.log(1 / 2)
|
console.log(1 / 2)
|
||||||
|
|
Loading…
Reference in New Issue