Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paramiko cannot connect to tamte server #2161

Open
thisismygitrepo opened this issue Dec 31, 2022 · 19 comments
Open

Paramiko cannot connect to tamte server #2161

thisismygitrepo opened this issue Dec 31, 2022 · 19 comments

Comments

@thisismygitrepo
Copy link

I'm trying to ssh to Tmate, a popular terminal sharing server.
Via ssh, the process is easy:
ssh {user_name}/{sess_name}@sgp1.tmate.io

But Paramiko doesn't seem to be able to do that.
I get those types of errors:

IncompatiblePeer: Incompatible ssh server (no acceptable compression) [] [] ('none',)

or 

SSHException: Error reading SSH protocol banner

Is this possible at all?
What is missing here?

@jun66j5
Copy link
Contributor

jun66j5 commented Dec 31, 2022

That's an issue of tmate server settings. Please ask on https://groups.google.com/group/tmate-io.

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

It seems your tmate server requires compression in ssh connection by the settings. I think the settings typically should be configured to accept both with/without compression, however if you couldn't change the settings, try to pass compress=True to SSHClient.connect().

@thisismygitrepo
Copy link
Author

@jun66j5

It worked, now ssh.connect no longer throws an error. But when I executed a command I get this error:

----> 1 ssh.exec_command("ls")

File ~\venvs\ve\lib\site-packages\paramiko\client.py:525, in SSHClient.exec_command(self, command, bufsize, timeout, get_pty, environment)
    485 def exec_command(
    486     self,
    487     command,
   (...)
    491     environment=None,
    492 ):
    493     """
    494     Execute a command on the SSH server.  A new `.Channel` is opened and
    495     the requested command is executed.  The command's input and output
   (...)
    523         Added the ``get_pty`` kwarg.
    524     """
--> 525     chan = self._transport.open_session(timeout=timeout)
    526     if get_pty:
    527         chan.get_pty()

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:920, in Transport.open_session(self, window_size, max_packet_size, timeout)
    892 def open_session(
    893     self, window_size=None, max_packet_size=None, timeout=None
    894 ):
    895     """
    896     Request a new channel to the server, of type ``"session"``.  This is
    897     just an alias for calling `open_channel` with an argument of
   (...)
    918         Added the ``window_size`` and ``max_packet_size`` arguments.
    919     """
--> 920     return self.open_channel(
    921         "session",
    922         window_size=window_size,
    923         max_packet_size=max_packet_size,
    924         timeout=timeout,
    925     )

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:1014, in Transport.open_channel(self, kind, dest_addr, src_addr, window_size, max_packet_size, timeout)
    978 """
    979 Request a new channel to the server. `Channels <.Channel>` are
    980 socket-like objects used for the actual transfer of data across the
   (...)
   1011     Added the ``window_size`` and ``max_packet_size`` arguments.
   1012 """
   1013 if not self.active:
-> 1014     raise SSHException("SSH session not active")
   1015 timeout = 3600 if timeout is None else timeout
   1016 self.lock.acquire()

SSHException: SSH session not active

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

Your script has something wrong. The transport in the ssh instance is already closed. Please provide entire of scripts which you've tried.

@thisismygitrepo
Copy link
Author

thisismygitrepo commented Jan 8, 2023

Full script as requested:

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect(username="**", hostname="sgp1.tmate.io", compress=True)
print("Connected Succesfully.")

ssh.exec_command("ls")
print("Finished executing first command")

ssh.exec_command("ls")
print("Finished executing second command")

Execution results

 (...)
    918         Added the ``window_size`` and ``max_packet_size`` arguments.
    919     """
--> 920     return self.open_channel(
    921         "session",
    922         window_size=window_size,
    923         max_packet_size=max_packet_size,
    924         timeout=timeout,
    925     )

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:1014, in Transport.open_channel(self, kind, dest_addr, src_addr, window_size, max_packet_size, timeout)
    978 """
    979 Request a new channel to the server. `Channels <.Channel>` are
    980 socket-like objects used for the actual transfer of data across the
   (...)
   1011     Added the ``window_size`` and ``max_packet_size`` arguments.
   1012 """
   1013 if not self.active:
-> 1014     raise SSHException("SSH session not active")
   1015 timeout = 3600 if timeout is None else timeout
   1016 self.lock.acquire()

SSHException: SSH session not active

The first execution returns stdin, stdout, stderr like this:

(<paramiko.ChannelFile from <paramiko.Channel 0 (closed) -> <paramiko.Transport at 0x4297aa60 (unconnected)>>>,
 <paramiko.ChannelFile from <paramiko.Channel 0 (closed) -> <paramiko.Transport at 0x4297aa60 (unconnected)>>>,
 <paramiko.ChannelFile from <paramiko.Channel 0 (closed) -> <paramiko.Transport at 0x4297aa60 (unconnected)>>>)

In stdout, I see: 'Invalid command\r\n'

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

That is not a paramiko issue.

I think it is unable to send any commands to tmate server. The ssh connection to tmate server is used only for terminal sharing.

I have no idea about what you want to do with paramiko. Please ask on tmate forum.

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

I guess that tmake server responds Invalid command for your exec_command and disconnects. If you want to investigate it, add paramiko.util.log_to_file('paramiko.log') at next line of import paramiko and check logged paramiko.log file.

@thisismygitrepo
Copy link
Author

thisismygitrepo commented Jan 8, 2023

What I need to achieve with tmate is SSHing over internet, not just local network. I'm not using it for file transfer.

Here is the logfile for the same script.


DEB [20230108-17:57:41.412] thr=1   paramiko.transport: starting thread (client mode): 0x40455ac0
DEB [20230108-17:57:41.412] thr=1   paramiko.transport: Local version/idstring: SSH-2.0-paramiko_2.12.0
DEB [20230108-17:57:41.491] thr=1   paramiko.transport: Remote version/idstring: SSH-2.0-tmate
INF [20230108-17:57:41.491] thr=1   paramiko.transport: Connected (version 2.0, client tmate)
DEB [20230108-17:57:41.504] thr=1   paramiko.transport: === Key exchange possibilities ===
DEB [20230108-17:57:41.504] thr=1   paramiko.transport: kex algos: curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group18-sha512, diffie-hellman-group16-sha512, diffie-hellman-group-exchange-sha256, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: server key: rsa-sha2-512, rsa-sha2-256, ssh-rsa
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: client encrypt: aes256-gcm@openssh.com, aes128-gcm@openssh.com, aes256-ctr, aes192-ctr, aes128-ctr, aes256-cbc, aes192-cbc, aes128-cbc, 3des-cbc
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: server encrypt: aes256-gcm@openssh.com, aes128-gcm@openssh.com, aes256-ctr, aes192-ctr, aes128-ctr, aes256-cbc, aes192-cbc, aes128-cbc, 3des-cbc
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: client mac: hmac-sha2-256-etm@openssh.com, hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, hmac-sha2-256, hmac-sha2-512, hmac-sha1
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: server mac: hmac-sha2-256-etm@openssh.com, hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, hmac-sha2-256, hmac-sha2-512, hmac-sha1
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: client compress: zlib@openssh.com, zlib
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: server compress: zlib@openssh.com, zlib
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: client lang: <none>
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: server lang: <none>
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: kex follows: False
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: === Key exchange agreements ===
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: Kex: curve25519-sha256@libssh.org
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: HostKey: rsa-sha2-512
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: Cipher: aes128-ctr
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: MAC: hmac-sha2-256
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: Compression: zlib@openssh.com
DEB [20230108-17:57:41.507] thr=1   paramiko.transport: === End of kex handshake ===
DEB [20230108-17:57:41.698] thr=1   paramiko.transport: kex engine KexCurve25519 specified hash_algo <built-in function openssl_sha256>
DEB [20230108-17:57:41.698] thr=1   paramiko.transport: Switch to new keys ...
DEB [20230108-17:57:41.698] thr=2   paramiko.transport: Adding ssh-rsa host key for sgp1.tmate.io: b'***'
DEB [20230108-17:57:41.788] thr=1   paramiko.transport: Got EXT_INFO: {'server-sig-algs': b'ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256,ssh-rsa,ssh-dss'}
DEB [20230108-17:57:42.127] thr=2   paramiko.transport: Trying discovered key b'**' in C:\Users\alex/.ssh/id_rsa
DEB [20230108-17:57:42.229] thr=1   paramiko.transport: userauth is OK
DEB [20230108-17:57:42.229] thr=1   paramiko.transport: Finalizing pubkey algorithm for key of type 'ssh-rsa'
DEB [20230108-17:57:42.229] thr=1   paramiko.transport: Our pubkey algorithm list: ['rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa']
DEB [20230108-17:57:42.229] thr=1   paramiko.transport: Server-side algorithm list: ['ssh-ed25519-cert-v01@openssh.com', 'ecdsa-sha2-nistp521-cert-v01@openssh.com', 'ecdsa-sha2-nistp384-cert-v01@openssh.com', 'ecdsa-sha2-nistp256-cert-v01@openssh.com', 'rsa-sha2-512-cert-v01@openssh.com', 'rsa-sha2-256-cert-v01@openssh.com', 'ssh-rsa-cert-v01@openssh.com', 'ssh-dss-cert-v01@openssh.com', 'ssh-ed25519', 'ecdsa-sha2-nistp521', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp256', 'rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa', 'ssh-dss']
DEB [20230108-17:57:42.229] thr=1   paramiko.transport: Agreed upon 'rsa-sha2-512' pubkey algorithm
INF [20230108-17:57:42.336] thr=1   paramiko.transport: Authentication (publickey) failed.
DEB [20230108-17:57:42.351] thr=2   paramiko.transport: Trying discovered key b'**' in C:\Users\alex/.ssh/id_ed25519
DEB [20230108-17:57:42.434] thr=1   paramiko.transport: userauth is OK
INF [20230108-17:57:42.542] thr=1   paramiko.transport: Authentication (publickey) successful!
DEB [20230108-17:57:42.542] thr=1   paramiko.transport: Switching on outbound compression ...
DEB [20230108-17:57:42.542] thr=1   paramiko.transport: Switching on inbound compression ...
DEB [20230108-17:57:42.557] thr=2   paramiko.transport: [chan 0] Max packet in: 32768 bytes
DEB [20230108-17:57:42.637] thr=1   paramiko.transport: [chan 0] Max packet out: 35000 bytes
DEB [20230108-17:57:42.637] thr=1   paramiko.transport: Secsh channel 0 opened.
DEB [20230108-17:57:42.733] thr=1   paramiko.transport: [chan 0] Sesch channel 0 request ok
DEB [20230108-17:57:42.733] thr=2   paramiko.transport: [chan 0] EOF sent (0)
DEB [20230108-17:57:42.733] thr=2   paramiko.transport: [chan 1] Max packet in: 32768 bytes
DEB [20230108-17:57:42.748] thr=1   paramiko.transport: [chan 0] EOF received (0)
DEB [20230108-17:57:42.748] thr=1   paramiko.transport: EOF in transport thread

@thisismygitrepo
Copy link
Author

I'm receiving different error now, instead of cosed connection, I get EOF error:

Connected Succesfully.
Finished executing first command
---------------------------------------------------------------------------
EOFError                                  Traceback (most recent call last)
Cell In[23], line 13
     10 ssh.exec_command("ls")
     11 print("Finished executing first command")
---> 13 ssh.exec_command("ls")
     14 print("Finished executing second command")

File ~\venvs\ve\lib\site-packages\paramiko\client.py:525, in SSHClient.exec_command(self, command, bufsize, timeout, get_pty, environment)
    485 def exec_command(
    486     self,
    487     command,
   (...)
    491     environment=None,
    492 ):
    493     """
    494     Execute a command on the SSH server.  A new `.Channel` is opened and
    495     the requested command is executed.  The command's input and output
   (...)
    523         Added the ``get_pty`` kwarg.
    524     """
--> 525     chan = self._transport.open_session(timeout=timeout)
    526     if get_pty:
    527         chan.get_pty()

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:920, in Transport.open_session(self, window_size, max_packet_size, timeout)
    892 def open_session(
    893     self, window_size=None, max_packet_size=None, timeout=None
    894 ):
    895     """
    896     Request a new channel to the server, of type ``"session"``.  This is
    897     just an alias for calling `open_channel` with an argument of
   (...)
    918         Added the ``window_size`` and ``max_packet_size`` arguments.
    919     """
--> 920     return self.open_channel(
    921         "session",
    922         window_size=window_size,
    923         max_packet_size=max_packet_size,
    924         timeout=timeout,
    925     )

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:1051, in Transport.open_channel(self, kind, dest_addr, src_addr, window_size, max_packet_size, timeout)
   1049     if e is None:
   1050         e = SSHException("Unable to open channel.")
-> 1051     raise e
   1052 if event.is_set():
   1053     break

File ~\venvs\ve\lib\site-packages\paramiko\transport.py:2110, in Transport.run(self)
   2108     self._send_kex_init()
   2109 try:
-> 2110     ptype, m = self.packetizer.read_message()
   2111 except NeedRekeyException:
   2112     continue

File ~\venvs\ve\lib\site-packages\paramiko\packet.py:459, in Packetizer.read_message(self)
    451 def read_message(self):
    452     """
    453     Only one thread should ever be in this function (no other locking is
    454     done).
   (...)
    457     :raises: `.NeedRekeyException` -- if the transport should rekey
    458     """
--> 459     header = self.read_all(self.__block_size_in, check_rekey=True)
    460     if self.__etm_in:
    461         packet_size = struct.unpack(">I", header[:4])[0]

File ~\venvs\ve\lib\site-packages\paramiko\packet.py:303, in Packetizer.read_all(self, n, check_rekey)
    301 x = self.__socket.recv(n)
    302 if len(x) == 0:
--> 303     raise EOFError()
    304 out += x
    305 n -= len(x)

EOFError:

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

You must use tmate command to start new session. it is unable to use paramiko to start new session (at least, my understanding)

Also, it is need to use none authentication request to connect the shared session.

$ ssh -v token@sgp1.tmate.io
...
debug1: Enabling compression at level 6.
debug1: Authentication succeeded (none).
Authenticated to sgp1.tmate.io ([188.166.207.127]:22).
...

The following script is to view the shared session on tmate server:

import paramiko, os
with paramiko.Transport('sgp1.tmate.io') as transport:
    transport.use_compression()
    transport.start_client()
    transport.auth_none('---- your token here ----')
    with transport.open_session() as sess:
        sess.set_combine_stderr(True)
        sess.get_pty()
        sess.invoke_shell()
        while sess.active:
            while sess.recv_ready():
                os.write(1, sess.recv(128))

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

You should describe what you want to do with paramiko. Otherwise, please close this issue and ask on tmate forum.

@jun66j5
Copy link
Contributor

jun66j5 commented Jan 8, 2023

Ah, it is unable to request exec_command to tmate server. Instead, the command should be written to the channel after calling invoke_shell.

@thisismygitrepo
Copy link
Author

Description of what I want to do:

  • ssh to a machine over the internet (as opposed to local network)
    • tmate is my cheap and easy solution.
  • I'm not starting a tmate server on the remote with paramiko. I am only SSHing from local to an existing tmate session on the remote. This was implicit in all snippets of code I provided.

I assumed that whatever is doable via ssh utility must be doable with paramiko. But so far, we established that compress=True must be manually raised in paramiko but you never worry about this in ssh utility (may I suggest that this is handled internally if not passed?).

Thanks for the snippet. I'm not sure if it can be streamlined in the future so that it is as simple as exec_command.

@bskinn
Copy link
Contributor

bskinn commented May 11, 2023

What is the status of this, @thisismygitrepo? Did you get this to work? If not, do you have any further information about what features/fixes you might need in paramiko to make it work?

But so far, we established that compress=True must be manually raised in paramiko but you never worry about this in ssh utility (may I suggest that this is handled internally if not passed?).

If you still think this would be a helpful change, can you clarify what you mean by "this is handled internally if not passed"? Are you suggesting that paramiko should automatically attempt to connect both with and without compression?

@thisismygitrepo
Copy link
Author

thisismygitrepo commented May 18, 2023

@bskinn paramiko allowed me to have automated full control of other machines on my network. However, when the remote is only accessible via proxy/jump server like tmate, it starts to crack.

  • Yes, for once, compression=True must be passed upon instantiation if remote is served by tmate, but the equivalent ssh command doesn't require such a flag to be raised.
  • Beyond this minor inconvenience, sftp doesn't work at all in tmate case.

@bskinn
Copy link
Contributor

bskinn commented May 23, 2023

  • Yes, for once, compression=True must be passed upon instantiation if remote is served by tmate, but the equivalent ssh command doesn't require such a flag to be raised.

@jun66j5 -- do you know if common SSH implementations will automatically try with and without compression?

@bskinn bskinn added the Feature label May 23, 2023
@bskinn
Copy link
Contributor

bskinn commented May 23, 2023

I'm adding the "Feature" tag to this because it looks to me like there may be additional implementation required in order to make paramiko work here, especially with SFTP.

@bskinn
Copy link
Contributor

bskinn commented May 23, 2023

Separately, @thisismygitrepo -- to make sure that searches for 'tmate' can find this ticket, could you fix the typo in the issue name (tamte --> tmate)?

@jun66j5
Copy link
Contributor

jun66j5 commented May 23, 2023

do you know if common SSH implementations will automatically try with and without compression?

The OpenSSH client sends kexinit packets to prefer the compression setting, however paramiko with compression=False sends the kexinit packets to require no compression.

Compression in kexinit packet
OpenSSH Compression no none,zlib@openssh.com,zlib
OpenSSH Compression yes zlib@openssh.com,zlib,none
paramiko compression=False none (requiring no compression to the server)
paramiko compression=True zlib@openssh.com,zlib,none

See also:

@bskinn bskinn added the SFTP label May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants