Data packets sent to dropbear can be oversized
See original GitHub issueSending large amounts of data to a process’s stdin through dropbear causes dropbear to complain with “bad packet, oversized decompressed” and close the channel.
Checked with asyncssh v2.9.0 (current master) and dropbear v2020.81. I see no related changes in asyncssh develop
and on the dropbear side it seems like it should reproduce on all versions from v2013.59 to current master — anything since https://github.com/mkj/dropbear/commit/49263b5314e59de654d7b01f513b1cd95b1b9ec9 .
Reproducing this should amount to just having dropbear running somewhere — in case it makes a difference, I’ve seen this with dropbear -W 65536
which increases the default receive window size from 24576 to 65536 — and then e.g.:
import asyncio
import asyncssh
import logging
logging.basicConfig()
asyncssh.set_log_level(logging.DEBUG)
asyncssh.set_debug_level(2)
async def run():
client = await asyncssh.connect(...)
data = "x" * 50000
result = await client.run("cat", input=data)
assert result.stdout == data
asyncio.get_event_loop().run_until_complete(run())
To be precise, this works up to a payload size of 32758 but fails for 32759 or greater. This is obviously no coincidence, from an excerpt of the log output:
DEBUG:asyncssh:[conn=0, chan=0] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=0] Requesting new SSH session
DEBUG:asyncssh:[conn=0, chan=0] Initial recv window 2097152, packet size 32768
DEBUG:asyncssh:[conn=0, chan=0] Initial send window 65536, packet size 32759
INFO:asyncssh:[conn=0, chan=0] Command: cat
DEBUG:asyncssh:[conn=0, chan=0] Sending 32759 data bytes
DEBUG:asyncssh:[conn=0, chan=0] Sending EOF
DEBUG:asyncssh:[conn=0, chan=0] Reading from channel started
INFO:asyncssh:[conn=0] Connection failure: [Errno 104] Connection reset by peer
From what I can tell, dropbear negotiating a receive packet size of 32759 does not mean that it is willing to accept a MSG_CHANNEL_DATA
with 32759 data bytes within it, but rather the whole String(data)
, i.e. with the 4-byte length included, has to fit within those 32759 bytes, meaning there’s room for only 32755 bytes in data
itself. This feels somehow logical since it allows for 32768 bytes (dropbear’s default RECV_MAX_PAYLOAD_LEN
) to contain the 1-byte packet type, 4-byte channel, and in the case of MSG_CHANNEL_EXTENDED_DATA
4-byte data type, along with the rest of the payload. This snippet in dropbear’s source suggests the same: https://github.com/mkj/dropbear/blob/a70b9e34c8119a82e05aaf4f7faa0ebf5a50dacc/common-channel.c#L62-L67
I don’t know enough about the protocol to be able to say if this is actually an issue in asyncssh or in dropbear, but given the proliferation of old dropbear installations in embedded devices, it seems most practical to work around it in the client anyway.
Issue Analytics
- State:
- Created a year ago
- Comments:9 (6 by maintainers)
I just realized I left it out of the change log, but this fix has been included in AsyncSSH 2.10.1. Thanks again for reporting this and helping me to reproduce it. The updated changelog is now in the “develop” branch and will be included in the next release.
Great, thanks for digging into it!