mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-23 15:31:26 +00:00
can be used as a node module
This commit is contained in:
parent
b22a8b482e
commit
978b549be7
33
README.md
33
README.md
@ -2,20 +2,21 @@ anyproxy
|
|||||||
==========
|
==========
|
||||||
|
|
||||||
## Intro
|
## 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 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 they want to intercept some https requests.
|
||||||
|
|
||||||
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.
|
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.
|
This is useful when you want to establish a standard proxy and forwarding data. But this can also be useless when being used 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,aka the man-in-the-middle(MITM) 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.
|
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 inherit from root CA 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 any 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 enable_ssl_proxy in preference.
|
||||||
|
|
||||||
## Feature
|
## Feature
|
||||||
* can work as http or https proxy
|
* work as http or https proxy
|
||||||
* generate and intercept https requests for any domain without complaint by browser (only after you trust its root CA)
|
* generate and intercept https requests for any domain without complaint by browser (after you trust its root CA)
|
||||||
|
* can be used globally or as a nodejs module
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
### step 0 - setup env
|
### step 0 - setup env
|
||||||
@ -46,11 +47,25 @@ What this proxy do is to generate and replace a temporary cert for any domain if
|
|||||||
|
|
||||||
### others
|
### others
|
||||||
|
|
||||||
|
#### work as a module
|
||||||
|
```
|
||||||
|
npm install anyproxy
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var proxy = require("anyproxy");
|
||||||
|
|
||||||
|
!proxy.isRootCAFileExists() && proxy.generateRootCA();
|
||||||
|
proxy.startServer("http","8001", "localhost" ,"path/to/rule/file");
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
#### clear all the temperary certificates
|
#### clear all the temperary certificates
|
||||||
* ``anyproxy --clear``
|
* ``anyproxy --clear``
|
||||||
|
|
||||||
#### map file to local
|
#### map file to local
|
||||||
* ``anyproxy --rule /path/to/rule.js``
|
* ``anyproxy --rule /path/to/ruleFile.js``
|
||||||
|
* actually ruleFile.js is a module for Nodejs
|
||||||
* a sample schema of ruls.js is as follows
|
* a sample schema of ruls.js is as follows
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -64,7 +79,7 @@ var rules = {
|
|||||||
}
|
}
|
||||||
,{
|
,{
|
||||||
"host" :/./,
|
"host" :/./,
|
||||||
"path" :/png/,
|
"path" :/\.(png|gif|jpg|jpeg)/,
|
||||||
"localFile" :"/Users/Stella/tmp/test.png",
|
"localFile" :"/Users/Stella/tmp/test.png",
|
||||||
"localDir" :"~/"
|
"localDir" :"~/"
|
||||||
}
|
}
|
||||||
|
13
bin.js
13
bin.js
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
var program = require('commander'),
|
var program = require('commander'),
|
||||||
mainProxy = require("./proxy.js"),
|
proxy = require("./proxy.js"),
|
||||||
color = require('colorful'),
|
color = require('colorful'),
|
||||||
fs = require("fs");
|
fs = require("fs");
|
||||||
|
|
||||||
@ -25,12 +25,5 @@ if(program.clear){
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
var handleRule;
|
proxy.startServer(program.type,program.port, program.host ,program.rule);
|
||||||
if(program.rule){
|
|
||||||
console.log("parsing rule file..");
|
|
||||||
var handleRule = require(program.rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
mainProxy.startServer(program.type,program.port, program.host ,handleRule);
|
|
||||||
|
|
||||||
}
|
}
|
@ -7,7 +7,6 @@ openssl req -x509 -new -nodes -key rootCA.key -days 36500 -out rootCA.crt
|
|||||||
echo "============="
|
echo "============="
|
||||||
echo "rootCA generated at :"
|
echo "rootCA generated at :"
|
||||||
pwd
|
pwd
|
||||||
echo "please trust them and add to your system keychain"
|
|
||||||
echo "============="
|
echo "============="
|
||||||
|
|
||||||
exit 0
|
exit 0
|
@ -4,6 +4,7 @@ var exec = require('child_process').exec,
|
|||||||
fs = require("fs"),
|
fs = require("fs"),
|
||||||
os = require("os"),
|
os = require("os"),
|
||||||
color = require('colorful'),
|
color = require('colorful'),
|
||||||
|
readline = require('readline'),
|
||||||
asyncTask = require("async-task-mgr");
|
asyncTask = require("async-task-mgr");
|
||||||
|
|
||||||
var certDir = path.join(getUserHome(),"/.anyproxy_certs/"),
|
var certDir = path.join(getUserHome(),"/.anyproxy_certs/"),
|
||||||
@ -60,35 +61,65 @@ function clearCerts(cb){
|
|||||||
exec("rm *.key *.csr *.crt",{cwd : certDir},cb);
|
exec("rm *.key *.csr *.crt",{cwd : certDir},cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRootCAFileExists(){
|
||||||
|
var crtFile = path.join(cmdDir,"rootCA.crt"),
|
||||||
|
keyFile = path.join(cmdDir,"rootCA.key");
|
||||||
|
|
||||||
|
return (fs.existsSync(crtFile) && fs.existsSync(keyFile));
|
||||||
|
}
|
||||||
|
|
||||||
function checkRootCA(){
|
function checkRootCA(){
|
||||||
|
if(!isRootCAFileExists()){
|
||||||
var crtFile = path.join(cmdDir,"rootCA.crt"),
|
|
||||||
keyFile = path.join(cmdDir,"rootCA.key");
|
|
||||||
|
|
||||||
if(!fs.existsSync(crtFile) || !fs.existsSync(keyFile)){
|
|
||||||
console.log(color.red("can not find rootCA.crt or rootCA.key"));
|
console.log(color.red("can not find rootCA.crt or rootCA.key"));
|
||||||
process.exit(0);
|
console.log(color.red("you may generate one by the following methods"));
|
||||||
|
console.log(color.red("\twhen using globally : anyproxy --root"));
|
||||||
|
console.log(color.red("\twhen using as a module : require(\"anyproxy\").generateRootCA();"));
|
||||||
|
process.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateRootCA(){
|
function generateRootCA(){
|
||||||
var spawnSteam = spawn("./gen-rootCA",['.'],{cwd:cmdDir,stdio: 'inherit'});
|
if(isRootCAFileExists()){
|
||||||
|
console.log(color.yellow("rootCA exists at " + certDir));
|
||||||
|
var rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout
|
||||||
|
});
|
||||||
|
|
||||||
spawnSteam.on('close', function (code) {
|
rl.question("do you really want to generate a new one ?)(yes/NO)", function(answer) {
|
||||||
if(code == 0){
|
if(/yes/i.test(answer)){
|
||||||
console.log(color.green("rootCA generated"));
|
startGenerating();
|
||||||
console.log("now clearing temp certs...");
|
}else{
|
||||||
clearCerts(function(){
|
console.log("will not generate a new one");
|
||||||
console.log(color.green("done"));
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
}
|
||||||
}else{
|
|
||||||
console.log(color.red("fail to generate root CA"));
|
rl.close();
|
||||||
}
|
});
|
||||||
});
|
}else{
|
||||||
|
startGenerating();
|
||||||
|
}
|
||||||
|
|
||||||
|
function startGenerating(){
|
||||||
|
var spawnSteam = spawn("./gen-rootCA",['.'],{cwd:cmdDir,stdio: 'inherit'});
|
||||||
|
|
||||||
|
spawnSteam.on('close', function (code) {
|
||||||
|
if(code == 0){
|
||||||
|
console.log(color.green("rootCA generated"));
|
||||||
|
console.log(color.green(color.bold("please trust the rootCA.crt in " + cmdDir)));
|
||||||
|
clearCerts(function(){
|
||||||
|
console.log(color.green("temp certs cleared"));
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
console.log(color.red("fail to generate root CA"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.generateRootCA = generateRootCA;
|
module.exports.generateRootCA = generateRootCA;
|
||||||
module.exports.getCertificate = getCertificate;
|
module.exports.getCertificate = getCertificate;
|
||||||
module.exports.createCert = createCert;
|
module.exports.createCert = createCert;
|
||||||
module.exports.clearCerts = clearCerts;
|
module.exports.clearCerts = clearCerts;
|
||||||
|
module.exports.isRootCAFileExists = isRootCAFileExists;
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "anyproxy",
|
"name": "anyproxy",
|
||||||
"version": "1.0.1",
|
"version": "1.1.0",
|
||||||
"description": "https proxy over http",
|
"description": "a charles/fiddle like web proxy for developers which can intercept https requests without browser warning",
|
||||||
"main": "proxy.js",
|
"main": "proxy.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"anyproxy": "bin.js"
|
"anyproxy": "bin.js"
|
||||||
|
20
proxy.js
20
proxy.js
@ -16,14 +16,20 @@ var T_TYPE_HTTP = 0,
|
|||||||
DEFAULT_HOST = "localhost",
|
DEFAULT_HOST = "localhost",
|
||||||
DEFAULT_TYPE = T_TYPE_HTTP;
|
DEFAULT_TYPE = T_TYPE_HTTP;
|
||||||
|
|
||||||
var httpProxyServer;
|
function startServer(type, port, hostname,ruleFile){
|
||||||
|
|
||||||
function startServer(type, port, hostname,rule){
|
|
||||||
var proxyType = /https/i.test(type || DEFAULT_TYPE) ? T_TYPE_HTTPS : T_TYPE_HTTP ,
|
var proxyType = /https/i.test(type || DEFAULT_TYPE) ? T_TYPE_HTTPS : T_TYPE_HTTP ,
|
||||||
proxyPort = port || DEFAULT_PORT,
|
proxyPort = port || DEFAULT_PORT,
|
||||||
proxyHost = hostname || DEFAULT_HOST;
|
proxyHost = hostname || DEFAULT_HOST,
|
||||||
|
httpProxyServer;
|
||||||
|
|
||||||
requestHandler.setRules(rule);
|
if(ruleFile){
|
||||||
|
if(fs.existsSync(ruleFile)){
|
||||||
|
requestHandler.setRules(require(ruleFile));
|
||||||
|
console.log(color.green("rule file loaded"));
|
||||||
|
}else{
|
||||||
|
console.log(color.red("can not find rule file"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
|
|
||||||
@ -71,4 +77,6 @@ function startServer(type, port, hostname,rule){
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.startServer = startServer;
|
module.exports.startServer = startServer;
|
||||||
|
module.exports.generateRootCA = certMgr.generateRootCA;
|
||||||
|
module.exports.isRootCAFileExists = certMgr.isRootCAFileExists;
|
@ -8,7 +8,7 @@ var rules = {
|
|||||||
}
|
}
|
||||||
,{
|
,{
|
||||||
"host" :/./,
|
"host" :/./,
|
||||||
"path" :/png/,
|
"path" :/\.(png|gif|jpg|jpeg)/,
|
||||||
"localFile" :"/Users/Stella/tmp/test.png",
|
"localFile" :"/Users/Stella/tmp/test.png",
|
||||||
"localDir" :"~/"
|
"localDir" :"~/"
|
||||||
}
|
}
|
||||||
|
21
testCert.js
21
testCert.js
@ -1,21 +0,0 @@
|
|||||||
var certMgr = require("./lib/certMgr");
|
|
||||||
|
|
||||||
certMgr.clearCerts(function(){
|
|
||||||
console.log(arguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
certMgr.getCertificate("www.test3.com",function(){
|
|
||||||
console.log(arguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
certMgr.getCertificate("www.test2.com",function(){
|
|
||||||
console.log(arguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
certMgr.getCertificate("www.test3.com",function(){
|
|
||||||
console.log(arguments);
|
|
||||||
});
|
|
||||||
|
|
||||||
certMgr.getCertificate("www.test3.com",function(){
|
|
||||||
console.log(arguments);
|
|
||||||
});
|
|
Loading…
x
Reference in New Issue
Block a user