How to enable HSTS with node-http-proxy? - node.js

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

Related

Nodejs HTTPS->HTTPS proxy

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

nodejs http-proxy not passing URL

I'm using http-proxy module and I'm trying to send the request to port 1234 and gets its reply back.
But in the apache logs I can see that request is only to /. The documentation says to use toProxy: true in order to pass the URL but it isn't working.
https://github.com/http-party/node-http-proxy
toProxy: true/false, passes the absolute URL as the path (useful for proxying to proxies)
Here is the code:
var http = require('http');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer();
var fs = require('fs');
http.createServer(function(req, res) {
return proxy.web(req, res, { target: {host: 'localhost', port: 1234},
ssl: {
key: fs.readFileSync('/root/test.pem', 'utf8'),
cert: fs.readFileSync('/root/test_cert.pem', 'utf8')
},
toProxy: true
});
}).listen(3000);
I'm using curl to test and checking the apache logs which is listening on port 1234.
curl -v http://localhost:3000/getsomething.html
Figured it out. I had to include protocol.
return proxy.web(req, res, { target: { protocol: 'https:', host: 'localhost', port: 1234},

Http proxy with https target

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);

Redirect http to https in Hapi.js

I do have the following configuration for my hapi server
const server = new Hapi.Server();
const tls = {
cert: fs.readFileSync(path.join(__dirname, '../certificates/cert.crt')),
key: fs.readFileSync(path.join(__dirname, '../certificates/cert.key')),
};
server.connection({
port: process.env.PORT_HTTP || 80,
host: process.env.HOST || 'localhost',
});
server.connection({
port: process.env.PORT_HTTPS || 443,
host: process.env.HOST || 'localhost',
tls,
});
The server is working ok on both, http and https, but I would like to redirect all the traffic from the http to https.
How should I proceed, tried already to register the hapi-require-https npm module but the traffic still remain the same, nothing happens.
Create an extra server for http requests and bind them to redirect function.
var Hapi = require('hapi');
var http = new Hapi.Server(80);
var server = new Hapi.Server(443, { tls: {} });
var redirect = function () {
this.reply.redirect('https://your.site/' + this.params.path);
});
http.route({ method: '*', path: '/{path*}', handler: redirect });
Update(other option)
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
if(request.headers.referer.split(':')[0] == "http"){
this.reply.redirect('https://your.site' + this.params.path);
}
}
});
How about this? Binding them both
var http = new Hapi.Server(80); // our extra server
http.route({
method: '*',
path: '/{path*}',
handler:
function (request, reply) {
// if(request.headers.referer.split(':')[0] == "http"){
this.reply.redirect('https://your.site' + this.params.path);
// }
}
});
Create two server instances to handle http & https traffic seperately.
var Hapi = require('hapi');
var server = new Hapi.Server(80);
var httpsServer = new Hapi.Server(443, { tls: { // your certificates here} });
Now register the hapi-gate plugin to the base server so that it redirects the traffic to https.
server.register({
register: require('hapi-gate'),
options: {https: true} // will force https on all requests
});
You can also use the hapi-require-https plugin instead.

Include subdomain when proxying in node

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.

Resources