From 9069aca2260f37ee10aae119ca52cd2b0e720f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=A0=E9=87=8C?= Date: Wed, 13 Aug 2014 17:30:16 +0800 Subject: [PATCH] update doc ,ready to push to npm --- .gitignore | 28 +++------------- README.md | 74 ++++++++++++++++++++++++++++++++++--------- lib/asyncTaskMgr.js | 3 +- lib/certMgr.js | 12 +++---- lib/httpsServerMgr.js | 9 +++--- package.json | 3 +- rule_sample.js | 26 ++++----------- 7 files changed, 85 insertions(+), 70 deletions(-) diff --git a/.gitignore b/.gitignore index 6ed0009..287ccbe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ +cert/**/*.srl +cert/**/*.key +cert/**/*.crt +cert/**/*.csr +tmp.txt .*.swp ._* .DS_Store @@ -6,39 +11,16 @@ .lock-wscript .svn .wafpickle-* -tmp.txt CVS npm-debug.log -cert/**/*.srl -cert/**/*.key -cert/**/*.crt -cert/**/*.csr - -# Logs logs *.log - -# Runtime data pids *.pid *.seed - -# Directory for instrumented libs generated by jscoverage/JSCover lib-cov - -# Coverage directory used by tools like istanbul coverage - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt - -# Compiled binary addons (http://nodejs.org/api/addons.html) build/Release - -# Dependency directory -# Commenting this out is preferred by some people, see -# https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git node_modules - -# Users Environment Variables .lock-wscript \ No newline at end of file diff --git a/README.md b/README.md index 859d7b0..75216e1 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,16 @@ anyproxy ========== ## Intro -While there are lots of proxy written by nodejs in github, most of them can not handle users' HTTPS requests perfectly. A typical problem is that the browser will throw some warning like INVALID_CERTIFICATE when some https requests are sent. +While there are lots of proxy written by nodejs in github, most of them can not handle users' HTTPS requests perfectly. A typical problem is that the browser will throw warning like INVALID_CERTIFICATE when some https requests are sent. A simple and fast solution is to short the traffic between the user and the target server. That is to say, what the proxy do is to forward all the traffic of both sides, without intercepting or looking inside. This is useful when you want to establish a standard proxy and do some forwarding tasks. But this can also be useless when using as a debug tool. -To work as a debug tool of HTTPS, the proxy itself should do two things : intercept the request and cheat the browser with a valid certificate. This is what you know as the man-in-the-middle attack. +To work as a debug tool of HTTPS, the proxy itself should do two things : intercept the request and cheat the browser with a valid certificate,aka the man-in-the-middle(MITM) attack. In order to have a browser-trusted certificate, we would sign certificates dynamically. The first thing to do is to generate a self-signed root CA and import to the system keychain. After trusting this CA, all child certs signed by it can be naturally trusted by the browser. -What this proxy do is to generate and replace a temporary cert for any domain if neccessary. Using it, we can intercept all the https requests for debug. BTW, this is also what the charlse/fiddler do when you check the HTTPS_PROXY in preference settings. +What this proxy do is to generate and replace a temporary cert for any domain if neccessary. Using it, we can intercept any requests for debug. BTW, this is also what the charlse/fiddler do when you check the HTTPS_PROXY in preference settings. ## Feature * can work as http or https proxy @@ -19,24 +19,68 @@ What this proxy do is to generate and replace a temporary cert for any domain if ## How to use ### step 0 - setup env -* install NodeJS -* install [openssl](http://www.openssl.org/) , i.e. the command ``openssl`` should be exposed to your shell -### step 1 - clone codes -* Clone repo with ``https://github.com/ottomao/anyproxy.git`` -* change working directory to anyproxy ``cd anyproxy`` +* install NodeJS +* install [openssl](http://wiki.openssl.org/index.php/Compilation_and_Installation) , i.e. the command ``openssl`` should be exposed to your shell + +### step 1 - install + +* ``npm install -g anyproxy`` , may need ``sudo`` + ### step 2 - generate a rootCA and trust it -* ``cd cert`` -* run ``./gen-rootCA`` ,filling the necessary info according to the tip -* trust this rootCA. In OSX, just double-click rootCA.crt and add to system keychain -* ``cd ..`` +* execute ``anyproxy --root`` ,follow the instructions on screen +* you will see some tip like *rootCA generated at : /usr/lib...* , just cd to that position, add the rootCA.crt file to your system keychain and trust. In OSX, you may do that by open the *crt file directly -### start server -* ``node bin.js`` , or use ``node bin.js --help`` for help +### step 3 - start server +#### with default settings +* ``anyproxy`` +#### set port +* ``anyproxy --port 8001`` + +#### start a https proxy +* ``anyproxy --type https --host my.domain.com`` +* the param ``host`` is required with https proxy and it should be kept exactly what it it when you config your browser. Otherwise, you may get some warning about security. + +### others + +#### clear all the temperary certificates +* ``anyproxy --clear`` + +#### may file to local +* ``anyproxy --rule /path/to/rule.js`` +* a sample schema of ruls.js is as follows + +```javascript +var rules = { + "map" :[ + { + "host" :/./, //regExp + "path" :/\/path\/test/, //regExp + "localFile" :"", //this file will be returned to user when host and path pattern both meets the request + "localDir" :"~/" //find the file of same name in localdir. anyproxy will not read localDir settings unless localFile is falsy + } + ,{ + "host" :/./, + "path" :/png/, + "localFile" :"/Users/Stella/tmp/test.png", + "localDir" :"~/" + } + ] + ,"httpsConfig":{ + "bypassAll" : false, //by setting this to true, anyproxy will not intercept any https request + "interceptDomains":[/www\.a\.com/,/www\.b\.com/] //by setting bypassAll:false, requests towards these domains will be intercepted, and try to meet the map rules above + } +} + +module.exports = rules; + +``` ## Contact -Otto Mao +Author : Otto Mao, from Shanghai,China ottomao@gmail.com + +Please feel free to raise any issue about this project, or give me some advice on this poor english doc. :) diff --git a/lib/asyncTaskMgr.js b/lib/asyncTaskMgr.js index 470ef68..a96987d 100644 --- a/lib/asyncTaskMgr.js +++ b/lib/asyncTaskMgr.js @@ -41,11 +41,12 @@ function asyncTaskMgr(){ while(tmpCb = task.callbackList.shift()){ tmpCb && tmpCb.apply(null,task.result); } - } }); } } + + }; module.exports = asyncTaskMgr; diff --git a/lib/certMgr.js b/lib/certMgr.js index 35a1dae..c0ab880 100644 --- a/lib/certMgr.js +++ b/lib/certMgr.js @@ -4,7 +4,7 @@ var exec = require('child_process').exec, fs = require("fs"), os = require("os"), color = require('colorful'), - asyncTask = require("./asyncTaskMgr"); + asyncTask = require("async-task-mgr"); var certDir = path.join(getUserHome(),"/.anyproxy_certs/"), cmdDir = path.join(__dirname,"..","./cert/"), @@ -19,16 +19,16 @@ function getCertificate(hostname,cb){ crtFile = path.join(certDir , "__hostname.crt".replace(/__hostname/,hostname) ); if(!fs.existsSync(keyFile) || !fs.existsSync(crtFile)){ - asyncTaskMgr.addTask(hostname,function(err){ + asyncTaskMgr.addTask(hostname,function(cb){ + createCert(hostname,function(err){ + cb(err ? err : null); + }); + },function(err){ if(!err){ cb(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile) ); }else{ cb(err); } - },function(cb){ - createCert(hostname,function(err){ - cb(err ? -1 : null); - }); }); }else{ diff --git a/lib/httpsServerMgr.js b/lib/httpsServerMgr.js index f554731..6f0e8a1 100644 --- a/lib/httpsServerMgr.js +++ b/lib/httpsServerMgr.js @@ -8,7 +8,7 @@ var getPort = require('./getPort'), url = require('url'), color = require('colorful'), certMgr = require("./certMgr"), - asyncTask = require("./asyncTaskMgr"); + asyncTask = require("async-task-mgr"); var DEFAULT_RELEASE_TIME = 120*1000; @@ -40,9 +40,10 @@ module.exports =function(){ //create server with corresponding CA }else{ - asyncTaskMgr.addTask(hostname ,userCB,function(cb){ - createServer(cb); - }); + asyncTaskMgr.addTask(hostname, createServer ,userCB); + // ,function(cb){ + // createServer(cb); + // }); function createServer(cb){ async.series([ diff --git a/package.json b/package.json index 742277f..d7a3f34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anyproxy", - "version": "0.2.4", + "version": "1.0.0", "description": "https proxy over http", "main": "proxy.js", "bin": { @@ -8,6 +8,7 @@ }, "dependencies": { "async": "~0.9.0", + "async-task-mgr": "^1.0.1", "colorful": "^2.1.0", "commander": "~2.3.0" }, diff --git a/rule_sample.js b/rule_sample.js index 2377030..8da9c8a 100644 --- a/rule_sample.js +++ b/rule_sample.js @@ -1,10 +1,10 @@ var rules = { "map" :[ { - "host" :/./, - "path" :/\/path\/test/, - "localFile" :"", - "localDir" :"~/" + "host" :/./, //regExp + "path" :/\/path\/test/, //regExp + "localFile" :"", //this file will be returned to user when host and path pattern both meets the request + "localDir" :"~/" //find the file of same name in localdir. anyproxy will not read localDir settings unless localFile is falsy } ,{ "host" :/./, @@ -12,24 +12,10 @@ var rules = { "localFile" :"/Users/Stella/tmp/test.png", "localDir" :"~/" } - ,{ - "host" :/./, - "path" :/jpg/, - "localFile" :"/Users/Stella/tmp/test.png", - "localDir" :"~/" - } - ,{ - "host" :/./, - "path" :/gif/, - "localFile" :"/Users/Stella/tmp/test.png", - "localDir" :"~/" - } ] ,"httpsConfig":{ - // "bypassAll" : true, - // "interceptDomains":[/^.*alibaba-inc\.com$/] - "bypassAll" : false, - "interceptDomains":[] + "bypassAll" : false, //by setting this to true, anyproxy will not intercept any https request + "interceptDomains":[/www\.a\.com/,/www\.b\.com/] //by setting bypassAll:false, requests towards these domains will be intercepted, and try to meet the map rules above } }