java sockets ssh sftp deadlock

java - Identificación del servidor SSH nunca recibida-Interbloqueo de Handshake



sockets sftp (1)

Apuesto a que el siguiente código crea un problema:

String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString(); if (ident.isEmpty()) { return ident; }

Si IdentificationStringParser.parseIdentificationString () devuelve una cadena vacía, se devolverá al método de la persona que llama. El método de llamada seguirá llamando al while ((serverID = readIdentification(buf)).isEmpty()) ya que la cadena siempre está vacía. La única forma de romper el bucle sería llamar a int b = connInfo.in.read(); devuelve -1 ... pero si el servidor sigue enviando los datos (o reenviando los datos) esta condición nunca se cumple.

Si este es el caso, agregaría algún tipo de forma artificial para detectar esto como:

private String readIdentification(Buffer.PlainBuffer buffer, AtomicInteger numberOfAttempts) throws IOException { String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString(); numberOfAttempts.incrementAndGet(); if (ident.isEmpty() && numberOfAttempts.intValue() < 1000) { // 1000 return ident; } else if (numberOfAttempts.intValue() >= 1000) { throw new TransportException("To many attempts to read the server ident"). } if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-")) throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED, "Server does not support SSHv2, identified as: " + ident); return ident; }

De esta forma, al menos confirmaría que este es el caso y podrá seguir investigando por qué .parseIdentificationString () devuelve una cadena vacía.

Estamos teniendo problemas para tratar de implementar un conjunto de SftpConnections para nuestra aplicación.

Actualmente estamos utilizando SSHJ (Schmizz) como la biblioteca de transporte, y enfrentando un problema que simplemente no podemos simular en nuestro entorno de desarrollo (pero el error sigue apareciendo aleatoriamente en producción, a veces después de tres días, a veces después de solo 10 minutos).

El problema es que al intentar enviar un archivo a través de SFTP, el hilo se bloquea en el método init de la clase schmizz '' TransportImpl :

@Override public void init(String remoteHost, int remotePort, InputStream in, OutputStream out) throws TransportException { connInfo = new ConnInfo(remoteHost, remotePort, in, out); try { if (config.isWaitForServerIdentBeforeSendingClientIdent()) { receiveServerIdent(); sendClientIdent(); } else { sendClientIdent(); receiveServerIdent(); } log.info("Server identity string: {}", serverID); } catch (IOException e) { throw new TransportException(e); } reader.start(); }

isWaitForServerIdentBeforeSendingClientIdent es FALSO para nosotros, por lo tanto, antes que nada, el cliente (nosotros) enviaremos nuestra identificación, tal como aparece en los registros:

" Cadena de identidad del cliente: blabla "

Luego le toca a receiveServerIdent :

private void receiveServerIdent() throws IOException { final Buffer.PlainBuffer buf = new Buffer.PlainBuffer(); while ((serverID = readIdentification(buf)).isEmpty()) { int b = connInfo.in.read(); if (b == -1) throw new TransportException("Server closed connection during identification exchange"); buf.putByte((byte) b); } }

El hilo nunca recupera el control, ya que el servidor nunca responde con su identidad. Parece que el código está atascado en este ciclo While. No se producen tiempos de espera o excepciones de SSH, mi cliente simplemente espera para siempre y el hilo se estanca.

Esta es la readIdentification método de readIdentification :

private String readIdentification(Buffer.PlainBuffer buffer) throws IOException { String ident = new IdentificationStringParser(buffer, loggerFactory).parseIdentificationString(); if (ident.isEmpty()) { return ident; } if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-")) throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED, "Server does not support SSHv2, identified as: " + ident); return ident; }

Parece que inputstream de ConnectionInfo nunca obtiene datos para leer, como si el servidor cerrara la conexión (incluso si, como se dijo antes, no se lanza ninguna excepción).

Intenté simular este error saturando la negociación, cerrando los sockets durante la conexión, usando conntrack para eliminar las conexiones establecidas mientras se realiza el handshake, pero sin suerte en absoluto, por lo que cualquier ayuda sería ALTAMENTE apreciada.

:)