node.js中的HTTPS代理服务器

node.js中的HTTPS代理服务器,http,node.js,ssl,https,proxy,Http,Node.js,Ssl,Https,Proxy,我正在开发一个node.js代理服务器应用程序,我希望它支持HTTP和HTTPS(SSL)协议(作为服务器) 我目前使用的是: const httpProxy = require('http-proxy'), http = require('http'); var server = httpProxy.createServer(9000, 'localhost', function(req, res, proxy) { console.log(req.url); p

我正在开发一个
node.js
代理服务器应用程序,我希望它支持
HTTP
HTTPS(SSL)
协议(作为服务器)

我目前使用的是:

const httpProxy = require('http-proxy'),
      http = require('http');

var server = httpProxy.createServer(9000, 'localhost', function(req, res, proxy) {
    console.log(req.url);
    proxy.proxyRequest(req, res);
});

http.createServer(function(req, res) {
    res.end('hello!');
}).listen(9000);

server.listen(8000);
我将浏览器设置为在
localhost:8000
上使用
HTTP
代理,它可以正常工作。我还想捕获
HTTPS
请求(即,将我的浏览器设置为使用
localhost:8000
作为
HTTPS
代理,并在我的应用程序中捕获请求)。你能帮我吗?我怎么做

PS

如果我订阅
httpProxy
服务器对象的
upgrade
事件,我可以获得请求,但我不知道如何转发请求并向客户端发送响应:

server.on('upgrade', function(req, socket, head) {
    console.log(req.url);
    // I don't know how to forward the request and send the response to client
});

如果您有任何帮助,我们将不胜感激。

节点http代理文档包含这方面的示例。在配置过程中查找“从HTTPS代理到HTTPS”在每个浏览器中都略有不同。有些人可以选择对所有协议使用代理设置;有些用户需要单独配置SSL代理。

我在模块的帮助下创建了一个http/https代理:

截至目前的代码:

var fs = require('fs'),
  http = require('http'),
  https = require('https'),
  httpProxy = require('http-proxy');

var isHttps = true; // do you want a https proxy?

var options = {
  https: {
    key: fs.readFileSync('key.pem'),
    cert: fs.readFileSync('key-cert.pem')
  }
};

// this is the target server
var proxy = new httpProxy.HttpProxy({
  target: {
    host: '127.0.0.1',
    port: 8080
  }
});

if (isHttps)
  https.createServer(options.https, function(req, res) {
    console.log('Proxying https request at %s', new Date());
    proxy.proxyRequest(req, res);
  }).listen(443, function(err) {
    if (err)
      console.log('Error serving https proxy request: %s', req);

    console.log('Created https proxy. Forwarding requests from %s to %s:%s', '443', proxy.target.host, proxy.target.port);
  });
else
  http.createServer(options.https, function(req, res) {
    console.log('Proxying http request at %s', new Date());
    console.log(req);
    proxy.proxyRequest(req, res);
  }).listen(80, function(err) {
    if (err)
      console.log('Error serving http proxy request: %s', req);

    console.log('Created http proxy. Forwarding requests from %s to %s:%s', '80', proxy.target.host, proxy.target.port);
  });

这方面的解决方案几乎不存在,对于在一台服务器上同时支持这两个方面,文档充其量也很差。这里的诀窍是理解客户端代理配置可能会向http代理服务器发送https请求。如果您指定HTTP代理,然后选中“所有协议相同”,则Firefox也是如此

您可以通过侦听“connect”事件来处理发送到HTTP服务器的https连接。请注意,您无权访问connect事件上的响应对象,只能访问套接字和bodyhead。通过此套接字发送的数据将作为代理服务器对您进行加密

在这个解决方案中,您不必制作自己的证书,也不会因此产生证书冲突。流量只是被代理,而不是被截获并用不同的证书重写

//  Install npm dependencies first
//  npm init
//  npm install --save url@0.10.3
//  npm install --save http-proxy@1.11.1

var httpProxy = require("http-proxy");
var http = require("http");
var url = require("url");
var net = require('net');

var server = http.createServer(function (req, res) {
  var urlObj = url.parse(req.url);
  var target = urlObj.protocol + "//" + urlObj.host;

  console.log("Proxy HTTP request for:", target);

  var proxy = httpProxy.createProxyServer({});
  proxy.on("error", function (err, req, res) {
    console.log("proxy error", err);
    res.end();
  });

  proxy.web(req, res, {target: target});
}).listen(8080);  //this is the port your clients will connect to

var regex_hostport = /^([^:]+)(:([0-9]+))?$/;

var getHostPortFromString = function (hostString, defaultPort) {
  var host = hostString;
  var port = defaultPort;

  var result = regex_hostport.exec(hostString);
  if (result != null) {
    host = result[1];
    if (result[2] != null) {
      port = result[3];
    }
  }

  return ( [host, port] );
};

server.addListener('connect', function (req, socket, bodyhead) {
  var hostPort = getHostPortFromString(req.url, 443);
  var hostDomain = hostPort[0];
  var port = parseInt(hostPort[1]);
  console.log("Proxying HTTPS request for:", hostDomain, port);

  var proxySocket = new net.Socket();
  proxySocket.connect(port, hostDomain, function () {
      proxySocket.write(bodyhead);
      socket.write("HTTP/" + req.httpVersion + " 200 Connection established\r\n\r\n");
    }
  );

  proxySocket.on('data', function (chunk) {
    socket.write(chunk);
  });

  proxySocket.on('end', function () {
    socket.end();
  });

  proxySocket.on('error', function () {
    socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
    socket.end();
  });

  socket.on('data', function (chunk) {
    proxySocket.write(chunk);
  });

  socket.on('end', function () {
    proxySocket.end();
  });

  socket.on('error', function () {
    proxySocket.end();
  });

});

以下是我的无依赖性解决方案(纯NodeJS系统库):

我用Firefox代理设置测试了这段代码(它甚至要求输入用户名和密码!)。我输入了运行此代码的机器的IP地址和9191端口,如代码中所示。我还设置了“对所有协议使用此代理服务器”。我在本地和VPS上运行此代码-在这两种情况下都有效

您可以使用curl测试NodeJS代理:

curl -x http://username:password@127.0.0.1:9191 https://www.google.com/

指向要点的链接已经过时。我已将其更新为@david,再次过期
httpProxy.httpProxy不是一个函数
如何添加ssl证书?喜欢你的示例。我想知道您如何扩展它来处理websocket升级connections@y3sh请你检查一下我的问题好吗?我认为您的示例可以帮助我,但我不知道如何实现。我如何才能将用户和密码身份验证添加到该示例中,以便只转发来自我和我的动态IP地址的请求?@y3sh您应该编写一个npm包为什么“connect”侦听器仅为https触发?根据文档,connect是http上的事件之一,因此我不确定如何划分协议。通过它,您可以了解一些信息,如最终url的主机名和端口,但不知道完整url(带搜索路径)和请求方法。你知道怎么得到这些信息吗?什么意思?您想知道目标查询参数还是什么?是否可以从服务器读取响应数据?我试图通过socketServer侦听数据事件,但结果不可读。我只是得到了这样的东西:buړp������3&这仅适用于HTTP。对于HTTPS,这是不可能的,因为它是“加密科学”!在这种情况下,您的NodeJS代理将是“中间人”。“加密科学”主要用于防御浏览器服务器连接,以对抗任何“中间人”…这太棒了,我能问一下你是如何/从哪里学会如何编写代理的吗?我有兴趣扩展它来做一个转发代理。
curl -x http://username:password@127.0.0.1:9191 https://www.google.com/