1
我想創建一個使用Node.js的隧道,這將允許我從服務器Y訪問服務器X.服務器X連接到未端口轉發的路由器,在連接之前不知道服務器X的IP,這意味着服務器X必須向服務器Y打開一個套接字,而不是相反。支持任何端口的服務器之間的隧道
我已經使用socket.io
成功創建了此版本。服務器X打開服務器Y的套接字,然後用戶可以在Web瀏覽器中訪問服務器Y,服務器Y代理服務器X下的請求。
我想要做的是允許訪問任何類型的端口在服務器X上,不僅轉發網絡請求,而且轉發任何類型的請求。例如,我想允許轉發SSH,以便可以通過服務器Y訪問服務器X上的SSH(不必是端口22)。 localtunnel.me
是一個現有的服務,它是我想要實現的一個確切示例。
是否有任何庫可以幫助我實現這個目標,還是我可以很容易地從頭開始構建它?我很容易構建Web請求隧道,也許它可以適應不僅支持Web流量?我已將代碼附加到下面的現有網絡隧道中。
服務器X(連接到服務器Y於端口3001,接收請求用於數據並將其發送回:
var socket = require('socket.io-client')('http://localhost:3001');
socket.on('connect', function(){
console.log('Connected');
// Register the event for request of data
socket.on('request', function(data){
// Get the path
var options = {
host: 'localhost',
port: 3000,
path: data.path,
method: data.method
};
var request = http.get(options, function(resp){
resp.on('data', function(chunk){
socket.emit('response', { html: chunk });
// Probably need to fix this for file transfers. Use resp.on('end'
});
}).on("error", function(e){
console.log("Got error: " + e.message);
});
//Write our post data to the request
request.write(data.data);
//End the request.
request.end();
});
socket.on('disconnect', function(){});
});
服務器Y(偵聽端口3001連接到服務器X,並監聽在Web瀏覽器與用戶請求的端口3002轉發到服務器X:
app.listen(3001);
var rwPortalSocket;
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
// Save the socket object
rwPortalSocket = socket;
});
console.log('Data channel server running at http://127.0.0.1:3001/');
// Create web server
var http = require('http');
var qs = require('querystring');
http.createServer(function (req, res) {
// Send a request
rwPortalSocket.emit('request', { path: req.url, method: req.method });
// When we get a response
rwPortalSocket.on('response', function (responseData) {
res.writeHead(200);
res.end(responseData.html);
});
}).listen(3002, '127.0.0.1');
console.log('Web server running at http://127.0.0.1:3002/');
編輯
我現在更新了我的代碼,以便支持任何TCP端口或數據包類型。該代碼工作正常,當我告訴net.connect
連接到Web服務器,但是當我告訴它連接SSH服務器,我的SSH客戶端與Protocol error: expected packet type 31, got 20
抱怨我已經添加連接到SSH我的新代碼的例子服務器下面。
服務器X(連接到服務器Y於端口3001,接收請求用於數據並將其發送回:
var socket = require('socket.io-client')('http://localhost:3001');
socket.on('connect', function(){
console.log('Connected');
// Connect to 22
var buff = "";
var connected = false;
var net = require('net');
var client = net.connect({host: 'myserver.com', port: 22}, function() { //'connect' listener
connected = true;
console.log('Connected to 22');
});
// Register the event for request of data
socket.on('request', function(data){
if (!connected)
{
client = net.connect({host: 'myserver.com', port: 22}, function() { //'connect' listener
connected = true;
console.log('Connected to 22');
client.write(data.data);
});
}
else
{
client.write(data.data);
}
client.setMaxListeners(0);
// When data comes back to this service, we send it on to the other server
client.on('data', function(data) {
//console.log(data.toString());
console.log('Server sent back: ' + data.toString());
if (connected)
{
socket.emit('response', { data: data });
} else {
buff += d.toString();
}
});
client.on('end', function() {
console.log('Disconnected from 22');
connected = false;
});
client.on('error', function(e) {
console.log(e);
});
console.log('Client sent: ' + data.data);
});
socket.on('disconnect', function(){});
});
服務器Y(偵聽端口3001連接到服務器X,並監聽在SSH客戶端(終端)的用戶請求的端口3002轉發到服務器X:
app.listen(3001);
var rwPortalSocket;
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
// Save the socket object
rwPortalSocket = socket;
});
console.log('Data channel server running at http://127.0.0.1:3001/');
// Listen for tunnel requests
net = require('net');
var server = net.createServer(function(s) { //'connection' listener
s.on('end', function() {
console.log('server disconnected');
});
s.on('data', function (d) {
rwPortalSocket.emit('request', { data: d });
});
s.on('error', function(e) {
console.log(e);
});
s.setMaxListeners(0);
// When we get a response
rwPortalSocket.on('response', function (d) {
s.write(d.data);
});
});
server.listen(3002, function() { //'listening' listener
console.log('server bound');
});
console.log('Web server running at http://127.0.0.1:3002/');