0

我正在实现基于 libssh (npm install ssh) 的 SFTP Nodejs 服务器脚本

var config = require('config');
var fs = require('fs');
var path = require('path');
var libssh = require('ssh');

var server;
var options = {
    host: 'localhost',
    port: '3022',
    // Get the common name of ssh_keys
    host_key: config.get('logshipper.sftp.host_key'),
    // Root path of SFTP folder on the machine
    root: path.join(__dirname, config.get('logshipper.sftp.root')),
    test_username: 'correct_username',
    test_password: 'correct_password'
};

server = libssh.createServer({
    hostRsaKeyFile: __dirname + '/ssh_keys/' + 'rsa_' + options.host_key,
    hostDsaKeyFile: __dirname + '/ssh_keys/' + 'dsa_' + options.host_key
});

server.on('connection', function (session) {
    session.on('auth', function (message) {
        // Maybe check username/password
        return message.replyAuthSuccess();
    });

    session.on('channel', function (channel) {
        channel.on('subsystem', function (message) {
            if (message.subsystem == 'sftp') {
                message.replySuccess();
                message.sftpAccept();
            }
        });

        channel.on('sftp:realpath', function (message) {
            console.log('server cmd sftp:realpath');
            if (message.filename == '.' || (/\/$/).test(message.filename)) {
                message.replyName(path.join(options.root, message.filename), {
                    permissions: +libssh.Stat('777').dir()
                })
            } else {
                message.replyName(message.filename, {
                    permissions: +libssh.Stat('777').reg()
                })
            }
        });

        channel.on('sftp:stat', statHandle);

        function statHandle(message) {
            console.log('server cmd sftp:stat');

            var attrs = {
                permissions: +libssh.Stat(777).dir()
                , uid: 101
                , gid: 202
                , size: 100
                , atime: Date.now()
                , mtime: Date.now()
            };

            message.replyAttr(attrs)
        }

        // can be handled the same way as 'stat' if you like
        channel.on('sftp:lstat', statHandle);

        channel.on('sftp:opendir', function (message) {
            console.log('server cmd sftp:opendir');
            message.replyHandle(message.filename + '/');
        });

        var lastmsg;
        channel.on('sftpmessage', function (message) {
            lastmsg = message
        });

        channel.on('sftp:readdir', function (message) {
            console.log('server cmd sftp:readdir', message.handle);

            if (lastmsg.type == 'readdir') {
                return message.replyStatus('ok');
            }

            var readPath = message.handle;
            fs.readdir(readPath, function(err, files) {
                if (err) {
                    console.log(err);
                    throw err;

                } else {
                    files = files.map(function(file) {
                        return {
                            filename: file,
                            longname: file,
                            attrs: { permissions: +libssh.Stat(644).reg() }
                        };
                    });
                    return message.replyNames(files);
                }
            });
        });

        channel.on('sftp:close', function (message) {
            console.log('server cmd sftp:close');
            message.replyStatus('ok');
        })
    })
});

server.listen(options.port, options.host);
console.log('Listening on port ' + options.port);

Ubuntu 14.04,nodejs 0.10.25 在 sftp.root 目录中我有测试文件,我应该可以下载到,检查它是否在 sftp 服务器上等。

当我使用 sftp(ubuntu cmd 连接到我得到的服务器)时:

sftp -P 3022 localhost
Connected to localhost.
sftp> dir
Couldn't read directory: No error
test-file  
sftp> 

服务器输出:

/usr/bin/node sftpServer.js
Listening on port 3022
server cmd sftp:realpath
server cmd sftp:opendir
server cmd sftp:readdir /home/MyFolder/uploads/
server cmd sftp:readdir /home/MyFolder/uploads/
server cmd sftp:close

无法读取目录:没有错误

但实际上是为了测试,我需要通过 lftp 使用这个服务器

lftp sftp://localhost:3022
lftp localhost:~> dir
ls: ls: Access failed:     
lftp localhost:~> 

我收到访问失败错误。我尝试创建文件夹 chmod 777 或标记为根组,但没有帮助。

我希望有人会调查它并帮助我弄清楚为什么会出现此访问错误,谢谢!

4

1 回答 1

1

最后一个replyNames 应该包含EOF 标志并且replyStatus 必须有代码SSH_FX_EOF。否则状态被视为错误。也许这段代码可以:

        if (lastmsg.type == 'readdir') {
            return message.replyStatus('eof');
        }

在 lftp 中打开调试以查看协议消息很有用,然后比较成功与不成功的会话。

于 2016-07-15T09:56:06.837 回答