HTTP Man In The Middle (MITM) Proxy written in node.js. Supports capturing and modifying the request and response data.
This example will modify any search results coming from google and replace all the result titles with "Pwned!".
var Proxy = require('http-mitm-proxy');
var proxy = Proxy();
proxy.onError(function(ctx, err) {
console.error('proxy error:', err);
});
proxy.onRequest(function(ctx, callback) {
if (ctx.clientToProxyRequest.headers.host == 'www.google.com'
&& ctx.clientToProxyRequest.url.indexOf('/search') == 0) {
ctx.use(Proxy.gunzip);
ctx.onResponseData(function(ctx, chunk, callback) {
chunk = new Buffer(chunk.toString().replace(/<h3.*?<\/h3>/g, '<h3>Pwned!</h3>'));
return callback(null, chunk);
});
}
return callback();
});
proxy.listen(8081);
Create a CA
cd ~/.http-mitm-proxy
openssl genrsa -out ca/ca.key 1024
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca/cakey.pem -out ca/cacert.pem -config /etc/ssl/openssl.cnf
echo "02" > ca/cacert.srl
openssl genrsa -out www.google.com-key.pem 1024
openssl req -new -key www.google.com-key.pem -out www.google.com.pem
openssl x509 -req -days 3650 -CA ca/cacert.pem -CAkey ca/cakey.pem -in www.google.com.csr -out www.google.com-cert.pem
Import ca/cacert.pem into the browser.
Context functions only effect the current request/response. For example you may only want to gunzip requests made to a particular host.
## Proxy ### proxy.listenStarts the proxy listening on the given port.
Arguments
- port - The port to listen on.
Example
proxy.listen(80);
Adds a function to the list of functions to get called if an error occures.
Arguments
- fn(ctx, err) - The function to be called on an error.
Example
proxy.onError(function(ctx, err) {
console.error('error in proxy for url:', ctx.clientToProxyRequest.url, err);
});
Adds a function to get called at the beginning of a request.
Arguments
- fn(ctx, callback) - The function that gets called on each request.
Example
proxy.onRequest(function(ctx, callback) {
console.log('REQUEST:', ctx.clientToProxyRequest.url);
return callback();
});
Adds a function to get called for each request data chunk (the body).
Arguments
- fn(ctx, chunk, callback) - The function that gets called for each data chunk.
Example
proxy.onRequestData(function(ctx, chunk, callback) {
console.log('REQUEST DATA:', chunk.toString());
return callback(null, chunk);
});
Adds a function to get called at the beginning of the response.
Arguments
- fn(ctx, callback) - The function that gets called on each response.
Example
proxy.onResponse(function(ctx, callback) {
console.log('BEGIN RESPONSE');
return callback();
});
Adds a function to get called for each response data chunk (the body).
Arguments
- fn(ctx, chunk, callback) - The function that gets called for each data chunk.
Example
proxy.onResponseData(function(ctx, chunk, callback) {
console.log('RESPONSE DATA:', chunk.toString());
return callback(null, chunk);
});
Adds a module into the proxy. Modules encapsulate multiple life cycle processing functions into one object.
Arguments
- module - The module to add. Modules contain a hash of functions to add.
Example
proxy.use({
onError: function(ctx, err) { },
onRequest: function(ctx, callback) { return callback(); },
onRequestData: function(ctx, chunk, callback) { return callback(null, chunk); },
onResponse: function(ctx, callback) { return callback(); },
onResponseData: function(ctx, chunk, callback) { return callback(null, chunk); }
});
Adds a stream into the request body stream.
Arguments
- stream - The read/write stream to add in the request body stream.
Example
ctx.addRequestFilter(zlib.createGunzip());
Adds a stream into the response body stream.
Arguments
- stream - The read/write stream to add in the response body stream.
Example
ctx.addResponseFilter(zlib.createGunzip());