最新消息: 电脑我帮您提供丰富的电脑知识,编程学习,软件下载,win7系统下载。

如何使用ssh2和流星中的socket.io确保单个私有ssh连接

IT培训 admin 12浏览 0评论

如何使用ssh2和流星中的socket.io确保单个私有ssh连接

我正在使用ssh2和socket.io为Meteor 1.8.1应用程序的用户启用到远程服务器的实时ssh连接。该应用程序在Nginx和Phusion Passenger下在Ubuntu上运行。这是应用程序需要执行的操作:

  • 每个授权用户已经在远程服务器上拥有一个帐户。
  • 用户将通过输入其凭据并单击应用程序中的“连接”按钮来开始会话。
  • 用户可以在远程服务器上的主目录中浏览目录列表。
  • 没有用户应有权访问另一个用户的ssh会话。
  • 当用户单击“断开连接”按钮时,应从服务器上删除其ssh会话。

我的ssh连接正常工作,但是我无法弄清楚如何在用户会话结束时销毁ssh连接。每次他们按“断开连接”然后“连接”时,都会启动另一个ssh会话,并且旧的ssh会话仍可运行,因此发送的每个ssh命令都会执行多次,并且多个响应会发送到浏览器。

我也担心连接不安全;在开发中,我正在使用require('http')。createServer();创建服务器。在生产中,在配置了SSL的Ubuntu服务器上,足以使用require('https')。createServer();了。还是需要其他配置,例如Nginx?当websocket不可用时,Socket.io会回退到较旧的技术。如何确保安全?

  • 主要问题:为什么每次用户断开连接然后再连接时,我都会看到重复的SSH会话?

  • 次要问题:在哪里可以找到有关如何保护socket.io的最新说明?还是应该放弃socket.io并使用WebSocket?

我已经阅读了很多文章和堆栈溢出文章,但是我发现这非常令人困惑,并且大多数材料已经过时了。例如,不维护socketio-auth。在身份验证或授权的Socket.io documentation中几乎找不到任何内容-有handshake条目,但是由此我不清楚是需要的功能还是如何使用它。

这是我的代码。

服务器

    io.on('connection', (socket) => {
        console.log('socket id', socket.id); // this shows a new id after disconnect / reconnect

        const conn = new SSHClient();

        socket.on('disconnect', () => {
            console.log('disconnect on server');
            conn.end();
        });

        conn.on('ready', () => {
            socket.emit('message', '*** SSH CONNECTION ESTABLISHED ***');
            socket.emit('ready', 'ready');

            conn.shell((err, stream) => {
                stream.write('stty -echo \n'); // don't echo our own command back, or the user's password...

                if (err) {
                    return socket.emit('message', `*** SSH SHELL ERROR: ' ${err.message} ***`);
                }
                socket.on('path', (path) => {
                    // path is a request for a directory listing
                    if (typeof path === 'string') {
                        const bashCommand = `ls -l ${path} --time-style=full-iso`;
                        console.log('*** WRITE'); // if you disconnect and reconnect this runs twice. Disconnect and reconnect again, it runs 3 times.
                        console.log('socket id again', socket.id); // this shows the same new socket id each time
                        stream.write(`${bashCommand} \n`);
                    }
                });
                stream.on('data', (d) => {
                    socket.emit('data', response); // tell the browser!
                }).on('close', () => {
                    conn.end();
                });
            });
        }).on('close', () => {
            socket.emit('message', '*** SSH CONNECTION CLOSED ***');
        }).on('error', (err) => {
            socket.emit('message', `*** SSH CONNECTION ERROR: ${err.message} ***`);
        }).connect({
            'host': hosturl,
            'username': ausername,
            'agent': anagent, // just for dev I'm using public / private key from my local machine but this will be replaced with the user's entered credentials
        });
    }).on('disconnect', () => {
        console.log('user disconnected');
    });

    server.listen(8080);

客户:

const io = require('socket.io-client');
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {};
const myEmitter = new MyEmitter();

const PORT = 8080;

let socket;

myEmitter.on('connectClicked', () => {
    if (socket) {
        this.connected.set(socket.connected);
    }

    if (this.connected.get() === false) {
        socket = io(`http://localhost:${PORT}`);

        socket.on('connect', () => {
            this.connected.set(true);

            socket.on('ready', () => {
                console.log('ready');
            });

            // Backend -> Browser
            socket.on('message', (data) => {
                console.log('socket on message', data);
            });

            // Backend -> Browser
            socket.on('data', (data) => {
                console.log('got data', data);
                this.parseResponse(data); // client function to handle data, not shown here
            });

            // Browser -> Backend
            myEmitter.on('selectDirectory', () => {
                console.log('*** SELECT DIRECTORY');
                socket.emit('path', pathArray.join('/')); // path array is set in client code, it is a simple array of directory names
            });

            socket.on('disconnect', () => {
                console.log('\r\n*** Disconnected from backend***\r\n');
                this.connected.set(false);
            });
        });
    }

    myEmitter.on('disconnectClicked', () => {
        socket.disconnect();
    });
});
回答如下:

保持ssh连接分离的答案是维护当前ssh连接的列表并重新编写代码,以便将接收到的ssh数据仅发送到与传入消息相对应的浏览器。

我也放弃了socket.io,因为我对安全性没有信心。我现在正在通过the Meteor Direct Stream Access package使用Meteor的内置DDP消息系统。我认为这避免了打开对我的Web服务器的任何新访问点。

如何使用ssh2和流星中的socket.io确保单个私有ssh连接

我正在使用ssh2和socket.io为Meteor 1.8.1应用程序的用户启用到远程服务器的实时ssh连接。该应用程序在Nginx和Phusion Passenger下在Ubuntu上运行。这是应用程序需要执行的操作:

  • 每个授权用户已经在远程服务器上拥有一个帐户。
  • 用户将通过输入其凭据并单击应用程序中的“连接”按钮来开始会话。
  • 用户可以在远程服务器上的主目录中浏览目录列表。
  • 没有用户应有权访问另一个用户的ssh会话。
  • 当用户单击“断开连接”按钮时,应从服务器上删除其ssh会话。

我的ssh连接正常工作,但是我无法弄清楚如何在用户会话结束时销毁ssh连接。每次他们按“断开连接”然后“连接”时,都会启动另一个ssh会话,并且旧的ssh会话仍可运行,因此发送的每个ssh命令都会执行多次,并且多个响应会发送到浏览器。

我也担心连接不安全;在开发中,我正在使用require('http')。createServer();创建服务器。在生产中,在配置了SSL的Ubuntu服务器上,足以使用require('https')。createServer();了。还是需要其他配置,例如Nginx?当websocket不可用时,Socket.io会回退到较旧的技术。如何确保安全?

  • 主要问题:为什么每次用户断开连接然后再连接时,我都会看到重复的SSH会话?

  • 次要问题:在哪里可以找到有关如何保护socket.io的最新说明?还是应该放弃socket.io并使用WebSocket?

我已经阅读了很多文章和堆栈溢出文章,但是我发现这非常令人困惑,并且大多数材料已经过时了。例如,不维护socketio-auth。在身份验证或授权的Socket.io documentation中几乎找不到任何内容-有handshake条目,但是由此我不清楚是需要的功能还是如何使用它。

这是我的代码。

服务器

    io.on('connection', (socket) => {
        console.log('socket id', socket.id); // this shows a new id after disconnect / reconnect

        const conn = new SSHClient();

        socket.on('disconnect', () => {
            console.log('disconnect on server');
            conn.end();
        });

        conn.on('ready', () => {
            socket.emit('message', '*** SSH CONNECTION ESTABLISHED ***');
            socket.emit('ready', 'ready');

            conn.shell((err, stream) => {
                stream.write('stty -echo \n'); // don't echo our own command back, or the user's password...

                if (err) {
                    return socket.emit('message', `*** SSH SHELL ERROR: ' ${err.message} ***`);
                }
                socket.on('path', (path) => {
                    // path is a request for a directory listing
                    if (typeof path === 'string') {
                        const bashCommand = `ls -l ${path} --time-style=full-iso`;
                        console.log('*** WRITE'); // if you disconnect and reconnect this runs twice. Disconnect and reconnect again, it runs 3 times.
                        console.log('socket id again', socket.id); // this shows the same new socket id each time
                        stream.write(`${bashCommand} \n`);
                    }
                });
                stream.on('data', (d) => {
                    socket.emit('data', response); // tell the browser!
                }).on('close', () => {
                    conn.end();
                });
            });
        }).on('close', () => {
            socket.emit('message', '*** SSH CONNECTION CLOSED ***');
        }).on('error', (err) => {
            socket.emit('message', `*** SSH CONNECTION ERROR: ${err.message} ***`);
        }).connect({
            'host': hosturl,
            'username': ausername,
            'agent': anagent, // just for dev I'm using public / private key from my local machine but this will be replaced with the user's entered credentials
        });
    }).on('disconnect', () => {
        console.log('user disconnected');
    });

    server.listen(8080);

客户:

const io = require('socket.io-client');
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {};
const myEmitter = new MyEmitter();

const PORT = 8080;

let socket;

myEmitter.on('connectClicked', () => {
    if (socket) {
        this.connected.set(socket.connected);
    }

    if (this.connected.get() === false) {
        socket = io(`http://localhost:${PORT}`);

        socket.on('connect', () => {
            this.connected.set(true);

            socket.on('ready', () => {
                console.log('ready');
            });

            // Backend -> Browser
            socket.on('message', (data) => {
                console.log('socket on message', data);
            });

            // Backend -> Browser
            socket.on('data', (data) => {
                console.log('got data', data);
                this.parseResponse(data); // client function to handle data, not shown here
            });

            // Browser -> Backend
            myEmitter.on('selectDirectory', () => {
                console.log('*** SELECT DIRECTORY');
                socket.emit('path', pathArray.join('/')); // path array is set in client code, it is a simple array of directory names
            });

            socket.on('disconnect', () => {
                console.log('\r\n*** Disconnected from backend***\r\n');
                this.connected.set(false);
            });
        });
    }

    myEmitter.on('disconnectClicked', () => {
        socket.disconnect();
    });
});
回答如下:

保持ssh连接分离的答案是维护当前ssh连接的列表并重新编写代码,以便将接收到的ssh数据仅发送到与传入消息相对应的浏览器。

我也放弃了socket.io,因为我对安全性没有信心。我现在正在通过the Meteor Direct Stream Access package使用Meteor的内置DDP消息系统。我认为这避免了打开对我的Web服务器的任何新访问点。

发布评论

评论列表 (0)

  1. 暂无评论