1

我正在尝试创建一个能够处理 HTTPS 网站的转发代理。我正在尝试观察和修改不同站点的流量。这是我的代码,适用于 http 网站,但不适用于 https 网站。

httpProxy.createServer(function(req, res, next) {
   //custom logic
   next();
}, function(req, res) {
   var proxy = new httpProxy.RoutingProxy();
   var buffer = httpProxy.buffer(req);
   var urlObj = url.parse(req.url);
   req.headers.host = urlObj.host;
   req.url = urlObj.path;
   console.log(urlObj.protocol);
  setTimeout(function() {
     proxy.proxyRequest(req, res, {
        host: urlObj.host,
        port: 80,
        buffer: buffer,
    }
   )}, 5000);

}).listen(9000, function() {
console.log("Waiting for requests...");
});

谢谢你们的帮助!

4

5 回答 5

8

在处理 https 流量时,必须指定一些 https 选项。这是我在代理设置中所做的。

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

var proxyTable = {};

proxyTable['domain.com'] = 'localhost:3001';
proxyTable['domain.com/path'] = 'localhost:3002';
proxyTable['sub.domain.com'] = 'localhost:3003';

var httpOptions = {
    router: proxyTable
};

var httpsOptions = {
    router: proxyTable,
    https: {
        passphrase: 'xxxxxxx',
        key: fs.readFileSync('/path/to/key'),
        ca: fs.readFileSync('/path/to/ca'),
        cert: fs.readFileSync('/path/to/crt')}
};

httpProxy.createServer(httpOptions).listen(80);
httpProxy.createServer(httpsOptions).listen(443);

https 的文档也在他们的 github 页面上。

https://github.com/nodejitsu/node-http-proxy

于 2013-07-24T23:15:06.810 回答
4

如果您只是在做转发代理,那么您必须考虑一些事情。

  • HTTPS 请求的代理不会触发常规请求 - 相反,您会看到 HTTP CONNECT。

这是您需要处理的序列流。

  1. CONNECT 事件从浏览器发送到 HTTPS 部分中指定的代理。你会在这里看到这个:http ://nodejs.org/api/http.html#http_event_connect请注意,这来自 HTTP 模块,而不是 HTTPS 连接。
  2. 您创建到请求的域(或映射的域)的新套接字连接。[srvSocket]
  3. 您将使用 200 响应 CONNECT 套接字
  4. 您将通过 CONNECT 事件收到的缓冲区写入 srvSocket,然后将两个套接字连接在一起srvSocket.pipe(socket);
  5. socket.pipe(srvSocket);

由于您试图在本地欺骗请求的域,因此您需要做更多的事情

  1. 您需要生成根 CA。
  2. 您需要将此证书作为受信任的权威导入您的操作系统
  3. 您将使用此证书为您尝试访问的域创建一个新的密钥/证书文件
  4. 您的映射主机将需要使用在步骤 3 中为您要映射的每个域生成的相应密钥/证书文件进行响应。
于 2013-07-30T19:30:48.897 回答
1

我们可以有一个如下的中间件

request = require("request"); app.use(function (req, res, next) { request('http://anotherurl.that.serves/the/request').pipe(res); });

参见示例https://github.com/manuks/proxy

于 2014-09-09T07:27:55.197 回答
1

https://github.com/substack/bouncy

var bouncy = require('bouncy');

var server = bouncy(function (req, res, bounce) {
    if (req.headers.host === 'beep.example.com') {
    bounce(8001);
    }
    else if (req.headers.host === 'boop.example.com') {
        bounce(8002);
    }
    else {
        res.statusCode = 404;
        res.end('no such host');
    }
});
server.listen(8000);

If you specify opts.key and opts.cert, the connection will be set to secure mode using tls. Do this if you want to make an https router.

于 2013-07-25T04:59:43.647 回答
0

基本上,在 http-proxy npm 下面是 Node 使用的一些网络库(特别是http://nodejs.org/api/https.html和 TLS)。即使我的 Apache 能够通过在我的浏览器中访问它来在没有代理的自签名证书上很好地连接我:

https://localhost:8002    

您需要建立一个证书颁发机构以克服 Node 中的“无法验证叶签名”错误(我使用了SSLCACertificateFile选项)。然后,你会被“self_signed_cert_in_chain”击中。这导致一些谷歌结果表明 npm 放弃了自签名证书,但我很确定这与 Node.js 无关。

你最终得到的是一些人表明你在你的 https 代理中使用process.env.NODE_TLS_REJECT_UNAUTHORIZEDrejectUnauthorized 。如果您深入研究 http-proxy 源,您会发现它接受代理选项。用这个:

/**
 * Module dependencies
 */

// basic includes
express     = require('express');
fs          = require('fs');
http        = require('http');
https       = require('https');
httpProxy   = require('http-proxy');
require('child_process').spawn(__dirname+'/../../../dependencies/apache/bin/httpd.exe',['-f',__dirname+'/../../../dependencies/apache/conf/httpd-payments.conf']); 

var app     = module.exports = express();
app.set('port', process.env.PORT || 8001); // we sometimes change the port

// creates an output object for this particular request
//app.use(express.cookieParser(''));
//app.use(express.bodyParser());
//app.use(express.methodOverride());

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

app.all('*',function(req,res,next) {
    var options = {
      hostname: '127.0.0.1',
      port: 8002,
      rejectUnauthorized: false,
      key: fs.readFileSync(__dirname+"/../../../deployment/server.key.pem"),
      cert: fs.readFileSync(__dirname+"/../../../deployment/server.crt.pem")
    };
    agent = new https.Agent(options);
    try {
        proxy.web(req,res, {
            target: "https://localhost:8002",
            proxyTimeout: 30,
            agent: agent
        });
    } catch(e) {
        // 500 error
        res.send(500,e);
    }
})

/** 
 * Start Server
 */

var options = {
  key: fs.readFileSync(__dirname+"/../../../deployment/server.key.pem"),
  cert: fs.readFileSync(__dirname+"/../../../deployment/server.crt.pem")
};
server  = https.createServer(options,app).listen(app.get('port'), function () {
  console.log('Running payments server on port ' + app.get('port'));
});
于 2014-10-10T10:29:02.540 回答