sshtunnel
sshtunnel copied to clipboard
Timeout set is not honoured by sshtunnel
Hi,
Python 3.8.3 (default, Aug 31 2020, 16:03:14)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sshtunnel
>>> sshtunnel.__version__
'0.4.0'
>>>
When specifying SSH_TIMEOUT, this value is not honoured. From the example on the website, note the timestamps on when an exception is thrown. It seems the timeout stays at approx 120seconds.
Code to reproduce:
import sshtunnel
import datetime
sshtunnel.SSH_TIMEOUT = 5.0
sshtunnel.TUNNEL_TIMEOUT = 5.0
print('======START======')
print(datetime.datetime.now())
print('=================')
server = sshtunnel.SSHTunnelForwarder(
'10.39.254.33',
ssh_username="pahaz",
ssh_password="secret",
remote_bind_address=('127.0.0.1', 8080)
)
server.start()
print(server.local_bind_port) # show assigned local port
server.stop()
print('======EXCEPTION======')
print(datetime.datetime.now())
print('=================')
OUTPUT:
======START======
2021-01-18 12:36:20.427075
=================
2021-01-18 12:38:30,924| ERROR | Could not connect to gateway 10.39.254.33:22 : Unable to connect to 10.39.254.33: [Errno 110] Connection timed out
TUNNEL_TIMEOUT
and SSH_TIMEOUT
consts are for socket.settimeout. It's not related to SSH protocol.
Paramiko has special variables for SSH protocol level timeout tunning (banner_timeout
, handshake_timeout
, auth_timeout
).
Try this example:
import sshtunnel
import datetime
sshtunnel.DEFAULT_LOGLEVEL = 1
print('======START======')
print(datetime.datetime.now())
print('=================')
server = sshtunnel.SSHTunnelForwarder(
'10.39.254.33',
ssh_username="pahaz",
ssh_password="secret",
remote_bind_address=('127.0.0.1', 8080)
)
# how long (seconds) to wait for the SSH banner
server._transport.banner_timeout = 15
# how long (seconds) to wait for the handshake to finish after SSH banner sent
server._transport.handshake_timeout = 15
# how long (seconds) to wait for the auth response.
server._transport.auth_timeout = 30
server.start()
print(server.local_bind_port) # show assigned local port
server.stop()
print('======EXCEPTION======')
print(datetime.datetime.now())
print('=================')
Could you please also provide the logs with sshtunnel.DEFAULT_LOGLEVEL = 1
Thanks for the reply. In your example, the server object has no attribute _transport:
'SSHTunnelForwarder' object has no attribute '_transport'
With my example, running with sshtunnel.DEFAULT_LOGLEVEL = 1, here is the output:
2021-02-01 12:27:19,196| WAR | MainThrea/1032@sshtunnel | Could not read SSH configuration file: ~/.ssh/config
2021-02-01 12:27:19,197| INF | MainThrea/1060@sshtunnel | 0 keys loaded from agent
2021-02-01 12:27:19,218| DEB | MainThrea/1309@sshtunnel | Private key file (/home/fatti/.ssh/id_rsa, <class 'paramiko.rsakey.RSAKey'>) successfully loaded
2021-02-01 12:27:19,219| INF | MainThrea/1117@sshtunnel | 1 key(s) loaded
2021-02-01 12:27:19,220| INF | MainThrea/0978@sshtunnel | Connecting to gateway: 10.39.254.33:22 as user 'pahaz'
2021-02-01 12:27:19,220| DEB | MainThrea/0983@sshtunnel | Concurrent connections allowed: True
2021-02-01 12:27:19,222| DEB | MainThrea/1400@sshtunnel | Trying to log in with key: b'c4eb02e1b3a56952de73f72de91eb528'
======START======
2021-02-01 12:27:19.195555
=================
2021-02-01 12:29:29,796| ERR | MainThrea/1223@sshtunnel | Could not connect to gateway 10.39.254.33:22 : Unable to connect to 10.39.254.33: [Errno 110] Connection timed out
---------------------------------------------------------------------------
BaseSSHTunnelForwarderError Traceback (most recent call last)
<ipython-input-10-045b309d7b47> in <module>
14 )
15
---> 16 server.start()
17
18 print(server.local_bind_port) # show assigned local port
~/python_envs/fatti_post_analytics/lib/python3.8/site-packages/sshtunnel.py in start(self)
1329 self._create_tunnels()
1330 if not self.is_active:
-> 1331 self._raise(BaseSSHTunnelForwarderError,
1332 reason='Could not establish session to SSH gateway')
1333 for _srv in self._server_list:
~/python_envs/fatti_post_analytics/lib/python3.8/site-packages/sshtunnel.py in _raise(self, exception, reason)
1172 def _raise(self, exception=BaseSSHTunnelForwarderError, reason=None):
1173 if self._raise_fwd_exc:
-> 1174 raise exception(reason)
1175 else:
1176 self.logger.error(repr(exception(reason)))
BaseSSHTunnelForwarderError: Could not establish session to SSH gateway
This seems to work, except that the transport has been replaced with _get_transport. So the code should be:
# how long (seconds) to wait for the SSH banner
server._get_transport().banner_timeout = 5
# how long (seconds) to wait for the handshake to finish after SSH banner sent
server._get_transport().handshake_timeout = 5
# how long (seconds) to wait for the auth response.
server._get_transport().auth_timeout = 5
Thanks for the help!
FYI, the methods using _get_transport()
didn't work for me, but I was able to use socket.setdefaulttimeout
instead:
import socket
from paramiko import Transport
# Must be called before the socket is created
socket.setdefaulttimeout(2)
T = Transport((<host>, <port>))
# Optionally, set it back to the default (once you are certain the socket has been created)
socket.setdefaulttimeout(None)
It quickly timed-out:
raise SSHException(
paramiko.ssh_exception.SSHException: Unable to connect to <host>: timed out
sshtunnel.SSH_TIMEOUT = 5, it works