mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-24 16:51:29 +00:00
Merge pull request #401 from alibaba/ca_helper
Add ca helper when run anyproxy -i
This commit is contained in:
commit
0621dadf28
95
bin/anyproxy
95
bin/anyproxy
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
const program = require('commander'),
|
const program = require('commander'),
|
||||||
color = require('colorful'),
|
color = require('colorful'),
|
||||||
|
co = require('co'),
|
||||||
packageInfo = require('../package.json'),
|
packageInfo = require('../package.json'),
|
||||||
ruleLoader = require('../lib/ruleLoader'),
|
|
||||||
util = require('../lib/util'),
|
util = require('../lib/util'),
|
||||||
|
rootCACheck = require('./rootCaCheck'),
|
||||||
|
startServer = require('./startServer'),
|
||||||
logUtil = require('../lib/log');
|
logUtil = require('../lib/log');
|
||||||
|
|
||||||
program
|
program
|
||||||
@ -33,85 +35,20 @@ if (program.clear) {
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const AnyProxy = require('../proxy.js');
|
co(function *() {
|
||||||
let proxyServer;
|
if (program.silent) {
|
||||||
|
logUtil.setPrintStatus(false);
|
||||||
if (program.silent) {
|
|
||||||
logUtil.setPrintStatus(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load rule module
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
if (program.rule) {
|
|
||||||
resolve(ruleLoader.requireModule(program.rule));
|
|
||||||
} else {
|
|
||||||
resolve(null);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
logUtil.printLog('Failed to load rule file', logUtil.T_ERR);
|
|
||||||
logUtil.printLog(e, logUtil.T_ERR);
|
|
||||||
process.exit();
|
|
||||||
})
|
|
||||||
|
|
||||||
//start proxy
|
|
||||||
.then(ruleModule => {
|
|
||||||
proxyServer = new AnyProxy.ProxyServer({
|
|
||||||
type: 'http',
|
|
||||||
port: program.port || 8001,
|
|
||||||
throttle: program.throttle,
|
|
||||||
rule: ruleModule,
|
|
||||||
webInterface: {
|
|
||||||
enable: true,
|
|
||||||
webPort: program.web,
|
|
||||||
},
|
|
||||||
wsIntercept: program.wsIntercept,
|
|
||||||
forceProxyHttps: program.intercept,
|
|
||||||
dangerouslyIgnoreUnauthorized: !!program.ignoreUnauthorizedSsl,
|
|
||||||
silent: program.silent
|
|
||||||
});
|
|
||||||
// proxyServer.on('ready', () => {});
|
|
||||||
proxyServer.start();
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
logUtil.printLog(e, logUtil.T_ERR);
|
|
||||||
if (e && e.code) {
|
|
||||||
logUtil.printLog('code ' + e.code, logUtil.T_ERR);
|
|
||||||
}
|
|
||||||
logUtil.printLog(e.stack, logUtil.T_ERR);
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', (code) => {
|
|
||||||
if (code > 0) {
|
|
||||||
logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit();
|
if (program.intercept) {
|
||||||
});
|
try {
|
||||||
|
yield rootCACheck();
|
||||||
//exit cause ctrl+c
|
} catch (e) {
|
||||||
process.on('SIGINT', () => {
|
console.error(e);
|
||||||
try {
|
|
||||||
proxyServer && proxyServer.close();
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
process.exit();
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('uncaughtException', (err) => {
|
|
||||||
let errorTipText = 'got an uncaught exception, is there anything goes wrong in your rule file ?\n';
|
|
||||||
try {
|
|
||||||
if (err && err.stack) {
|
|
||||||
errorTipText += err.stack;
|
|
||||||
} else {
|
|
||||||
errorTipText += err;
|
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
}
|
||||||
logUtil.printLog(errorTipText, logUtil.T_ERR);
|
|
||||||
try {
|
return startServer(program);
|
||||||
proxyServer && proxyServer.close();
|
})
|
||||||
} catch (e) {}
|
|
||||||
process.exit();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
bin/rootCACheck.js
Normal file
33
bin/rootCACheck.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* check if root CA exists and installed
|
||||||
|
* will prompt to generate when needed
|
||||||
|
*/
|
||||||
|
|
||||||
|
const thunkify = require('thunkify');
|
||||||
|
const AnyProxy = require('../proxy');
|
||||||
|
const logUtil = require('../lib/log');
|
||||||
|
|
||||||
|
const certMgr = AnyProxy.utils.certMgr;
|
||||||
|
|
||||||
|
function checkRootCAExists() {
|
||||||
|
return certMgr.isRootCAFileExists();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function *() {
|
||||||
|
try {
|
||||||
|
if (!checkRootCAExists()) {
|
||||||
|
logUtil.warn('Missing root CA, generating now');
|
||||||
|
yield thunkify(certMgr.generateRootCA)();
|
||||||
|
yield certMgr.trustRootCA();
|
||||||
|
} else {
|
||||||
|
const isCATrusted = yield thunkify(certMgr.ifRootCATrusted)();
|
||||||
|
if (!isCATrusted) {
|
||||||
|
logUtil.warn('ROOT CA NOT INSTALLED YET');
|
||||||
|
yield certMgr.trustRootCA();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
86
bin/startServer.js
Normal file
86
bin/startServer.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* start the AnyProxy server
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ruleLoader = require('../lib/ruleLoader');
|
||||||
|
const logUtil = require('../lib/log');
|
||||||
|
const AnyProxy = require('../proxy');
|
||||||
|
|
||||||
|
module.exports = function startServer(program) {
|
||||||
|
let proxyServer;
|
||||||
|
// load rule module
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
if (program.rule) {
|
||||||
|
resolve(ruleLoader.requireModule(program.rule));
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
logUtil.printLog('Failed to load rule file', logUtil.T_ERR);
|
||||||
|
logUtil.printLog(e, logUtil.T_ERR);
|
||||||
|
process.exit();
|
||||||
|
})
|
||||||
|
|
||||||
|
//start proxy
|
||||||
|
.then(ruleModule => {
|
||||||
|
proxyServer = new AnyProxy.ProxyServer({
|
||||||
|
type: 'http',
|
||||||
|
port: program.port || 8001,
|
||||||
|
throttle: program.throttle,
|
||||||
|
rule: ruleModule,
|
||||||
|
webInterface: {
|
||||||
|
enable: true,
|
||||||
|
webPort: program.web,
|
||||||
|
},
|
||||||
|
wsIntercept: program.wsIntercept,
|
||||||
|
forceProxyHttps: program.intercept,
|
||||||
|
dangerouslyIgnoreUnauthorized: !!program.ignoreUnauthorizedSsl,
|
||||||
|
silent: program.silent
|
||||||
|
});
|
||||||
|
// proxyServer.on('ready', () => {});
|
||||||
|
proxyServer.start();
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
logUtil.printLog(e, logUtil.T_ERR);
|
||||||
|
if (e && e.code) {
|
||||||
|
logUtil.printLog('code ' + e.code, logUtil.T_ERR);
|
||||||
|
}
|
||||||
|
logUtil.printLog(e.stack, logUtil.T_ERR);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
process.on('exit', (code) => {
|
||||||
|
if (code > 0) {
|
||||||
|
logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
|
||||||
|
//exit cause ctrl+c
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
try {
|
||||||
|
proxyServer && proxyServer.close();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('uncaughtException', (err) => {
|
||||||
|
let errorTipText = 'got an uncaught exception, is there anything goes wrong in your rule file ?\n';
|
||||||
|
try {
|
||||||
|
if (err && err.stack) {
|
||||||
|
errorTipText += err.stack;
|
||||||
|
} else {
|
||||||
|
errorTipText += err;
|
||||||
|
}
|
||||||
|
} catch (e) { }
|
||||||
|
logUtil.printLog(errorTipText, logUtil.T_ERR);
|
||||||
|
try {
|
||||||
|
proxyServer && proxyServer.close();
|
||||||
|
} catch (e) { }
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
}
|
@ -1,11 +1,16 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const util = require('./util');
|
|
||||||
const EasyCert = require('node-easy-cert');
|
const EasyCert = require('node-easy-cert');
|
||||||
const co = require('co');
|
const co = require('co');
|
||||||
|
const os = require('os');
|
||||||
|
const inquirer = require('inquirer');
|
||||||
|
|
||||||
|
const util = require('./util');
|
||||||
|
const logUtil = require('./log');
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
rootDirPath: util.getAnyProxyPath('certificates'),
|
rootDirPath: util.getAnyProxyPath('certificates'),
|
||||||
|
inMemory: false,
|
||||||
defaultCertAttrs: [
|
defaultCertAttrs: [
|
||||||
{ name: 'countryName', value: 'CN' },
|
{ name: 'countryName', value: 'CN' },
|
||||||
{ name: 'organizationName', value: 'AnyProxy' },
|
{ name: 'organizationName', value: 'AnyProxy' },
|
||||||
@ -54,4 +59,45 @@ crtMgr.getCAStatus = function *() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* trust the root ca by command
|
||||||
|
*/
|
||||||
|
crtMgr.trustRootCA = function *() {
|
||||||
|
const platform = os.platform();
|
||||||
|
const rootCAPath = crtMgr.getRootCAFilePath();
|
||||||
|
const trustInquiry = [
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'trustCA',
|
||||||
|
message: 'The rootCA is not trusted yet, install it to the trust store now?',
|
||||||
|
choices: ['Yes', "No, I'll do it myself"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
if (platform === 'darwin') {
|
||||||
|
const answer = yield inquirer.prompt(trustInquiry);
|
||||||
|
if (answer.trustCA === 'Yes') {
|
||||||
|
logUtil.info('About to trust the root CA, this may requires your password');
|
||||||
|
// https://ss64.com/osx/security-cert.html
|
||||||
|
const result = util.execScriptSync(`sudo security add-trusted-cert -d -k /Library/Keychains/System.keychain ${rootCAPath}`);
|
||||||
|
if (result.status === 0) {
|
||||||
|
logUtil.info('Root CA install, you are ready to intercept the https now');
|
||||||
|
} else {
|
||||||
|
console.error(result);
|
||||||
|
logUtil.info('Failed to trust the root CA, please trust it manually');
|
||||||
|
util.guideToHomePage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logUtil.info('Please trust the root CA manually so https interception works');
|
||||||
|
util.guideToHomePage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (/^win/.test(process.platform)) {
|
||||||
|
logUtil.info('You can install the root CA manually.');
|
||||||
|
}
|
||||||
|
logUtil.info('The root CA file path is: ' + crtMgr.getRootCAFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = crtMgr;
|
module.exports = crtMgr;
|
||||||
|
@ -58,7 +58,7 @@ function printLog(content, type) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(color.magenta(`[AnyProxy WARN][${timeString}]: ` + content));
|
console.error(color.yellow(`[AnyProxy WARN][${timeString}]: ` + content));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ module.exports.warn = (content) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports.error = (content) => {
|
module.exports.error = (content) => {
|
||||||
printLog(content, LogLevelMap.error);
|
printLog(content, LogLevelMap.system_error);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.ruleError = (content) => {
|
module.exports.ruleError = (content) => {
|
||||||
|
37
lib/util.js
37
lib/util.js
@ -4,7 +4,7 @@ const fs = require('fs'),
|
|||||||
path = require('path'),
|
path = require('path'),
|
||||||
mime = require('mime-types'),
|
mime = require('mime-types'),
|
||||||
color = require('colorful'),
|
color = require('colorful'),
|
||||||
crypto = require('crypto'),
|
child_process = require('child_process'),
|
||||||
Buffer = require('buffer').Buffer,
|
Buffer = require('buffer').Buffer,
|
||||||
logUtil = require('./log');
|
logUtil = require('./log');
|
||||||
const networkInterfaces = require('os').networkInterfaces();
|
const networkInterfaces = require('os').networkInterfaces();
|
||||||
@ -216,6 +216,8 @@ function deleteFolderContentsRecursive(dirPath, ifClearFolderItself) {
|
|||||||
throw new Error('can_not_delete_this_dir');
|
throw new Error('can_not_delete_this_dir');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logUtil.info('==>>> clearing cache ', dirPath);
|
||||||
|
|
||||||
if (fs.existsSync(dirPath)) {
|
if (fs.existsSync(dirPath)) {
|
||||||
fs.readdirSync(dirPath).forEach((file) => {
|
fs.readdirSync(dirPath).forEach((file) => {
|
||||||
const curPath = path.join(dirPath, file);
|
const curPath = path.join(dirPath, file);
|
||||||
@ -307,17 +309,22 @@ module.exports.isIpDomain = function (domain) {
|
|||||||
return ipReg.test(domain);
|
return ipReg.test(domain);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
module.exports.execScriptSync = function (cmd) {
|
||||||
* To generic a Sec-WebSocket-Accept value
|
let stdout,
|
||||||
* 1. append the `Sec-WebSocket-Key` request header with `matic string`
|
status = 0;
|
||||||
* 2. get sha1 hash of the string
|
try {
|
||||||
* 3. get base64 of the sha1 hash
|
stdout = child_process.execSync(cmd);
|
||||||
*/
|
} catch (err) {
|
||||||
module.exports.genericWsSecAccept = function (wsSecKey) {
|
stdout = err.stdout;
|
||||||
// the string to generate the Sec-WebSocket-Accept
|
status = err.status;
|
||||||
const magicString = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
|
}
|
||||||
const targetString = `${wsSecKey}${magicString}`;
|
|
||||||
const shasum = crypto.createHash('sha1');
|
return {
|
||||||
shasum.update(targetString);
|
stdout: stdout.toString(),
|
||||||
return shasum.digest('base64');
|
status
|
||||||
}
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.guideToHomePage = function () {
|
||||||
|
logUtil.info('Refer to http://anyproxy.io for more detail');
|
||||||
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "anyproxy",
|
"name": "anyproxy",
|
||||||
"version": "4.0.10",
|
"version": "4.0.11",
|
||||||
"description": "A fully configurable HTTP/HTTPS proxy in Node.js",
|
"description": "A fully configurable HTTP/HTTPS proxy in Node.js",
|
||||||
"main": "proxy.js",
|
"main": "proxy.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -35,6 +35,7 @@
|
|||||||
"request": "^2.74.0",
|
"request": "^2.74.0",
|
||||||
"stream-throttle": "^0.1.3",
|
"stream-throttle": "^0.1.3",
|
||||||
"svg-inline-react": "^1.0.2",
|
"svg-inline-react": "^1.0.2",
|
||||||
|
"thunkify": "^2.1.2",
|
||||||
"whatwg-fetch": "^1.0.0",
|
"whatwg-fetch": "^1.0.0",
|
||||||
"ws": "^5.1.0"
|
"ws": "^5.1.0"
|
||||||
},
|
},
|
||||||
@ -68,7 +69,6 @@
|
|||||||
"koa-send": "^3.2.0",
|
"koa-send": "^3.2.0",
|
||||||
"less": "^2.7.1",
|
"less": "^2.7.1",
|
||||||
"less-loader": "^2.2.3",
|
"less-loader": "^2.2.3",
|
||||||
"memwatch-next": "^0.3.0",
|
|
||||||
"node-simhash": "^0.1.0",
|
"node-simhash": "^0.1.0",
|
||||||
"nodeunit": "^0.9.1",
|
"nodeunit": "^0.9.1",
|
||||||
"phantom": "^4.0.0",
|
"phantom": "^4.0.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user