node.js 中的 HTTPS 代理服务器

标签 http node.js ssl https proxy

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

我目前正在使用 node-http-proxy像这样:

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

任何帮助将不胜感激。

最佳答案

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

您可以通过监听“connect”事件来处理发送到 HTTP 服务器的 https 连接。请注意,您将无法访问连接事件的响应对象,只能访问套接字和 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();
  });

});

关于node.js 中的 HTTPS 代理服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8165570/

相关文章:

http - 使用 gocraft 中间件检查 HTTP 请求的主体

node.js - 使用 async_hooks 跟踪上下文

ssl - Neo4j 中的常见 SSLEngine 错误

http - HTTP PUT 请求是否需要包含正文?

java - restful web 服务 : HTTP Status 500. 服务器遇到内部错误,阻止它完成此请求错误

javascript - 使用 Javascript 从 SQLITE Select 接收数据

node.js - CI/CD 到 Azure AppService 失败,ENOENT : no such file or directory, 打开 '/home/site/wwwroot/package.json'

ssl - 客户端无法在端口 5223 上使用 SSL 连接 ejabberd

ssl - 通配符证书在未指定 FQDN 时标记为无效,即使它在搜索域中?

c - C 中的 HTTP 请求语法