Merge branch 'ca_helper' into typescript

# Conflicts:
#	bin/anyproxy
#	lib/log.js
#	lib/util.js
This commit is contained in:
砚然 2018-07-11 16:00:47 +08:00
commit 68c0d17a33
6 changed files with 210 additions and 102 deletions

View File

@ -4,9 +4,11 @@
const program = require('commander'),
color = require('colorful'),
co = require('co'),
packageInfo = require('../package.json'),
ruleLoader = require('../dist/ruleLoader'),
util = require('../dist/util'),
rootCACheck = require('./rootCaCheck'),
startServer = require('./startServer'),
logUtil = require('../dist/log');
program
@ -33,85 +35,20 @@ if (program.clear) {
process.exit(0);
});
} else {
const AnyProxy = require('../proxy.js');
let proxyServer;
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);
co(function *() {
if (program.silent) {
logUtil.setPrintStatus(false);
}
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;
if (program.intercept) {
try {
yield rootCACheck();
} catch (e) {
console.error(e);
}
} catch (e) {}
logUtil.printLog(errorTipText, logUtil.T_ERR);
try {
proxyServer && proxyServer.close();
} catch (e) {}
process.exit();
});
}
return startServer(program);
})
}

33
bin/rootCACheck.js Normal file
View 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('../dist/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
View File

@ -0,0 +1,86 @@
/**
* start the AnyProxy server
*/
const ruleLoader = require('../dist/ruleLoader');
const logUtil = require('../dist/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();
});
}

View File

@ -1,11 +1,16 @@
'use strict'
const util = require('./util');
const EasyCert = require('node-easy-cert');
const co = require('co');
const os = require('os');
const inquirer = require('inquirer');
const util = require('./util');
const logUtil = require('./log');
const options = {
rootDirPath: util.getAnyProxyPath('certificates'),
inMemory: false,
defaultCertAttrs: [
{ name: 'countryName', value: 'CN' },
{ 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;

View File

@ -12,11 +12,10 @@ import * as fs from 'fs';
import * as path from 'path';
import * as mime from 'mime-types';
import * as color from 'colorful';
import {Buffer} from 'buffer';
import * as crypto from 'crypto';
// import buffer from 'buffer';
import { Buffer } from 'buffer';
import { execSync } from 'child_process';
import logUtil from './log';
// const Buffer = buffer.Buffer;
const networkInterfaces = require('os').networkInterfaces();
@ -113,7 +112,7 @@ import logUtil from './log';
* useLocalResponse的时候会使用到
*/
function contentType (filepath: string): string {
return mime.contentType(path.extname(filepath));
return mime.contentType(path.extname(filepath)) || '';
};
/*
@ -323,20 +322,26 @@ import logUtil from './log';
return ipReg.test(domain);
};
/**
* To generic a Sec-WebSocket-Accept value
* 1. append the `Sec-WebSocket-Key` request header with `matic string`
* 2. get sha1 hash of the string
* 3. get base64 of the sha1 hash
*/
function genericWsSecAccept (wsSecKey) {
// the string to generate the Sec-WebSocket-Accept
const magicString = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const targetString = `${wsSecKey}${magicString}`;
const shasum = crypto.createHash('sha1');
shasum.update(targetString);
return shasum.digest('base64');
}
function execScriptSync (cmd: string): object {
let stdout,
status = 0;
try {
stdout = execSync(cmd);
} catch (err) {
stdout = err.stdout;
status = err.status;
}
return {
stdout: stdout.toString(),
status
};
};
function guideToHomePage (): void {
logUtil.info('Refer to http://anyproxy.io for more detail');
};
const Util = {
lower_keys,
@ -357,7 +362,8 @@ const Util = {
isIpDomain,
getByteSize,
deleteFolderContentsRecursive,
genericWsSecAccept,
execScriptSync,
guideToHomePage,
formatDate
}

View File

@ -1,6 +1,6 @@
{
"name": "anyproxy",
"version": "4.0.10",
"version": "4.0.11",
"description": "A fully configurable HTTP/HTTPS proxy in Node.js",
"main": "proxy.js",
"bin": {
@ -35,6 +35,7 @@
"request": "^2.74.0",
"stream-throttle": "^0.1.3",
"svg-inline-react": "^1.0.2",
"thunkify": "^2.1.2",
"whatwg-fetch": "^1.0.0",
"ws": "^5.1.0"
},
@ -71,7 +72,6 @@
"koa-send": "^3.2.0",
"less": "^2.7.1",
"less-loader": "^2.2.3",
"memwatch-next": "^0.3.0",
"node-simhash": "^0.1.0",
"nodeunit": "^0.9.1",
"phantom": "^4.0.0",