mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-20 04:04:22 +00:00
214 lines
7.8 KiB
JavaScript
214 lines
7.8 KiB
JavaScript
try{
|
|
GLOBAL.util = require('./lib/util');
|
|
}catch(e){}
|
|
|
|
var http = require('http'),
|
|
https = require('https'),
|
|
fs = require('fs'),
|
|
async = require("async"),
|
|
url = require('url'),
|
|
program = require('commander'),
|
|
color = require('colorful'),
|
|
certMgr = require("./lib/certMgr"),
|
|
getPort = require("./lib/getPort"),
|
|
requestHandler = require("./lib/requestHandler"),
|
|
Recorder = require("./lib/recorder"),
|
|
logUtil = require("./lib/log"),
|
|
wsServer = require("./lib/wsServer"),
|
|
webInterface = require("./lib/webInterface"),
|
|
inherits = require("util").inherits,
|
|
util = require("./lib/util"),
|
|
path = require("path"),
|
|
juicer = require('juicer'),
|
|
events = require("events"),
|
|
express = require("express"),
|
|
ip = require("ip"),
|
|
ThrottleGroup = require("stream-throttle").ThrottleGroup,
|
|
iconv = require('iconv-lite'),
|
|
Buffer = require('buffer').Buffer;
|
|
|
|
|
|
var T_TYPE_HTTP = 0,
|
|
T_TYPE_HTTPS = 1,
|
|
DEFAULT_PORT = 8001,
|
|
DEFAULT_WEB_PORT = 8002, // port for web interface
|
|
DEFAULT_WEBSOCKET_PORT = 8003, // internal web socket for web interface, not for end users
|
|
DEFAULT_CONFIG_PORT = 8088,
|
|
DEFAULT_HOST = "localhost",
|
|
DEFAULT_TYPE = T_TYPE_HTTP;
|
|
|
|
var default_rule = require('./lib/rule_default');
|
|
|
|
//may be unreliable in windows
|
|
try{
|
|
var anyproxyHome = path.join(util.getUserHome(),"/.anyproxy/");
|
|
if(!fs.existsSync(anyproxyHome)){
|
|
fs.mkdirSync(anyproxyHome);
|
|
}
|
|
if(fs.existsSync(path.join(anyproxyHome,"rule_default.js"))){
|
|
default_rule = require(path.join(anyproxyHome,"rule_default"));
|
|
}
|
|
if(fs.existsSync(path.join(process.cwd(),'rule.js'))){
|
|
default_rule = require(path.join(process.cwd(),'rule'));
|
|
}
|
|
}catch(e){}
|
|
|
|
//option
|
|
//option.type : 'http'(default) or 'https'
|
|
//option.port : 8001(default)
|
|
//option.hostname : localhost(default)
|
|
//option.rule : ruleModule
|
|
//option.webPort : 8002(default)
|
|
//option.socketPort : 8003(default)
|
|
//option.webConfigPort : 8088(default)
|
|
//option.dbFile : null(default)
|
|
//option.throttle : null(default)
|
|
//option.disableWebInterface
|
|
//option.silent : false(default)
|
|
//option.interceptHttps ,internal param for https
|
|
function proxyServer(option){
|
|
option = option || {};
|
|
|
|
var self = this,
|
|
proxyType = /https/i.test(option.type || DEFAULT_TYPE) ? T_TYPE_HTTPS : T_TYPE_HTTP ,
|
|
proxyPort = option.port || DEFAULT_PORT,
|
|
proxyHost = option.hostname || DEFAULT_HOST,
|
|
proxyRules = option.rule || default_rule,
|
|
proxyWebPort = option.webPort || DEFAULT_WEB_PORT, //port for web interface
|
|
socketPort = option.socketPort || DEFAULT_WEBSOCKET_PORT, //port for websocket
|
|
proxyConfigPort = option.webConfigPort || DEFAULT_CONFIG_PORT, //port to ui config server
|
|
disableWebInterface = !!option.disableWebInterface,
|
|
ifSilent = !!option.silent,
|
|
webServerInstance;
|
|
|
|
if(ifSilent){
|
|
logUtil.setPrintStatus(false);
|
|
}
|
|
|
|
if(option.dbFile){
|
|
GLOBAL.recorder = new Recorder({filename: option.dbFile});
|
|
}else{
|
|
GLOBAL.recorder = new Recorder();
|
|
}
|
|
|
|
if(!!option.interceptHttps){
|
|
default_rule.setInterceptFlag(true);
|
|
|
|
//print a tip when using https features in Node < v0.12
|
|
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
|
if(nodeVersion < 0.12){
|
|
logUtil.printLog(color.red("node >= v0.12 is required when trying to intercept HTTPS requests :("), logUtil.T_ERR);
|
|
}
|
|
}
|
|
|
|
if(option.throttle){
|
|
logUtil.printLog("throttle :" + option.throttle + "kb/s");
|
|
GLOBAL._throttle = new ThrottleGroup({rate: 1024 * parseInt(option.throttle) }); // rate - byte/sec
|
|
}
|
|
|
|
requestHandler.setRules(proxyRules); //TODO : optimize calling for set rule
|
|
self.httpProxyServer = null;
|
|
|
|
async.series(
|
|
[
|
|
//creat proxy server
|
|
function(callback){
|
|
if(proxyType == T_TYPE_HTTPS){
|
|
certMgr.getCertificate(proxyHost,function(err,keyContent,crtContent){
|
|
if(err){
|
|
callback(err);
|
|
}else{
|
|
self.httpProxyServer = https.createServer({
|
|
key : keyContent,
|
|
cert: crtContent
|
|
},requestHandler.userRequestHandler);
|
|
callback(null);
|
|
}
|
|
});
|
|
}else{
|
|
self.httpProxyServer = http.createServer(requestHandler.userRequestHandler);
|
|
callback(null);
|
|
}
|
|
},
|
|
|
|
//handle CONNECT request for https over http
|
|
function(callback){
|
|
self.httpProxyServer.on('connect',requestHandler.connectReqHandler);
|
|
callback(null);
|
|
},
|
|
|
|
//start proxy server
|
|
function(callback){
|
|
self.httpProxyServer.listen(proxyPort);
|
|
callback(null);
|
|
},
|
|
|
|
//start web socket service
|
|
function(callback){
|
|
var ws = new wsServer({port : socketPort});
|
|
callback(null)
|
|
},
|
|
|
|
//start web interface
|
|
function(callback){
|
|
if(disableWebInterface){
|
|
logUtil.printLog('web interface is disabled');
|
|
}else{
|
|
var config = {
|
|
port : proxyWebPort,
|
|
wsPort : socketPort,
|
|
userRule : proxyRules,
|
|
ip : ip.address()
|
|
};
|
|
|
|
webServerInstance = new webInterface(config);
|
|
}
|
|
callback(null);
|
|
},
|
|
|
|
//server status manager
|
|
function(callback){
|
|
|
|
//kill web server when father process exits
|
|
process.on("exit",function(code){
|
|
logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR);
|
|
process.exit();
|
|
});
|
|
|
|
process.on("uncaughtException",function(err){
|
|
logUtil.printLog('Caught exception: ' + err, logUtil.T_ERR);
|
|
process.exit();
|
|
});
|
|
|
|
callback(null);
|
|
}
|
|
],
|
|
|
|
//final callback
|
|
function(err,result){
|
|
if(!err){
|
|
var webTip,webUrl;
|
|
webUrl = "http://" + ip.address() + ":" + proxyWebPort +"/";
|
|
webTip = "GUI interface started at : " + webUrl;
|
|
logUtil.printLog(color.green(webTip));
|
|
|
|
var tipText = (proxyType == T_TYPE_HTTP ? "Http" : "Https") + " proxy started at " + color.bold(ip.address() + ":" + proxyPort);
|
|
logUtil.printLog(color.green(tipText));
|
|
}else{
|
|
var tipText = "err when start proxy server :(";
|
|
logUtil.printLog(color.red(tipText), logUtil.T_ERR);
|
|
logUtil.printLog(err, logUtil.T_ERR);
|
|
}
|
|
}
|
|
);
|
|
|
|
self.close = function(){
|
|
self.httpProxyServer && self.httpProxyServer.close();
|
|
logUtil.printLog(color.green("server closed :" + proxyHost + ":" + proxyPort));
|
|
}
|
|
}
|
|
|
|
module.exports.proxyServer = proxyServer;
|
|
module.exports.generateRootCA = certMgr.generateRootCA;
|
|
module.exports.isRootCAFileExists = certMgr.isRootCAFileExists;
|