When modifying a node-http-proxy example...
The Issue: When manually changing the req.headers.host to a remote host ('example.com'), the url in the the browser is not changing.
Note: I thought this was working, however when using google.com as my example, it turned out google was detecting the proxy and changing the host.
Question: Is there a way to change the url in the browser to a remote host (ie. example.com), everytime? Thanks!
var util = require('util'),
colors = require('colors'),
http = require('http'),
httpProxy = require('../../lib/node-http-proxy');
//
// Http Server with proxyRequest Handler and Latency
//
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
req.headers.host = 'example.com'; // manually setting example.com
var buffer = httpProxy.buffer(req);
setTimeout(function () {
proxy.proxyRequest(req, res, {
port: 80,
host: 'example.com',
buffer: buffer
});
}, 200);
}).listen(8004);
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '8004 '.yellow + 'with proxyRequest handler'.cyan.underline + ' and latency'.magenta);
util.puts('http server '.blue + 'started '.green.bold + 'on port '.blue + '9000 '.yellow);
A few solutions that will do this are:
Issue a 301 redirect.
Use IPTables to DNAT and change the desination address.
Use TPROXY to transparently proxy the requests without modifying the
packets.
Related
I have a HTTP web server and I'm trying to set it up behind a HTTPS proxy server.
I've tried the example that's in the repository: https://github.com/http-party/node-http-proxy/blob/master/examples/http/proxy-https-to-http.js but I'm always getting ERR_EMPTY_RESPONSE in browser.
Example code
var https = require('https'),
http = require('http'),
util = require('util'),
path = require('path'),
fs = require('fs'),
colors = require('colors'),
httpProxy = require('../../lib/http-proxy'),
fixturesDir = path.join(__dirname, '..', '..', 'test', 'fixtures');
//
// Create the target HTTP server
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello http over https\n');
res.end();
}).listen(9009);
//
// Create the HTTPS proxy server listening on port 8000
//
httpProxy.createServer({
target: {
host: 'localhost',
port: 9009
},
ssl: {
key: fs.readFileSync(path.join(fixturesDir, 'agent2-key.pem'), 'utf8'),
cert: fs.readFileSync(path.join(fixturesDir, 'agent2-cert.pem'), 'utf8')
}
}).listen(8009);
console.log('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8009'.yellow);
console.log('http server '.blue + 'started '.green.bold + 'on port '.blue + '9009 '.yellow);
Error
Screenshot
Browser is pointed to use 127.0.0.1:8009 proxy.
Does anybody know what's wrong ?
Any suggestion is appreciated.
I'm trying to setup an HTTPS server that proxies requests to changing targets that also enforce HTTPS. this is because I want to setup an intercepting https proxy, terminate ssl, modify data and send encrypted modifications to target server (or backwards through the response).
Example:
Browser --> myHTTPSProxy(modify request) --> https://targethost.com --> myHTTPSProxy(modify response) --> Browser
This is sample implementation for the task from the node-http-proxy library:
const https = require('https'),
fs = require('fs'),
colors = require('colors'),
httpProxy = require('http-proxy'),
httpsOpts = {
key: fs.readFileSync('agent2-key.pem', 'utf8'),
cert: fs.readFileSync('agent2-cert.pem', 'utf8')
};
// Create DUMMY HTTPS SRV
https.createServer(httpsOpts, function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(3000);
// PROXY
httpProxy.createServer({
ssl: httpsOpts,
target: 'https://localhost:3000',
secure: false
}).listen(8080);
console.log('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8080'.yellow);
console.log('https server '.blue + 'started '.green.bold + 'on port '.blue + '3000 '.yellow);
Certificates are also taken from the library, and I tried using valid ones as well that works on a straight https server but no as a proxy.
as a proxy - I get Secure Connection Failed.
TL;DR Question
Does anyone know how to implement a HTTPS proxy server using nodejs?
Similar unresolved posts:
Https proxy server(secure proxy server) in Nodejs with http-proxy is not working
https://github.com/http-party/node-http-proxy/issues/1456
https://github.com/http-party/node-http-proxy/issues/1506
I have a requirement to set up an https proxy server(Secure Web Proxy-http://dev.chromium.org/developers/design-documents/secure-web-proxy) to test one of my application with the proxy environment.
Steps followed:
1.Created an https proxy server with the help of http-proxy. code,
var https = require('https'),
http = require('http'),
util = require('util'),
fs = require('fs'),
path = require('path'),
colors = require('colors'),
httpProxy = require('http-proxy'),
// fixturesDir = path.join(__dirname, '..', '..', 'test', 'fixtures'),
httpsOpts = {
key: fs.readFileSync('server.key', 'utf8'),
cert: fs.readFileSync('server.crt', 'utf8')
};
//
// Create the target HTTPS server
//
https.createServer(httpsOpts, function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(9010);
//
// Create the proxy server listening on port 8010
//
httpProxy.createServer({
ssl: httpsOpts,
target: 'https://localhost:9010',
secure: false
}).listen(8010);
console.log('https proxy server'.blue + ' started '.green.bold + 'on port '.blue + '8010'.yellow);
console.log('https server '.blue + 'started '.green.bold + 'on port '.blue + '9010 '.yellow);
Created a PAC file with https proxy server details
function FindProxyForURL(url, host) {
return "HTTPS 127.0.0.1:8010";
}
And point the pac file in my application to test application with proxy environment, sample code pasted here.
var url = require('url');
var https = require('https');
var PacProxyAgent = require('pac-proxy-agent');
// URI to a PAC proxy file to use (the "pac+" prefix is stripped)
var proxy = 'pac+http://localhost:123/hosted/pac.pac';
//console.log('using PAC proxy proxy file at %j', proxy);
// HTTP endpoint for the proxy to connect to
var endpoint = 'https://nodejs.org/api/';
//console.log('attempting to GET %j', endpoint);
var opts = url.parse(endpoint);
// create an instance of the `PacProxyAgent` class with the PAC file location
var agent = new PacProxyAgent(proxy,opts);
opts.agent = agent;
https.get(opts, function (res) {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
But it's not working, it throws the error
Chrome behavior:
I configured the PAC file in windows proxy settings
After that I am not getting any response from any sites
ex: when I enter https://gmail.com/ it ends up with
any suggestions?
I've setup a simple HTTPS server to handle the following to situations:
Requests to https://localhost:5000/ that have a matching file in my directory are served via connect.static(__dirname). This works great for everything like my index.html and my CSS files and is working exactly as I need.
Requests to https://localhost:5000/api should redirect to https://subdomain.mydomain.com:443/api.
The proxy is properly transferring everything over HTTPS and the SSL handshake part seems to be working exactly as I would expect. The problem is that my API uses the subdomain to determine what database to connect to and what data to return. So, my API sees the request
https://localhost:5000/api/something
instead of
https://subdomain.mydomain.com/api/something
and is throwing an error telling me I have to supply the subdomain.
How can I tell the node proxy to forward (or use) the domain/subdomain when doing the proxy?
Here is my code:
var fs = require('fs');
var connect = require('connect'),
https = require('https'),
httpProxy = require('http-proxy'),
options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
},
endpoint = {
host: 'subdomain.mydomain.com',
port: 443,
prefix: '/api',
target: { https: true }
};
var proxy = new httpProxy.RoutingProxy();
var app = connect()
.use(connect.logger('dev'))
.use(function(req, res, next) {
if (req.url.indexOf(endpoint.prefix) === 0) {
proxy.proxyRequest(req, res, endpoint);
} else {
next();
}
})
.use(connect.static(__dirname));
https.createServer(options, app).listen(5000);
console.log('Listening on port 5000');
Just in case someone bumps into this old question, you should use http-proxy's changeOrigin option.
I want to do a simple node.js reverse proxy to host multiple Node.JS applications along with my apache server on the same port 80. So I found this example here
var http = require('http')
, httpProxy = require('http-proxy');
httpProxy.createServer({
hostnameOnly: true,
router: {
'www.my-domain.com': '127.0.0.1:3001',
'www.my-other-domain.de' : '127.0.0.1:3002'
}
}).listen(80);
The problem is that I want to have for example app1.my-domain.com pointing to localhost:3001, app2.my-domain.com pointing to localhost:3002, and all other go to port 3000 for example, where my apache server will be running. I couldn't find anything in the documentation on how to have a "default" route.
Any ideas?
EDIT I want to do that because I have a lot of domains/subdomains handled by my apache server and I don't want to have to modify this routing table each time I have want to add a new subdomain.
For nearly a year, I had successfully used the accepted answer to have a default host, but there's a much simpler way now that node-http-proxy allows for RegEx in the host table.
var httpProxy = require('http-proxy');
var options = {
// this list is processed from top to bottom, so '.*' will go to
// '127.0.0.1:3000' if the Host header hasn't previously matched
router : {
'example.com': '127.0.0.1:3001',
'sample.com': '127.0.0.1:3002',
'^.*\.sample\.com': '127.0.0.1:3002',
'.*': '127.0.0.1:3000'
}
};
// bind to port 80 on the specified IP address
httpProxy.createServer(options).listen(80, '12.23.34.45');
The requires that you do NOT have hostnameOnly set to true, otherwise the RegEx would not be processed.
This isn't baked into node-http-proxy, but it's simple to code:
var httpProxy = require('http-proxy'),
http = require('http'),
addresses;
// routing hash
addresses = {
'localhost:8000': {
host: 'localhost',
port: 8081
},
'local.dev:8000': {
host: 'localhost',
port: 8082
},
'default': {
host: 'xkcd.com',
port: 80
}
};
// create servers on localhost on ports specified by param
function createLocalServer(ports) {
ports.forEach(function(port) {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello from ' + port + '</h1');
}).listen(port);
});
console.log('Servers up on ports ' + ports.join(',') + '.');
}
createLocalServer([8081, 8082]);
console.log('======================================\nRouting table:\n---');
Object.keys(addresses).forEach(function(from) {
console.log(from + ' ==> ' + addresses[from].host + ':' + addresses[from].port);
});
httpProxy.createServer(function (req, res, proxy) {
var target;
// if the host is defined in the routing hash proxy to it
// else proxy to default host
target = (addresses[req.headers.host]) ? addresses[req.headers.host] : addresses.default;
proxy.proxyRequest(req, res, target);
}).listen(8000);
If you visit localhost on port 8000 it will proxy to localhost port 8081.
If you visit 127.0.0.1 on port 8000 (which is not defined in our routing hash) it will go to the default 'location', namely xkcd.com on port 80.