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
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 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 installed an SSL certificate on my Nodejs server.
const fs = require('fs');
const https = require('https');
const app = require('express');
https.createServer({
key: fs.readFileSync('./ssl/private.key'),
ca:fs.readFileSync('./ssl/ca_bundle.crt'),
cert: fs.readFileSync('./ssl/certificate.crt')
}, app).listen(443);
Port 443 is the default listening for for https and port 8080 is the default listening port for http. My server is working fine and I can do https://www.example.net to access my site. But if I remove https or replace it with http , I wanted my server to auto redirect to https so I added:
app.use (function (req, res, next) {
if (req.secure) {
// request was via https, so do no special handling
console.log(`Secure request`)
next();
} else {
// request was via http, so redirect to https
console.log(`Unsecure request`)
res.redirect('https://' + req.headers.host + req.url);
}
});
I can still connect file with https but if I remove it I get:
> dial tcp 312.312.d12.213:80: connectex: A connection attempt failed
> because the connected party did not properly respond after a period of
> time, or established connection failed because connected host has
> failed to respond.
I had to add
http.createServer(app).listen(80);
so that it can listen to unsecure request as well
I'm trying to create my own proxy server in NodeJs with the library node-http-proxy the problem is that I want to create a http proxy server that will have the possibility to forward the request to a https target (ex. https://google.com).
I know it's possible, because there is already a library that does this called: proxy-chain
When I try to request a https target with node-http-proxy I get an error: ERR_EMPTY_RESPONSE.
It also states in the documentation that I need to add a PKCS12 client certificate, but the proxy-chain does not do this.
Is there a way I can replicate the proxy-chain library with the node-http-proxy library?
This is my code at the moment:
var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function(req, res) {
// You can define here your custom logic to handle the request
// and then proxy the request.
proxy.web(req, res, {
target: {
hostname: 'github.com',
port: 433,
protocol: 'https',
},
secure: false,
changeOrigin: true
});
});
console.log("listening on port 5050")
server.listen(5050);
Under node.js 0.8, I'm using node-http-proxy in "router table" mode configured like so:
var httpProxy = require("http-proxy");
var config = require("./config");
proxyServer = httpProxy.createServer({
hostnameOnly: true,
router: {
"one.example.com": "localhost:9000",
"two.example.com": "localhost:9001"
},
https: {
key: config.key,
cert: config.cert,
// mitigate BEAST: https://community.qualys.com/blogs/securitylabs/2011/10/17/mitigating-the-beast-attack-on-tls
honorCipherOrder: true,
ciphers: "ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH"
}
})
proxyServer.listen(8000)
I'd like to add HSTS (HTTP Strict Transport Security) so that compliant browsers will be told to always use SSL. To do this, I need to get http-proxy to add the header:
Strict-Transport-Security: max-age=60000
(or other max-age). How can I ask node-http-proxy to efficiently append this header?
For your example, I'm not sure as it seems this older question is using http-proxy#0.8. However, here's what I've done with http-proxy#1.0.0:
var httpProxy = require('http-proxy');
// https server to decrypt TLS traffic and direct to a normal HTTP backend
var proxy = httpProxy.createProxyServer({
target: {
host: 'localhost',
port: 9009 // or whatever port your local http proxy listens on
},
ssl: {
key: fs.readFileSync('valid-ssl-key.pem', 'utf8'),
cert: fs.readFileSync('valid-ssl-cert.pem', 'utf8')
}
}).listen(443); // HTTPS listener for the real server
// http server that redirects all requests to their corresponding
// https urls, and allows standards-compliant HTTP clients to
// prevent future insecure requests.
var server = http.createServer(function(req, res) {
res.statusCode = 301;
res.setHeader('Location', 'https://' + req.headers.host.split(':')[0] + req.url);
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
return res.end();
});
server.listen(80); // HTTP listener for the old HTTP clients