High Performance SSH/SCP
Posted by gslin 6 days ago
Comments
Comment by nickcw 13 hours ago
The main problem is that it packetizes the data and waits for responses, effectively re-implementing the TCP window inside a TCP stream. You can only have so many packets outstanding in the standard SFTP implementation (64 is the default) and the buffers are quite small (32k by default) which gives a total outstanding data of 2MB. The highest transfer rate you can make depends on the latency of the link. If you have 100 ms of latency then you can send at most 20 MB/s which is about 200 Mbit/s - nowhere near filling a fast wide pipe.
You can tweak the buffer size (up to 256k I think) and the number of outstanding requests, but you hit limits in the popular servers quite quickly.
To mitigate this rclone lets you do multipart concurrent uploads and downloads to sftp which means you can have multiple streams operating at 200 Mbit/s which helps.
The fastest protocols are the TLS/HTTP based ones which stream data. They open up the TCP window properly and the kernel and networking stack is well optimized for this use. Webdav is a good example.
Comment by riobard 13 hours ago
why is it designed this way? what problems it's supposed to solve?
Comment by nickcw 12 hours ago
SFTP was designed as a remote file system system access protocol rather than transfer a single file like scp.
I suspect that the root of the problem is that SFTP works over a single SSH channel. SSH connections can have multiple channels but usually the server binds a single channel to a single executable so it makes sense to use only a single channel.
Everything flows from that decision - packetisation becomes necessary otherwise you have to wait for all the files to transfer before you can do anything else (eg list a directory) and that is no good for your remote filesystem access.
Perhaps the packets could have been streamed but the way it works is more like an RPC protocol with requests and responses. Each request has a serial number which is copied to the response. This means the client can have many requests in-flight.
There was a proposal for rclone to use scp for the data connections. So we'd use sftp for the day to day file listings, creating directories etc, but do actual file transfers with scp. Scp uses one SSH channel per file so doesn't suffer from the same problems as sftp. I think we abandoned that idea though as many sftp servers aren't configured with scp as well. Also modern versions of OpenSSH (OpenSSH 9.0 released April 2022) use SFTP instead of scp anyway. This was done to fix various vulnerabilities in scp as I understand.
Comment by charonn0 12 hours ago
Comment by Veserv 12 hours ago
It just has a in-flight message/queue limit like basically every other communication protocol. You can only buffer so many messages and space for responses until you run out of space. The problem there is just that the default amount of buffering is very low and is not adaptive to the available space/bandwidth.
Comment by rapier1 12 hours ago
Comment by adrian_b 11 hours ago
Besides being faster, with rsync and the right command options you can be certain that it makes exact file copies, together with any file metadata, even between different operating systems and file systems.
I have not checked if in recent years all the bugs of scp and sftp have been fixed, but some years ago there were cases when scp and sftp were losing silently, without warnings, some file metadata (e.g. high-precision timestamps, which were truncated, or extended file attributes).
I am using ssh every day, but there are decades since I have last used scp or sftp, with the exception of the cases when I have to connect to a server that I cannot control and where it happens that rsync is not installed. Even on such servers, if I may add an executable in my home directory, I first copy there an rsync with scp, then I do any other copies with that rsync.
Comment by imcritic 7 hours ago
Comment by rapier1 9 hours ago
https://gist.github.com/rapier1/325de17bbb85f1ce663ccb866ce2...
Comment by adolph 12 hours ago
I think maybe you are referring to QUIC [0]? It'd be interesting to see some userspace clients/servers for QUIC that compete with Aspera's FASP [1] and operate on a point to point basis like scp. Both use UDP to decrease the overhead of TCP.
Comment by rapier1 12 hours ago
Comment by adolph 11 hours ago
However, I observed that curl [0] uses openssl' quic implementation (for one of its experimental implementations). Another backend for curl is Quiche [1] which has client and server components already, has the userspace crypto etc. It's a little confusing to me, but CloudFlare also has a project quiche [2] which is a Rust crate with a CLI to share and consume files.
0. https://curl.se/docs/http3.html
Comment by Veserv 11 hours ago
To be fair, that is not really a problem of the protocol, just the implementations. You can comfortably drive 10x that bandwidth with a reasonable design.
Comment by adolph 8 hours ago
Comment by nickcw 11 hours ago
I just think for streaming lots of data quickly HTTP/1.x plus TLS plus TCP has received many more engineering hours of optimization than any other combo.
Comment by adolph 8 hours ago
Comment by formerly_proven 11 hours ago
Comment by josephg 19 hours ago
Comment by Bender 16 hours ago
The only downside I have found using lftp is that given there is no corresponding daemon for rsync on the destination then directory enumeration can be slow if there are a lot of nested sub-directories. Oh and the syntax is a little odd for me anyway. I always have to look at my existing scripts when setting up new automation.
Demo to play with, download only. Try different values. This will be faster on your servers, especially anything within the data-center.
ssh mirror@mirror.newsdump.org # do this once to accept key as ssh-keyscan will choke on my big banner
mkdir -p /dev/shm/test && cd /dev/shm/test
lftp -u mirror, -e "mirror --parallel=4 --use-pget=8 --no-perms --verbose /pub/big_file_test/ /dev/shm/test;bye" sftp://mirror.newsdump.org
For automation add --loop to repeat job until nothing has changed.Comment by chasil 14 hours ago
The design of sftp is such that it cannot exploit "TCP sliding windows" to maximize bandwidth on high-latency connections. Thus, the migration from scp to sftp has involved a performance loss, which is well-known.
https://daniel.haxx.se/blog/2010/12/08/making-sftp-transfers...
The rsync question is not a workable answer, as OpenBSD has reimplemented the rsync protocol in a new codebase:
An attempt to combine the BSD-licensed rsync with OpenSSH would likely see it stripped out of GPL-focused implementations, where the original GPL release has long standing.
It would be more straightforward to design a new SFTP implementation that implements sliding windows.
I understand (but have not measured) that forcibly reverting to the original scp protocol will also raise performance in high-latency conditions. This does introduce an attack surface, should not be the default transfer tool, and demands thoughtful care.
Comment by Bender 13 hours ago
Rsync is great when moving files between trusted systems that one has a shell on but the downside is that rsync can not split up files into multiple streams so there is still a limit based on source+dest buffer+rtt and one has to provide people a shell or add some clunky way to prevent a shell by using wrappers unless using native rsync port 873 which is not encrypted. Some people break up jobs on the client side and spawn multiple rsync jobs in the background. It appears that openrsync is still very much work in progress.
SCP is being or has been deprecated but the binaries still exist for now. People will have to hold onto old binaries and should probably static compile them as the linked libraries will likely go away at some point.
Comment by chasil 12 hours ago
If you want to use the historic scp server instead, a command line option is provided to allow this:
"In case of incompatibility, the scp(1) client may be instructed to use the legacy scp/rcp using the -O flag."
https://www.openssh.org/releasenotes.html
The old scp behavior hasn't been removed, but you need to specifically request it. It is not the default.
It would seem to me that an alternate invocation for file transfer could be tested against sftp in high latency situations:
ssh yourhost 'cat somefile' > somefile
That would be slightly faster than tar, which adds some overhead. Using tar on both sides would allow transfers of special files, soft links, and retain hard links, which neither scp nor sftp will do. ssh yourhost 'tar cf - yourdir' | tar xpf -
Windows has also recently added a tar command.Comment by rapier1 9 hours ago
If your BDP is less than 2MB you still might get some benefit if you are CPU limited and use the parallel ciphers. However, the fastest cipher is AES-GCM and we haven't parallelized that as of yet (that's next on the list).
Comment by chasil 8 hours ago
Moving a terabyte database in an upgrade, I have connected three ports direct (no switch), then used xargs to keep all three connections busy with transferring the 2gb data files. I can get the transfer done in under an hour this way.
I don't currently have a performance need for an encrypted transfer, but one may arise.
Comment by rapier1 12 hours ago
Comment by ectospheno 8 hours ago
I thought openrsync existed solely because of rpki. Even OpenBSD devs recommend using the real version from ports.
Comment by zenoprax 14 hours ago
I often find myself needing to move a single large file rather than many smaller ones but TCP overhead and latency will always keep speeds down.
Comment by Bender 13 hours ago
Comment by fanf2 13 hours ago
Comment by Bender 12 hours ago
Comment by aidenn0 14 hours ago
Comment by zenoprax 5 hours ago
Comment by harvie 19 hours ago
Comment by rapier1 13 hours ago
I've been developing it for 20+ years and if you have any specific questions I'd be happy to answer them.
Comment by Bad_CRC 18 hours ago
Comment by Zambyte 17 hours ago
Comment by bomewish 16 hours ago
Comment by messe 16 hours ago
You may as well just use tailscale ssh in that case. It already disables ssh encryption because your connection is encrypted with WireGuard anyway.
Comment by gear54rus 16 hours ago
Better question is 'does it have any actual improvements in day-to-day operations'? Because it seems like it mostly changes up some ciphering which is already very fast.
Comment by yjftsjthsd-h 15 hours ago
On what basis are making that claim? Because AFAICT, concern about it being less secure is entirely reasonable and is one of the big caveats to it.
Comment by rapier1 13 hours ago
Comment by Zambyte 16 hours ago
- IF you don't trust it
- AND you want to use it
=> run it on a private network
You don't have to trust it for security to use it. Putting services on secure networks when the public doesn't need access is standard practice.
Comment by joecool1029 13 hours ago
But I don’t miss having those limitations.
Comment by rapier1 9 hours ago
Comment by emilfihlman 15 hours ago
Comment by rapier1 13 hours ago
Comment by joecool1029 13 hours ago
Comment by rapier1 12 hours ago
Comment by Almondsetat 18 hours ago
Comment by wahern 16 hours ago
OpenBSD's filesystem operations are slow not because of UFS2, but because they simply haven't been optimized up-and-down the stack the way Ext4 has been Linux or UFS2 on FreeBSD. And of course, OpenBSD's implementation doesn't have a journal (both UFS and Ext had journaling bolted late in life) so filesystem checks (triggered on an unclean shutdown or after N boots) can take a long time, which often cause people to think their system has frozen or didn't come up. That user interface problem notwithstanding, UFS2 is extremely robust. OpenBSD is very conservative about optimizations, especially when they increase code complexity, and particularly for subsystems where the project doesn't have time available to give it the necessary attention.
Comment by chasil 14 hours ago
I believe that these were recently removed. Perhaps they don't play well with SMP.
Comment by throw0101d 13 hours ago
Comment by frantathefranta 16 hours ago
[1] https://github.com/freebsd/freebsd-ports/blob/main/security/...
[2] https://github.com/NixOS/nixpkgs/blob/d85ef06512a3afbd6f9082...
Comment by yjftsjthsd-h 15 hours ago
Comment by suprjami 17 hours ago
Comment by rapier1 12 hours ago
Comment by gorgoiler 13 hours ago
Comment by hsbauauvhabzb 17 hours ago
Comment by joecool1029 13 hours ago
There are some minor usability bugs and I think both endpoints need to have it installed to take advantage. I remember asking ages ago why it wasn’t upstreamed, there were reasons…
Comment by rapier1 12 hours ago
As an aside - you only really need HPN-SSH on the receiving side of the bulk data to get the buffer normalization performance benefits. It turns out the bottleneck is almost entirely on the receiver and the client will send out data as quickly as you like. At least it was like that until OpenSSH 8.8. At that point changes were made where the client would crash if the send buffer exceeded 16MB. So we had to limit OpenSSH to HPN-SSH flows to a maximum of 16MB receive space. Which is annoying but that's still going to be a win for a lot of users.
Comment by nhatcher 15 hours ago
[1]: https://mosh.org/
Comment by freedomben 15 hours ago
I've been using mosh now for over a decade and it is amazing. Add on rsync for file transfers and I've felt pretty set. If you haven't checked out mosh, you should definitely do so!
Comment by chrisweekly 15 hours ago
Comment by actionfromafar 15 hours ago
Comment by freedomben 15 hours ago
Comment by freedomben 15 hours ago
Comment by tristor 14 hours ago
The only change I see here that is probably harmless and a speed boost is using AES-NI for AES-CTR. This should probably be an upstream patch. The rest is more iffy.
Comment by rapier1 13 hours ago
The main performance improvement is from the buffer normalization. This can provide, on the right path, a 100x improvement in throughput performance without any compromise in security.
Comment by ollybee 15 hours ago
Comment by rapier1 13 hours ago
Comment by baden1927 15 hours ago