Http proxy with https target - node.js

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

Related

How to use two chained socks proxies for a request in nodejs

I am trying to achieve an experimental setup in nodejs as illustrated below:
https-server --> local socks5 proxy (Tor) --> my external socks5 proxy --> webserver.
The existing https-server was written in nodejs and it intercepts requests from the clients firefox browser, modifies the headers, and uses the request module to fetch the requested url provided by the client.
I would like the https request to tunnel through Tor, then through my external proxy (necessary for data collection for my experiments), and then to the webserver.
I found that the socks module has a feature for chaining proxies but it has no Agent to send the https request. The code below works with the chain of proxies and with http and not https.
const SocksClient = require('socks').SocksClient;
const options = {
destination: {
host: 'ip-api.com', // host names are supported with SOCKS v4a and SOCKS v5.
port: 80
},
command: 'connect', // Only the connect command is supported when chaining proxies.
proxies: [ // The chain order is the order in the proxies array, meaning the last proxy will establish a connection to the destination.
{
ipaddress: '127.0.0.1', // ipv4, ipv6, or hostname
port: 9050,
type: 5
},
{
ipaddress: 'my external proxy ip', // ipv4, ipv6, or hostname
port: 1080,
type: 5
}
]
};
var socket = SocksClient.createConnectionChain(options)
.then(info => {
//console.log(info.socket);
console.log(info.socket.remoteAddress);
info.socket.write('GET /json HTTP/1.1\nHost: ip-api.com\n\n');
info.socket.on('data', (data) => {
console.log(data.toString()); // ip-api.com sees that the last proxy in the chain is connected to it.
});
})
.catch(err => {
// Handle errors
console.log(err);
});
Also, there is a module called socks5-https-client that is able to send https requests over a single socks5 proxy (see code below). It uses the request module and the socks5-https-client as an agent, a solution I would prefer. Unfortunately, it does not support proxy chaining (more than 1 proxy).
var Agent = require('socks5-https-client/lib/Agent');
request({
url: 'https://encrypted.google.com/',
strictSSL: true,
agentClass: Agent,
agentOptions: {
socksHost: 'my-tor-proxy-host', // Defaults to 'localhost'.
socksPort: 9050, // Defaults to 1080.
// Optional credentials that I don't need
//socksUsername: 'proxyuser',
//socksPassword: 'p#ssw0rd',
}
}, function(err, res) {
console.log(err || res.body);
});
I am a beginner in node programming but these are my general thoughts to a solution. An https agent can be added to the existing socks module -- the module already supports chaining of proxies -- such that it can be parsed to the request module as an agent, just like in the second code. Alternatively, the socks5-https-client can be modified to have a function like the createConnectionChain() in the socks module to support multiple proxies.
I will be grateful if anyone can assist me with a solution or materials that I can follow to get this done. Thanks

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

express node-http-proxy , proxy.proxyRequest to https server?

Is it possible to use the node-http-prox module and proxy.proxyRequest to a https server?
I tried to do the following but doesnt seem to work.
app.get('/c/users/moreuser', function(req, res) {
proxy.proxyRequest(req, res, {
host: 'api.example.com',
port: 80,
https: true
});
});
doing this i dont get any response from the server. But i can get response directly from the server.
try port: 443, which is the default port for HTTPS.

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.

How to enable HSTS with node-http-proxy?

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

Resources