开发者

Java SSH Tools: SftpClient error: The remote computer disconnected: Protocol error: packet too long: 65580

I am receiving "INFO: The remote computer disconnected: Protocol error: packet too long: 65580" error, when I trying to execute:

sUpload("server.host.com", "username", "/home/localuser/.ssh/id_rsa", "filename", "");

The file does not get transferred to SFTP server (only zero-byte gets created on the other side). When SFTPing manually via Unix shell, everything is working fine. I read online that it may be a problem with BLOCK_SIZE in SftpClient, but first I could not find a setter method to alter the size and second, it appears that default value is 65535 anyway, which totally does not explain the 65580 value from the error message.

Any ideas?

I have the following utility method that uses Java Ssh Tools (j2ssh-core-0开发者_如何学Go.2.9.jar):

private static void sUpload(String ftpServer, String user, String password,
String localFile, String remoteFile) throws IOException {
    String methodName = "sUpload: ";
    System.out.println(" START ftpServer="+ftpServer+" user="+user+" password="+password);

    int result = 0;
    System.out.println("ftpServer " + ftpServer);
    System.out.println("user  " + user);
    System.out.println("password  " + password);
    System.out.println("localFile " + localFile);
    System.out.println("remoteFile    " + remoteFile);

    SshClient ssh = new SshClient();

    ssh.connect(ftpServer);

    System.out.println("Server Connected  ");
    if (password.contains("\\") || password.contains("/")) {

        PublicKeyAuthenticationClient pk = 
            new PublicKeyAuthenticationClient();

        pk.setUsername(user);
        // Open up the private key file
        SshPrivateKeyFile file = SshPrivateKeyFile
                .parse(new File(password));
        SshPrivateKey key = file.toPrivateKey(null);
        pk.setKeyfile(password);
        pk.setKey(key);
        // Try the authentication
        result = ssh.authenticate(pk);

    } else {

        // Create a password authentication instance
        PasswordAuthenticationClient pwd = 
            new PasswordAuthenticationClient();
        // Get the users name
        pwd.setUsername(user);
        // Get the password
        pwd.setPassword(password);

        // Try the authentication
        result = ssh.authenticate(pwd);
    }

    System.out.println("Result fromssh.authenticate(pwd) " + result);
    // Evaluate the result
    if (result == AuthenticationProtocolState.COMPLETE) {

        // The connection is authenticated we can now do some real work!
        SftpClient sftp = ssh.openSftpClient();       
        System.out.println("openSftpClient");
        // Upload a file
        if(remoteFile != null && remoteFile.trim().length() > 0){
            sftp.put(localFile, remoteFile);
            System.out.println("======== no remote ======================================== file transfer success =======================================================================");
        }
        else    {
            System.out.println("================================================ file transfer starting =======================================================================");
            sftp.put(localFile);
            System.out.println("================================================ file transfer success =======================================================================");
        }


        // Quit
        sftp.quit();
        ssh.disconnect();
    }
    System.out.println(" END ");
}


The ssh client should tell the server what the desired max packet size is and the server should comply according to the specs.

Try against a different server and check the configuration of max packet size of your own server.


Looks like the following code works - I used lower level "com.sshtools.j2ssh.sftp.SftpSubsystemClient" instead of "com.sshtools.j2ssh.SftpClient" and reading/writing files using input/output streams:

    System.out.println("Result fromssh.authenticate(pwd) " + result);
    // Evaluate the result
    if (result == AuthenticationProtocolState.COMPLETE) {
        SftpSubsystemClient sftpSubsystemClient = ssh.openSftpChannel();
        com.sshtools.j2ssh.connection.Channel sftpChannel = sftpSubsystemClient;
        System.out.println("Local packet size: " + sftpChannel.getLocalPacketSize());
        System.out.println("Remote packet size: " + sftpChannel.getRemotePacketSize());

        SftpFile file = sftpSubsystemClient.openFile(remoteFile, SftpSubsystemClient.OPEN_CREATE | SftpSubsystemClient.OPEN_WRITE);

        FileAttributes attrs = file.getAttributes();
        attrs.setPermissions("rwxrwxrwx");
        sftpSubsystemClient.setAttributes(file, attrs);

        final int bufferSize = 4096;
        System.out.println("Creating buffered streams");
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(localFile), bufferSize);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new SftpFileOutputStream(file)));

        int c;            
        while ((c = in.read()) != -1) {
            out.write(c);
        }
        System.out.println("Done writing streams");
        out.close();
        in.close();
        sftpSubsystemClient.close();            
        ssh.disconnect();
    }
    System.out.println(" END ");

What's really interesting is that I am outputting remote and local packet sizes just for fun, and they are both equal to 65535. It really seems that this 65580 message is a bug in SSH server or SSH tools.


You cannot change BLOCKSIZE. There are several places that block size is mentioned. All of them are either using a fixed value for some read or write buffer, or are calling getBlockSize() on a Cipher object, which is part of the JVM crypto subsystem.

I'm not able to reproduce the error you're seeing. SI tried with several differently sized files including one of the exact size you mentioned. Something like this is very susceptible to the client and server settings.

My gut instinct is that there is a bug in the j2ssh library relating to cipher block sizes which is creating a larger than allowed block by not taking into account a packet header somewhere. I suggest fiddling with the settings to see if you can force the client to use a different cipher. It might also be helpful to download the j2ssh source and try to debug into the problem directly. Determine whether the error is happening on the first, last or some middle packet.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜