Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js,代理HTTPS流量,无需重新签名_Node.js_Https_Proxy_Fiddler - Fatal编程技术网

Node.js,代理HTTPS流量,无需重新签名

Node.js,代理HTTPS流量,无需重新签名,node.js,https,proxy,fiddler,Node.js,Https,Proxy,Fiddler,我正在使用Node.js构建一个代理,该代理将在本地计算机上运行,并记录所有访问的域。类似于Fiddler的工作方式,但我的程序更简单,我不需要查看数据或解密任何东西 我在HTTP上做得很好,但在HTTPS上,它使用提供的自签名证书放弃了流量。这将导致浏览器显示警告。同样的事情不会发生在fiddler中,除非您选择解密HTTPS流量 所以我的问题是:如何使用Node.js代理HTTPS流量,从而使其对用户完全透明 这是我现在正在使用的代码,使用Node.js http代理。基于Github项目,

我正在使用Node.js构建一个代理,该代理将在本地计算机上运行,并记录所有访问的域。类似于Fiddler的工作方式,但我的程序更简单,我不需要查看数据或解密任何东西

我在HTTP上做得很好,但在HTTPS上,它使用提供的自签名证书放弃了流量。这将导致浏览器显示警告。同样的事情不会发生在fiddler中,除非您选择解密HTTPS流量

所以我的问题是:如何使用Node.js代理HTTPS流量,从而使其对用户完全透明

这是我现在正在使用的代码,使用Node.js http代理。基于Github项目,代理镜像

var httpProxy = require('http-proxy'),
https = require('https'),
connect = require('connect'),
logger = connect.logger('dev'),
EventEmitter = require('events').EventEmitter,
util = require('util'),
Iconv = require('iconv').Iconv,
convertBuffer = require('./convertBuffer'),
fs = require('fs'),
net = require('net'),
url = require('url'),
path = require('path'),
certDir = path.join(__dirname, '/../cert'),
httpsOpts = {
    key: fs.readFileSync(path.join(certDir, 'proxy-mirror.key'), 'utf8'),
    cert: fs.readFileSync(path.join(certDir, 'proxy-mirror.crt'), 'utf8')
};

var Session = function (sessionId, req, res) {
EventEmitter.call(this);
var that = this;
this.id = req._uniqueSessionId = res._uniqueSessionId = sessionId;
this.request = req;
this.request.body = {asString: null, asBase64: null};
this.response = res;
this.response.body = {asString: null, asBase64: null};
this.state = 'start';

var hookInResponseWrite = function () {
    var response = that.response;
    var _write = response.write;
    var output = [];
    response.write = function (chunk, encoding) {
        output.push(chunk);
        _write.apply(response, arguments);
    };
    return output;
}, hookInRequestData = function () {
    var request = that.request,
        output = [];


    request.on('data', function (chunk, encoding) {
        output.push(chunk);
    });

    request.on('end', function () {
        var buffersConcatenated = Buffer.concat(output);
        request.body.asString = buffersConcatenated.toString();
        that.emit('request.end', that);
    });

    return output;
};

this.response.bodyBuffers = hookInResponseWrite();
this.request.bodyBuffers = hookInRequestData();

this.ended = function () {
    var buffersConcatenated = Buffer.concat(this.response.bodyBuffers);
    this.response.body.asString = convertBuffer.convertEncodingContentType(buffersConcatenated,this.response.getHeader('content-type') || '');
    this.response.body.asBase64 = buffersConcatenated.toString('base64');
    this.removeAllListeners();
 };
 };
 util.inherits(Session, EventEmitter);
 Session.extractSessionId = function (req) {
 return req._uniqueSessionId;
 };

var SessionStorage = function () {
var sessionHash = {},
    sessionIdCounter = 0,
    nextId = function () {
        return sessionIdCounter += 1;
    };

this.startSession = function (req, res) {
    var sessionId = nextId(), session;
    sessionHash[sessionId] = session = new Session(sessionId, req, res);
    return session;
};

this.popSession = function (req) {
    var sessionId = Session.extractSessionId(req),
        session = sessionHash[sessionId];

    delete sessionHash[sessionId];

    return session;
};

};


var ProxyServer = function ProxyServer() {
EventEmitter.call(this);

var proxyPort = 8888,
    secureServerPort = 8887,
    parseHostHeader = function (headersHost, defaultPort) {
        var hostAndPort = headersHost.split(':'),
            targetHost = hostAndPort[0],
            targetPort = parseInt(hostAndPort[1]) || defaultPort;

        return {hostname: targetHost, port: targetPort, host: headersHost};
    },
    sessionStorage = new SessionStorage(),
    adjustRequestUrl = function(req){
        if (requestToProxyMirrorWebApp(req)) {
            req.url = req.url.replace(/http:\/\/localhost:8889\//, '/');
        }
        req.url = url.parse(req.url).path;
    },
    proxyServer = httpProxy.createServer({
        changeOrigin: true,
        enable: {
            xforward: false
        }
    }, function (req, res, proxy) {
        var parsedHostHeader = parseHostHeader(req.headers['host'], 80),
            targetHost = parsedHostHeader.hostname,
            targetPort = parsedHostHeader.port;
        req.originalUrl = req.url;
        adjustRequestUrl(req);
        logger(req, res, function () {
            proxy.proxyRequest(req, res, {
                host: targetHost,
                port: targetPort
            });
        })

    }),
    proxy = proxyServer.proxy,
    secureServer = https.createServer(httpsOpts, function (req, res) {
        var parsedHostHeader = parseHostHeader(req.headers.host, 443);
 //            console.log('secure handler ', req.headers);
        req.originalUrl = req.url;
        if(!req.originalUrl.match(/https/)){
            req.originalUrl = 'https://' + parsedHostHeader.host + req.url;
        }
        adjustRequestUrl(req);
        logger(req, res, function () {
            proxy.proxyRequest(req, res, {
                host: parsedHostHeader.hostname,
                port: parsedHostHeader.port,
                changeOrigin: true,
                target: {
                    https: true
                }
            });
        });
    }),
    listening = false,
    requestToProxyMirrorWebApp = function (req) {
        var matcher = /(proxy-mirror:8889)|(proxy-mirror:35729)/;
        return req.url.match(matcher) || (req.originalUrl &&     req.originalUrl.match(matcher));
    };

[secureServer,proxyServer].forEach(function(server){
    server.on('upgrade', function (req, socket, head) {
 //            console.log('upgrade', req.url);
        proxy.proxyWebSocketRequest(req, socket, head);
    });
});

proxyServer.addListener('connect', function (request, socketRequest, bodyhead) {
    //TODO: trying fixing web socket connections to proxy - other web socket connections won't work :(
//        console.log('conenct', request.method, request.url, bodyhead);
    var targetPort = secureServerPort,
        parsedHostHeader = parseHostHeader(request.headers.host);
    if(requestToProxyMirrorWebApp(request)){
        targetPort = parsedHostHeader.port;
    }
    var srvSocket = net.connect(targetPort, 'localhost', function () {
        socketRequest.write('HTTP/1.1 200 Connection Established\r\n\r\n');
        srvSocket.write(bodyhead);
        srvSocket.pipe(socketRequest);
        socketRequest.pipe(srvSocket);
    });
});


this.emitSessionRequestEnd = function (session) {
    this.emit('session.request.end', session);
};

this.startSession = function (req, res) {
    if (requestToProxyMirrorWebApp(req)) {
        return;
    }
    var session = sessionStorage.startSession(req, res);
    this.emit('session.request.start', session);
    session.on('request.end', this.emitSessionRequestEnd.bind(this));
};
this.endSession = function (req, res) {
    if (requestToProxyMirrorWebApp(req)) {
        return;
    }
    var session = sessionStorage.popSession(req);
    if (session) {
        session.ended();
        this.emit('session.response.end', session);
    }
};

this.start = function (done) {
    done = done || function () {
    };
    proxy.on('start', this.startSession.bind(this));
    proxy.on('end', this.endSession.bind(this));
    proxyServer.listen(proxyPort, function () {
        secureServer.listen(secureServerPort, function () {
            listening = true;
            done();
        });
    });
};

this.stop = function (done) {
    done = done || function () {
    };
    proxy.removeAllListeners('start');
    proxy.removeAllListeners('end');
    if (listening) {
        secureServer.close(function () {
            proxyServer.close(function () {
                listening = false;
                done();
            });
        });
    }
};
 };
 util.inherits(ProxyServer, EventEmitter);


module.exports = ProxyServer;

你没有分享你的代码,这将使你很难帮助你,因为它不清楚如何“神奇地”退出流量。辞职流量不是一件小事,需要大量代码,这意味着您正在使用库或其他代表您这样做的东西。感谢Eric的回复。我想要的实际上是我可以很容易地用fiddlercore做的事情,但我也需要它在OSX上工作。我将尝试解释用例,但无法深入实际细节。用户位于防火墙后面,防火墙阻止对web的访问。要通过它,需要使用两个socks5代理。一个用于业务域,另一个用于一般域。我知道这听起来很奇怪,但这就是它的工作原理。在fiddlercore中,我只做了(但我确信库所做的是真正高级的):private void FiddlerApplication_BeforeRequestClient(Session oSession){if(isBusinessDomain(oSession.fullUrl))oSession[“x-overrideGateway”]=“socks=127.0.0.1:8888”;否则…我不确定fiddler是否真的代理了请求。我假设它像wireshark一样嗅探流量。如果您的用例更像fiddler,那么嗅探流量比实际代理流量要好。