2011-11-17 144 views
17

我正在開發一個node.js代理服務器應用程序,我希望它支持HTTPHTTPS(SSL)協議(作爲服務器)。node.js中的HTTPS代理服務器

我目前使用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); 

設置我的瀏覽器使用HTTP代理上localhost:8000和它的作品。我也想抓HTTPS請求(即設置我的瀏覽器使用localhost:8000作爲HTTPS代理以及捕獲我的應用程序中的請求)。你能幫我嗎我該怎麼做?

PS

如果我訂閱upgrade事件httpProxy服務器對象的我能得到請求,但我不知道如何將請求轉發和發送響應客戶端:

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

任何幫助,將不勝感激。

回答

2

node-http-proxy文檔包含此示例。請在https://github.com/nodejitsu/node-http-proxy處尋找「從HTTPS接近HTTPS」每個瀏覽器的配置過程略有不同。有些可以選擇使用所有協議的代理設置;有些需要單獨配置SSL代理。

7

我創建了一個HTTP/HTTPS代理與http-proxy模塊的幫助:https://gist.github.com/ncthis/6863947

守則截至目前:

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

該要點的鏈接已過時。我已經更新到https://gist.github.com/ncthis/6863947 – david

+1

@david再次過時 – fidev

+0

'httpProxy.HttpProxy不是函數' –

15

解決方案几乎不存在這一點,和文檔是窮人充其量用於在一臺服務器上支持。這裏的技巧是瞭解客戶端代理配置可能會將https請求發送到http代理服務器。如果您指定一個HTTP代理,然後選中「對所有協議相同」,那麼對於Firefox來說就是這樣。

您可以通過偵聽「連接」事件來處理髮送到HTTP服務器的https連接。請注意,您將無法訪問連接事件上的響應對象,只有套接字和bodyhead。通過此套接字發送的數據將作爲代理服務器保持加密狀態。

在此解決方案中,您不必製作自己的證書,因此不會有證書衝突。流量只是被代理,不會被截取並被不同的證書重寫。

// Install npm dependencies first 
// npm init 
// npm install --save [email protected] 
// npm install --save [email protected] 

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

}); 
+0

愛你的例子。我想知道你怎麼可以增加它來處理websocket升級連接 – lzc

+0

@ y3sh你會請檢查我的問題在這裏http://stackoverflow.com/questions/43908640/node-js-http-proxy-with-https?我認爲你的例子可以幫助我,但我不知道如何實現它.. – Valip

+0

我如何添加用戶和密碼認證,以便我只轉發來自我和我的動態IP地址的請求? – koampapapa

相關問題