Apache MINA SSHD使用ProcessShellFactory时会将会话字符回显两次,控制字符无效。

3

我在macOS 10.15.7上运行OpenJDK 14。我正在进行一些概念验证代码,用Apache Mina SSHD建立一个SSH服务器,然后连接到它。以下是我的代码:

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;

import org.apache.sshd.common.cipher.BuiltinCiphers;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;
import org.apache.sshd.server.ServerBuilder;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.AsyncAuthException;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellFactory;

public class FunctionalTest
{
    private static class TestAuthenticator
        extends AbstractLoggingBean
        implements PasswordAuthenticator
    {
        @Override
        public boolean authenticate(String username, String password, ServerSession session)
            throws PasswordChangeRequiredException, AsyncAuthException
        {
            if ("test".equals(username) && "foobar".equals(password))
            {
                this.log.info("authenticate({}[{}]: accepted", username, session);
                return true;
            }

            this.log.warn("authenticate({}[{}]: rejected", username, session);
            return false;
        }
    }

    public static void main(String... args) throws IOException
    {
        SshServer sshd = SshServer.setUpDefaultServer();
        sshd.setHost("0.0.0.0");
        sshd.setPort(1022);
        sshd.setShellFactory(InteractiveProcessShellFactory.INSTANCE);
        sshd.setPasswordAuthenticator(new TestAuthenticator());
        sshd.setCipherFactories(Arrays.asList(BuiltinCiphers.aes256ctr, BuiltinCiphers.aes192ctr));
        sshd.setKeyExchangeFactories(ServerBuilder.setUpDefaultKeyExchanges(false));
        sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("key.ser")));
        sshd.start();

        try
        {
            Thread.sleep(3_600_000);
        }
        catch(InterruptedException e)
        {
            System.out.println("Caught interrupt ... stopping server.");
            sshd.stop(true);
        }
    }
}

当我启动这个程序后,可以使用密码foobar通过ssh -p 1022 test@localhost进行认证,并且可以正常工作。在成功认证后,我首先看到这个:
sh: no job control in this shell

那么在提示符处,我输入的字符(包括换行符)会被重复两次回显,导致所有东西都被复制一遍:

williamsn:mina-test williamsn$ llss  --aall

total 24
... (list of files)
williamsn:mina-test williamsn$ eecchhoo  hheelllloo
hello

williamsn:mina-test williamsn$

此外,如果我运行像top这样的交互式命令,它不会识别我的输入,控制字符也无法工作。虽然ttoopp启动了(但其输出是丑陋的,并且会累加到屏幕上而不是替换之前的内容),但如果我键入q退出(此时q不会被回显两次),top不会响应q退出。它只会继续运行。ctrl+c也无法工作——top只会继续运行。唯一退出top的方法是杀死我的ssh进程或关闭MINA服务器。
我觉得我在这里一定做错了什么,请问您有何想法?
1个回答

0

“无作业控制”消息表示生成的 shell 不处于完全交互模式下,并且双字母显示您在本地和远程字符回显之间存在不匹配。

我只能假设 mac-os 上的默认 shell (/usr/bin/sh) 不像 Linux 上那样是 bash 实现。尝试将 shell 工厂更改为 new ProcessShellFactory("/usr/bin/bash","-i")

很抱歉我没有 mac 可以尝试这个。

保罗


谢谢,保罗!实际上我先尝试了Bash,然后再尝试使用sh,结果行为完全相同,只是措辞不同:我使用了sshd.setShellFactory(new ProcessShellFactory("bash", "/usr/local/bin/bash", "-i"));(请注意,ProcessShellFactory文档已经过时,现在需要新的第一个参数),输出如下面的评论所示: - Nick Williams
密码认证 [\n] 密码:[\n] bash: 无法设置终端进程组 (67423):设备不支持的 ioctl 操作 [\n] bash: 此 shell 中没有作业控制 [\n] bash-5.0$ - Nick Williams
遇到完全相同的问题。有更新吗?@Nick。在CentOS上也尝试了,一样。 - Lance Mao
不幸的是,没有运气。而且邮件列表上也从来没有人回复,所以我放弃了。 - Nick Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接