paramiko-expect icon indicating copy to clipboard operation
paramiko-expect copied to clipboard

expect always fails with "EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send()" error

Open nhtha opened this issue 9 months ago • 10 comments

Dear team, expect always fails with "EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send()" error, including the demo. Please help me to fix it. I am using: Windows 11 Pro, Python 3.10 x64 to connect to Centos 7, 8, 9 machine. Best regards, Ha Nguyen

nhtha avatar May 09 '24 07:05 nhtha

Hi @nhtha, that's too little information to help you

can you provide more details, on how you connect ? with user/password ? with ssh key ? which try of key ? can you provider a code snippet ? the sshd configuration you are using on the server end ?

fruch avatar May 12 '24 05:05 fruch

Hi Fruch, I'm using the demo itself with some slighly modifications on IP, user and password. Here is the code snippet: `from future import print_function import traceback

import paramiko from paramiko_expect import SSHClientInteraction

def main(): # Set login credentials and the server prompt HOSTNAME = '192.168.254.129' USERNAME = 'nhtha' PASSWORD = '123456' # PROMPT = r'nhtha@centos8:~$\s+' PROMPT = r"[.+@.+]#|[.+@.+]$"

# Use SSH client to login
try:
    # Create a new SSH client object
    client = paramiko.SSHClient()

    # Set SSH key parameters to auto accept unknown hosts
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    # Connect to the host
    client.connect(hostname=HOSTNAME, username=USERNAME, password=PASSWORD)

    # Create a client interaction class which will interact with the host
    with SSHClientInteraction(client, timeout=10, display=False) as interact:
        interact.expect(PROMPT)

        # Run the first command and capture the cleaned output, if you want
        # the output without cleaning, simply grab current_output instead.
        interact.send('uname -a')
        interact.expect(PROMPT)
        cmd_output_uname = interact.current_output_clean

        # Now let's do the same for the ls command but also set a timeout for
        # this specific expect (overriding the default timeout)
        interact.send('ls -l /')
        interact.expect(PROMPT, timeout=5)
        cmd_output_ls = interact.current_output_clean

        # To expect multiple expressions, just use a list.  You can also
        # selectively take action based on what was matched.

        # Send the exit command and expect EOF (a closed session)
        interact.send('exit')
        interact.expect()

    # Print the output of each command
    print('-' * 79)
    print('Cleaned Command Output')
    print('-' * 79)
    print('uname -a output:')
    print(cmd_output_uname)
    print('ls -l / output:')
    print(cmd_output_ls)

except Exception:
    traceback.print_exc()
finally:
    try:
        client.close()
    except Exception:
        pass

if name == 'main': main() Here is the sshd configuration on the linux server end:# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $

This is the sshd server system-wide configuration file. See

sshd_config(5) for more information.

This sshd was compiled with PATH=/usr/local/bin:/usr/bin

The strategy used for options in the default sshd_config shipped with

OpenSSH is to specify options with their default value where

possible, but leave them commented. Uncommented options override the

default value.

If you want to change the port on a SELinux system, you have to tell

SELinux about this change.

semanage port -a -t ssh_port_t -p tcp #PORTNUMBER

#Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress ::

HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key

Ciphers and keying

#RekeyLimit default none

Logging

#SyslogFacility AUTH SyslogFacility AUTHPRIV #LogLevel INFO

Authentication:

#LoginGraceTime 2m #PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #MaxSessions 10

#PubkeyAuthentication yes

The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2

but this is overridden so installations will only check .ssh/authorized_keys

AuthorizedKeysFile .ssh/authorized_keys

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none #AuthorizedKeysCommandUser nobody

For this to work you will also need host keys in /etc/ssh/ssh_known_hosts

#HostbasedAuthentication no

Change to yes if you don't trust ~/.ssh/known_hosts for

HostbasedAuthentication

#IgnoreUserKnownHosts no

Don't read the user's ~/.rhosts and ~/.shosts files

#IgnoreRhosts yes

To disable tunneled clear text passwords, change to no here!

#PasswordAuthentication yes #PermitEmptyPasswords no PasswordAuthentication yes

Change to no to disable s/key passwords

#ChallengeResponseAuthentication yes ChallengeResponseAuthentication no

Kerberos options

#KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no #KerberosUseKuserok yes

GSSAPI options

#GSSAPIAuthentication yes GSSAPIAuthentication no GSSAPICleanupCredentials no #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no #GSSAPIEnablek5users no

Set this to 'yes' to enable PAM authentication, account processing,

and session processing. If this is enabled, PAM authentication will

be allowed through the ChallengeResponseAuthentication and

PasswordAuthentication. Depending on your PAM configuration,

PAM authentication via ChallengeResponseAuthentication may bypass

the setting of "PermitRootLogin without-password".

If you just want the PAM account and session checks to run without

PAM authentication, then enable this but set PasswordAuthentication

and ChallengeResponseAuthentication to 'no'.

WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several

problems.

UsePAM yes

#AllowAgentForwarding yes #AllowTcpForwarding yes GatewayPorts no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes PermitTTY yes #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes #UseLogin no #UsePrivilegeSeparation sandbox #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #ShowPatchLevel no #UseDNS yes UseDNS no #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none #VersionAddendum none

no default banner path

#Banner none

Accept locale-related environment variables

AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS

override default of no subsystems

Subsystem sftp /usr/libexec/openssh/sftp-server

Example of overriding settings on a per-user basis

#Match User anoncvs

X11Forwarding no

AllowTcpForwarding no

PermitTTY no

ForceCommand cvs server`

Regards, Ha Nguyen

nhtha avatar May 12 '24 13:05 nhtha

I would recommend enabling full log levels in the sshd side, to see what are the failures from its side.

Also I would note the version of open ssh being used on the server, and which paramiko version is used, I might be comptabiliy issues between them.

After that I would try a clean example of paramiko itself, and if that isn't working either, I would take the issue there.

fruch avatar May 12 '24 16:05 fruch

When enabling display, I can see that results of uname -a and ls -l command are printed out as below, looks like the send command work fine, but the expect command failed.

`Last login: Mon May 13 09:06:33 2024 from 192.168.254.1 [nhtha@centos7 ~]$ EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send() uname -a Linux centos7 3.10.0-1160.114.2.el7.x86_64 #1 SMP Wed Mar 20 15:54:52 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux [nhtha@centos7 ~]$ EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send() ls -l / total 24 lrwxrwxrwx. 1 root root 7 Jan 6 2020 bin -> usr/bin dr-xr-xr-x. 5 root root 4096 Apr 29 17:24 boot drwxr-xr-x. 21 root root 3440 May 12 19:55 dev drwxr-xr-x. 147 root root 8192 May 13 08:45 etc drwxr-xr-x. 3 root root 19 Jan 6 2020 home lrwxrwxrwx. 1 root root 7 Jan 6 2020 lib -> usr/lib lrwxrwxrwx. 1 root root 9 Jan 6 2020 lib64 -> usr/lib64 drwxr-xr-x. 2 root root 6 Apr 11 2018 media drwxr-xr-x. 3 root root 18 Apr 29 16:31 mnt drwxr-xr-x. 3 root root 16 Jan 6 2020 opt dr-xr-xr-x. 227 root root 0 May 12 19:55 proc dr-xr-x---. 9 root root 277 Apr 29 18:20 root drwxr-xr-x. 45 root root 1320 May 13 09:05 run drwxr-xr-x. 4 root sambashare 31 Apr 29 21:21 samba lrwxrwxrwx. 1 root root 8 Jan 6 2020 sbin -> usr/sbin drwxr-xr-x. 2 root root 6 Apr 11 2018 srv dr-xr-xr-x. 13 root root 0 May 12 19:55 sys drwxrwxrwt. 28 root root 4096 May 13 09:05 tmp drwxr-xr-x. 13 root root 155 Jan 6 2020 usr drwxr-xr-x. 22 root root 4096 Apr 29 21:40 var [nhtha@centos7 ~]$ EXCESS TIME RECV_READY TIMEOUT, did you expect() before a send() exit logout

Cleaned Command Output

uname -a output:

ls -l / output:`

I also enable the sshd debug log. Which log/file do I need to collect and send to this thread? Regards, Ha Nguyen

nhtha avatar May 13 '24 02:05 nhtha

I'm using: paramiko version 3.2.0, paramiko-expect version 0.3.5, OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017. Regards, Ha Nguyen

nhtha avatar May 13 '24 02:05 nhtha

A strange is : self.channel.recv_ready() is always False. Regards, Ha Nguyen

nhtha avatar May 13 '24 02:05 nhtha

I also tried with paramiko 3.4.0, the problem still happened in this version. Regards, Ha Nguyen

nhtha avatar May 13 '24 03:05 nhtha

The same error happened with Centos8 and Centos9 target host. Regards, Ha Nguyen

nhtha avatar May 13 '24 03:05 nhtha

I also tried with paramiko version 2.12.0, the result is the same. Regards, Ha Nguyen

nhtha avatar May 13 '24 03:05 nhtha

For anyone having the same issue,

the paramiko using re.match to search for expect pattern

re.match(default_match_prefix + re_string + '$',
self.current_output, re.DOTALL)

default_match_prefix is .*\n but you can try change it to ^.*\n to match the pattern if it not from start of string

nhuongmh avatar Oct 08 '24 11:10 nhuongmh