Skip to content

Commit

Permalink
Change compression to be disabled by default
Browse files Browse the repository at this point in the history
This commit changes compression to default to off when AsyncSSH is
acting as a client, only enabling it if the server requires it. This
matches the OpenSSH default and avoids a potential bottleneck where
running with compression enabled can actually slow down performance
signficantly on high-bandwidth connections.

This also cleans up some unintended cosmetic differences between the
documentation for client and server connection options.
  • Loading branch information
ronf committed Oct 3, 2024
1 parent b5742a5 commit 46636d6
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 18 deletions.
6 changes: 3 additions & 3 deletions asyncssh/compression.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2013-2021 by Ron Frederick <[email protected]> and others.
# Copyright (c) 2013-2024 by Ron Frederick <[email protected]> and others.
#
# This program and the accompanying materials are made available under
# the terms of the Eclipse Public License v2.0 which accompanies this
Expand Down Expand Up @@ -149,9 +149,9 @@ def get_decompressor(alg: bytes) -> Optional[Decompressor]:

return _cmp_decompressors[alg]()

register_compression_alg(b'none',
_none, _none, False, True)
register_compression_alg(b'[email protected]',
_ZLibCompress, _ZLibDecompress, True, True)
register_compression_alg(b'zlib',
_ZLibCompress, _ZLibDecompress, False, False)
register_compression_alg(b'none',
_none, _none, False, True)
27 changes: 15 additions & 12 deletions asyncssh/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -7544,16 +7544,17 @@ class SSHClientConnectionOptions(SSHConnectionOptions):
:param compression_algs: (optional)
A list of compression algorithms to use during the SSH handshake,
taken from :ref:`compression algorithms <CompressionAlgs>`, or
`None` to disable compression.
`None` to disable compression. The client prefers to disable
compression, but will enable it if the server requires it.
:param signature_algs: (optional)
A list of public key signature algorithms to use during the SSH
handshake, taken from :ref:`signature algorithms <SignatureAlgs>`.
:param rekey_bytes: (optional)
The number of bytes which can be sent before the SSH session
key is renegotiated. This defaults to 1 GB.
key is renegotiated, defaulting to 1 GB.
:param rekey_seconds: (optional)
The maximum time in seconds before the SSH session key is
renegotiated. This defaults to 1 hour.
renegotiated, defaulting to 1 hour.
:param connect_timeout: (optional)
The maximum time in seconds allowed to complete an outbound
SSH connection. This includes the time to establish the TCP
Expand Down Expand Up @@ -8289,26 +8290,28 @@ class SSHServerConnectionOptions(SSHConnectionOptions):
this server, defaulting to `'AsyncSSH'` and its version number.
:param kex_algs: (optional)
A list of allowed key exchange algorithms in the SSH handshake,
taken from :ref:`key exchange algorithms <KexAlgs>`
taken from :ref:`key exchange algorithms <KexAlgs>`,
:param encryption_algs: (optional)
A list of encryption algorithms to use during the SSH handshake,
taken from :ref:`encryption algorithms <EncryptionAlgs>`
taken from :ref:`encryption algorithms <EncryptionAlgs>`.
:param mac_algs: (optional)
A list of MAC algorithms to use during the SSH handshake, taken
from :ref:`MAC algorithms <MACAlgs>`
from :ref:`MAC algorithms <MACAlgs>`.
:param compression_algs: (optional)
A list of compression algorithms to use during the SSH handshake,
taken from :ref:`compression algorithms <CompressionAlgs>`, or
`None` to disable compression
`None` to disable compression. The server defaults to allowing
either no compression or compression after auth, depending on
what the client requests.
:param signature_algs: (optional)
A list of public key signature algorithms to use during the SSH
handshake, taken from :ref:`signature algorithms <SignatureAlgs>`
handshake, taken from :ref:`signature algorithms <SignatureAlgs>`.
:param rekey_bytes: (optional)
The number of bytes which can be sent before the SSH session
key is renegotiated, defaulting to 1 GB
key is renegotiated, defaulting to 1 GB.
:param rekey_seconds: (optional)
The maximum time in seconds before the SSH session key is
renegotiated, defaulting to 1 hour
renegotiated, defaulting to 1 hour.
:param connect_timeout: (optional)
The maximum time in seconds allowed to complete an outbound
SSH connection. This includes the time to establish the TCP
Expand All @@ -8318,8 +8321,8 @@ class SSHServerConnectionOptions(SSHConnectionOptions):
and AsyncSSH's login timeout.
:param login_timeout: (optional)
The maximum time in seconds allowed for authentication to
complete, defaulting to 2 minutes. Setting this to 0
will disable the login timeout.
complete, defaulting to 2 minutes. Setting this to 0 will
disable the login timeout.
.. note:: This timeout only applies after the SSH TCP
connection is established. To set a timeout
Expand Down
8 changes: 5 additions & 3 deletions tests/test_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1848,8 +1848,9 @@ async def test_dropbear_client(self):
"""Test reduced dropbear send packet size"""

with patch('asyncssh.connection.SSHServerChannel', _ServerChannel):
async with self.connect(client_version='dropbear',
max_pktsize=32759) as conn:
async with self.connect(
client_version='dropbear', max_pktsize=32759,
compression_algs=['[email protected]']) as conn:
_, stdout, _ = await conn.open_session('send_pktsize')
self.assertEqual((await stdout.read()), '32758')

Expand All @@ -1875,7 +1876,8 @@ async def test_dropbear_server(self):
"""Test reduced dropbear send packet size"""

with patch('asyncssh.connection.SSHClientChannel', _ClientChannel):
async with self.connect() as conn:
async with self.connect(
compression_algs='[email protected]') as conn:
stdin, _, _ = await conn.open_session()
self.assertEqual(stdin.channel.get_send_pktsize(), 32758)

Expand Down
18 changes: 18 additions & 0 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,24 @@ def send_newkeys(self, k, h):
with self.assertRaises(asyncssh.ProtocolError):
await self.connect()

@asynctest
async def test_client_decompression_failure(self):
"""Test client decompression failure"""

def send_packet(self, pkttype, *args, **kwargs):
"""Send an SSH packet"""

asyncssh.connection.SSHConnection.send_packet(
self, pkttype, *args, **kwargs)

if pkttype == MSG_USERAUTH_SUCCESS:
self._compressor = None
self.send_debug('Test')

with patch('asyncssh.connection.SSHServerConnection.send_packet',
send_packet):
await self.connect(compression_algs=['[email protected]'])

@asynctest
async def test_packet_decode_error(self):
"""Test SSH packet decode error"""
Expand Down

0 comments on commit 46636d6

Please sign in to comment.