我尝试使用Node.js创建一个隧道,这样我就可以从服务器Y访问服务器X.服务器X连接到一个没有端口转发的路由器,我赢了['知道服务器X的IP,直到它连接,这意味着服务器X必须打开到服务器Y的套接字,而不是相反。
我已使用socket.io
成功创建了此版本。服务器X打开到服务器Y的套接字,然后用户可以在Web浏览器中访问服务器Y,服务器Y将请求代理到服务器X的套接字。
我想要做的是允许访问Server X上的任何类型的端口,不仅转发Web请求,还转发任何类型的请求。例如,我想允许转发SSH,以便我可以通过服务器Y访问服务器X上的SSH(不必是端口22)。 localtunnel.me
是一项现有服务,是我想要实现的一个确切示例。
是否有任何库可以帮助我实现这一目标,或者我可以从头开始构建它吗?我轻松构建了Web请求隧道,也许它可以适应不仅仅支持网络流量?我已将代码附加到下面的现有网络隧道中。
服务器X(连接到端口3001上的服务器Y,接收数据请求并将其发回:
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,并侦听端口3002,以获取用户在Web浏览器中转发到服务器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(连接到端口3001上的服务器Y,接收数据请求并将其发回:
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,并侦听端口3002以获取来自SSH客户端(终端)中用户的请求以转发到服务器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/');
答案 0 :(得分:0)
如果与服务器X的“连接”都是基于TCP的,则可以在两端运行SSH服务器。然后,服务器X将连接到服务器Y,仅转发服务器Y上的某个端口,该端口将指向在服务器X上运行的SSH服务器。然后,您可以使用像ssh2这样的节点模块连接到服务器X上的任何端口。
动态转发的另一个选择是设置一个socks代理,如this answer中所述。从那里你可以使用npm的socks客户端模块,例如socks5-client。
如果您拥有一组固定的端口,您可以通过在服务器Y和服务器X上连接SSH服务器来简化上述解决方案,并为您希望拥有的每个端口创建一个端口转发