Telnet 命令进入(通过,内部)SSH 会话

Posted

技术标签:

【中文标题】Telnet 命令进入(通过,内部)SSH 会话【英文标题】:Telnet commands into (through, inside) SSH session 【发布时间】:2021-11-20 09:58:25 【问题描述】:

我有一个任务: 通过 ssh 会话执行 telnet 命令。

我看过类似的问题:

    Running telnet command on remote SSH session using JSch telnet through SSH Execution hangs after Running telnet command on remote SSH session using JSch

我编写了代码(使用 lib https://mvnrepository.com/artifact/com.jcraft/jsch):

    类 SSH:

    公共类 SSH 私有最终字符串用户; 私人最终字符串密码; 私有最终字符串主机;

     public Ssh(String user, String password, String host) 
         this.USER = user;
         this.PASSWORD = password;
         this.HOST = host;
     
    
     public Session runSsh() 
         try 
             Session session = new JSch().getSession(USER, HOST, 22);
             session.setPassword(PASSWORD);
             // It must not be recommended, but if you want to skip host-key check,
             session.setConfig("StrictHostKeyChecking", "no");
             session.connect(3000);
             return session;
          catch (JSchException e) 
             System.out.println(e);
         
         return null;
     
    

    类 Telnet

    公共类 Telnet

     public String runCommand(Session session, String command) throws Exception 
         Channel channel = session.openChannel("shell");
         channel.connect(3000);
    
         DataOutputStream outputStream = new DataOutputStream(channel.getOutputStream());
    
         outputStream.writeBytes("telnet localhost 5000\r\n");
         outputStream.writeBytes(command + "\r\n");
         outputStream.writeBytes("exit\r\n");
         outputStream.flush();
    
         DataInputStream inputStream = new DataInputStream(channel.getInputStream());
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    
         channel.setInputStream(inputStream, true);
    
         String line = reader.readLine();
         String result = line +"\n";
         while (!(line= reader.readLine()).equals("exit"))
             result += line +"\n";
         
         result += "Connection closed by foreign host";
    
         outputStream.close();
         inputStream.close();
         channel.disconnect();
         session.disconnect();
    
         return result;
     
    

    类主

    公共类主

     public static void main(String[] arg) 
         Ssh ssh = new Ssh("user","password","ip-server");
         Telnet telnet = new Telnet();
         try 
             Session sessionSsh = ssh.runSsh();
             String result = telnet.runCommand(sessionSsh, "H");
             System.out.println(result);
          catch (Exception e) 
             e.printStackTrace();
         
     
    

我得到了结果:

telnet localhost 5000


Entering character mode

Escape character is '^]'.




 Command Shell 1 on intelpc-1 (Port: 5000)

 b01_1_1 (5000) >
H

Connection closed by foreign host

Process finished with exit code 0

我没有看到执行命令 telnet 的结果...

我通过 telnet 发出了不同的命令:

- H
or
- u s3

但我看不到他们的结果:(

请告诉我。如何获取 telnet 命令执行的结果?

【问题讨论】:

【参考方案1】:

我调试了您的示例,就我而言,我需要等待您通过 telnet 连接的程序,直到它准备好接收命令。

在第二步中,您可以发送命令和退出命令来停止远程登录,因此您可以从流中读取,直到通过说“连接关闭...”停止。请注意,从 telnet 退出可以有不同的命令,有些使用 quit,有些使用 exit 或只等待终止信号。

 class Telnet 

        public String runCommand(Session session, String command) throws Exception 
            Channel channel = session.openChannel("shell");
            channel.connect(3000);

            DataOutputStream outputStream = new DataOutputStream(channel.getOutputStream());

            outputStream.writeBytes("telnet localhost 16379\r\n");
            outputStream.flush();

            DataInputStream inputStream = new DataInputStream(channel.getInputStream());
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

            channel.setInputStream(inputStream, true);

            // Read until we are ready to write
            String line;
            while (!(line= reader.readLine()).equals("Escape character is '^]'."))
                System.out.println(line);
            

            // write command and exit telnet
            outputStream.writeBytes(command + "\r\n");
            outputStream.writeBytes("quit\r\n");
            outputStream.flush();

            // read until telnet has closed
            String result = "";
            while (!(line= reader.readLine()).equals("Connection closed by foreign host."))
                result += line +"\n";
            

            outputStream.close();
            inputStream.close();
            channel.disconnect();
            session.disconnect();

            return result;
        
    

最后,还有其他无需 telnet 的通信方式,即本地端口转发。

【讨论】:

感谢您的回复。我使用了你的代码,但没有得到结果(你还写了:最后,还有其他方法可以不用telnet进行通信,即本地端口转发。非常感谢。我开始使用ssh隧道:ssh Session。 setPortForwardingL(9999, ssh Session.getHost(), 5000); 如果先创建ssh隧道,然后telnet命令给出结果。我稍后会详细写我的结果。【参考方案2】:

感谢马蒂亚斯·维德曼。

按照 Matthias Wiedemann 的建议,我使用了 SSH 隧道 https://www.ssh.com/academy/ssh/tunneling/example。

总计:

1 步。通过 SSH 连接并创建会话 SSH

SSH ssh = new SSH(user, password, host, port);
Session session = SSHUtil.createSession(ssh);

2 步。使用 SSH 创建隧道

SSHUtil.createChannel(session, outputConsole);
SSHUtil.createSshTunnel(session, port);

3 步。通过 Telnet 连接并使用隧道端口(而不是 5000,端口变为 9999)执行 Telnet 命令。

clientForTelnet = new ClientForTelnet(new Telnet(host, port));
outputConsole.print(TelnetUtil.connect(clientForTelnet));

outputConsole 是 PrintStream。

我得到了以下信息:

1.

public class SSHUtil

    private final static Logger LOGGER = LogManager.getLogger(SSHUtil.class);

    public static Session createSession(SSH ssh) 
        Session session = null;
        try 
            session = new JSch().getSession(ssh.getUSER(), ssh.getHOST().getIp(), ssh.getPORT().getPort());
            session.setPassword(ssh.getPASSWORD());
            session.setConfig("StrictHostKeyChecking", "no"); // It must not be recommended, but if you want to skip host-key check
            session.connect(10000);
            LOGGER.info("SSH session created");
         catch (JSchException e) 
            LOGGER.error("SSH session not created " + e);
        
        return session;
    

    public static Channel createChannel(Session session, PrintStream output) 
        Channel channel = null;
        try 
            channel = session.openChannel("shell");
            channel.setInputStream(System.in);
            channel.setOutputStream(output);
            //  streamOut = channel.getOutputStream();

            channel.connect(10000);
            LOGGER.info("SSH channel created");
         catch (JSchException e) 
            LOGGER.error("SSH channel not created " + e);
        
        return channel;
    

    public static void createSshTunnel(Session session, Port port) 
        // TODO сделать пул портов, чтобы исключить вероятность, что порт 9999 занят
        try 
            session.setPortForwardingL(9999, session.getHost(), port.getPort());
            LOGGER.info("Tunnel created localhost:" + 9999 + " -> " + session.getHost() + ":" + port.getPort());
         catch (JSchException e) 
            LOGGER.error("SSH tunnel not created " + e);
        
    

    public static void disconnect(Session session) 
        if (session != null && session.isConnected()) 
            session.disconnect();
        
    


    公共类 TelnetUtil
    private final static Logger LOGGER = LogManager.getLogger(TelnetUtil.class);

    public static String connect(ClientForTelnet clientForTelnet) 
        try 
            // Connect to the server
            clientForTelnet.getTc().connect(clientForTelnet.getTelnet().getHOST().getIp(), clientForTelnet.getTelnet().getPORT().getPort());

            // Get input and output stream references
            clientForTelnet.setIn(clientForTelnet.getTc().getInputStream());
            clientForTelnet.setOut(new PrintStream(clientForTelnet.getTc().getOutputStream()));
         catch (IOException e) 
            LOGGER.error(e);
        

        return readUntil(clientForTelnet.getPrompt(), clientForTelnet.getIn());
    

    public static String readUntil(String pattern, InputStream in) 
        StringBuilder sb = new StringBuilder();
        try 
            char lastChar = pattern.charAt(pattern.length() - 1);
            boolean found = false;
            char ch = (char) in.read();
            while (true) 
           //     System.out.print(ch);
                sb.append(ch);
                if (ch == lastChar) 
                    if (sb.toString().endsWith(pattern)) 
                        return sb.toString();
                    
                
                ch = (char) in.read();
            
         catch (IOException e) 
            LOGGER.error(e);
        
        return sb.toString();
    

    public static void write(String value, PrintStream out) 
        out.println(value);
        out.flush();
    

    public static String sendCommand(ClientForTelnet clientForTelnet, String command) 
        write(command, clientForTelnet.getOut());
        return readUntil(clientForTelnet.getPrompt(), clientForTelnet.getIn());
    

    public static void disconnect(TelnetClient tc) 
        try 
            tc.disconnect();
         catch (IOException e) 
            LOGGER.error(e);
        
    


    公共类 SSH 私有最终字符串用户; 私人最终字符串密码; 私有最终主机 HOST; 私有最终端口 PORT;

      private final Port DEFAULT_PORT = new Port(22);
    
      public SSH(String user, String password, Host host, Port port) 
          this.USER = user;
          this.PASSWORD = password;
          this.HOST = host;
          this.PORT = port;
      
    
      public SSH(String user, String password, Host host) 
          this.USER = user;
          this.PASSWORD = password;
          this.HOST = host;
          this.PORT = DEFAULT_PORT;
      
    
      public String getUSER() 
          return USER;
      
    
      public String getPASSWORD() 
          return PASSWORD;
      
    
      public Host getHOST() 
          return HOST;
      
    
      public Port getPORT() 
          return PORT;
      
    

    公共类 Telnet

      private final Host HOST;
      private final Port PORT;
    
      private final Port DEFAULT_PORT = new Port(5000);
    
      public Telnet(Host host, Port port) 
          this.HOST = host;
          this.PORT = port;
      
    
      public Telnet(Host host) 
          this.HOST = host;
          this.PORT = DEFAULT_PORT;
      
    
      public Host getHOST() 
          return HOST;
      
    
      public Port getPORT() 
          return PORT;
      
    

    公共类 ClientForTelnet

      private final TelnetClient TC = new TelnetClient();
      private final String PROMT = ">";
      private final Telnet TELNET;
    
      private InputStream in;
      private PrintStream out;
    
      public ClientForTelnet(Telnet telnet) 
          this.TELNET = telnet;
      
    
      public InputStream getIn() 
          return in;
      
    
      public PrintStream getOut() 
          return out;
      
    
      public Telnet getTelnet() 
          return TELNET;
      
    
      public String getPrompt() 
          return PROMT;
      
    
      public TelnetClient getTc() 
          return TC;
      
    
      public void setIn(InputStream in) 
          this.in = in;
      
    
      public void setOut(PrintStream out) 
          this.out = out;
      
    

public class Host 

    private final static Logger LOGGER = LogManager.getLogger(Host.class);

    private String ip;

    public Host(String ip) 
        this.ip = ip;
    

    public String getIp() 
        return ip;
    


【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于Telnet 命令进入(通过,内部)SSH 会话的主要内容,如果未能解决你的问题,请参考以下文章

当我将任何命令通过管道传输到 telnet 会话时会发生啥,为啥会话会关闭

在windows环境下通过帐号密码SSH登录堡垒机,之后telnet到网络设备,通过命令交互对设备

什么命令将阻止使用Telnet,只允许使用SSH远程登陆路由器。

Telnet使用

telnet不是内部或外部命令怎么办

HTML5 Access:基于H5的远程桌面及Telnet/SSH接入方案