A little SSH file copy magic at the command line
redhat.com
redhat.com
"You can authenticate with keys" wasn't the punchline I was expecting but perhaps if I had noticed the domain I may have set my expectations differently.
If you copy a file using this method from host B to host C by issuing an scp command on host A, do the bits go directly from host B to host C? or do they go through host A on their way to host C ?
I suspect the latter is what happens on Windows network fileshares, because it takes significantly longer to perform a file transfer from \\hostB to \\hostC while in \\hostA than just doing it direct from \\hostB or \\hostC.
What happens in linux behind the scenes for such 3-party scp transfers?
-3 Copies between two remote hosts are transferred
through the local host. Without this option the
data is copied directly between the two remote
hosts. Note that this option disables the
progress meter.Any technology demonstrated to a sufficiently unsophisticated audience is indistinguishable from sufficiently advanced technology, which is indistinguishable from magic.
~~ Receiving system `# nc -l -p $arbitraryPort > /path/to/file `
~~ Sending system `# cat /path/to/file | nc $receivingSystemIP -p $arbitraryPort `
eg: `# nc -l -p 9669 > /home/user/staging/httpd.conf ` `# cat /etc/httpd/httpd.conf | nc 10.50.50.1 -p 9669 `
This method is a useful feather to have in one's cap when used in combination with tar and Pipeviewer `pv`.
I've used this several times doing a backup of a large database and when I don't have enough space locally to hold the copy.
https://www.openssh.com/txt/release-8.0
> The scp protocol is outdated, inflexible and not readily fixed. We recommend the use of more modern protocols like sftp and rsync for file transfer instead.
So, if you're using it to load code for net booting, scp is the obvious choice since you want to automate the retrieval of a specific file from a specific place, to a specific destination. And you don't want to have to babysit it every time.
If you're copying some specific files with lots of randomish names from your livingroom entertainment server's Downloads directory to your laptop's Documents directory, sftp is your friend.
One doesn't supersede the other in any way whatsoever. There are so many things wrong with the idea that rsync is more modern.
Isn't rsync older by quite a bit? And since it is lacking encryption, isn't scp the more obvious tool to use?
You can't use rsync the way that you use sftp. Think of it this way:
* Secure direct: scp <-- encrypted
* Secure interactive: sftp <-- encrypted
* Insecure direct: rsync <-- clear text
* Insecure interactive: ftp <-- clear text
Use clear text if the network is absolutely known to be secure (good luck on that in any productive environment) and stick to scp and sftp or equivalent secure protocols.
Toss ftp and rsync to the dogs and pretend you've never heard of them except in dire emergencies where significantly better tools (like scp and sftp) aren't available.
No. scp was included in Tatu Ylönens original ssh in 1995. sftp is significantly newer, e.g. openssh gained both client and server implementation with the 2.5 release in 2001, and is dependent on the ssh 2.0 protocol.
> One is interactive, and the other isn't. Nothing more. Nothing less.
No. They are different network protocols. And per CVE-2019-6111 mentioned in the link I provided in the previous post, the scp protocol has some questionable semantics, which is why the openssh developers are recommending people to switch to better designed protocols such as sftp or rsync.
> So, if you're using it to load code for net booting, scp is the obvious choice since you want to automate the retrieval of a specific file from a specific place, to a specific destination. And you don't want to have to babysit it every time.
You can automate sftp as well. Fetching files is as simple as with scp, but uploading is more tedious, but doable if, for instance, you don't have rsync available. Something like "sftp -b - user@server:/path <<< 'put filename'".
> There are so many things wrong with the idea that rsync is more modern.
rsync is not a fundamentally broken network protocol like scp. And as another answer mentioned, you can tunnel rsync over ssh, which nowadays even is the default if you don't specify otherwise.
rsync lately, and depending how it is compiled, defaults to using ssh, so it shouldn't be clear text in that case.
There was a recent CVE about writing to wherever the server specified but that does not necessarily reflect poorly on the protocol.
When copying a large number of small files rsync over ssh is much faster.
(I'm not sure how it's done, presumably interleaving readdir() calls with non-blocking sendfile, allowing page cache prefetching as well as the actual sending to be done in parallel by the kernel.)
... and if pigs could fly.. It could, but it doesn't, and openssh developers have made it quite clear they view scp as fundamentally broken and have no interest in improving it.
Scripting sftp is, while doable, tedious compared to scp. Then again, rsync is scriptable as well and offers much more than scp.
tar c folder | ssh server tar x rsync --filter=':- .gitignore' ...Is set on `sshd_config`.
Actually, scp got quite old. Rsync typically makes a better job, especially with many files or unreliable networks. Streaming tar.gz over ssh is again typically faster for many files.
$ lscpu | grep name
Model name: Intel(R) Xeon(R) Gold 6154 CPU @ 3.00GHz
$ time dd if=/dev/zero of=/dev/null bs=10240 count=102400
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 0.145168 s, 7.2 GB/s
real 0m0.147s
user 0m0.036s
sys 0m0.111s
$ time dd if=/dev/zero bs=10240 count=102400 | gzip > /dev/null
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 5.36061 s, 196 MB/s
real 0m5.364s
user 0m5.317s
sys 0m0.472s
$ time dd if=/dev/urandom bs=10240 count=102400 | gzip > /dev/null
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 27.3478 s, 38.3 MB/s
real 0m27.352s
user 0m27.169s
sys 0m10.119s
$ time dd if=biggestwords bs=10240 count=102400 | gzip > /dev/null
10642+1 records in
10642+1 records out
108981378 bytes (109 MB) copied, 6.66068 s, 16.4 MB/s
real 0m6.669s
user 0m6.667s
sys 0m0.249s
$ time dd if=biggestwords bs=10240 count=102400 | gzip -1 > /dev/null
10642+1 records in
10642+1 records out
108981378 bytes (109 MB) copied, 1.53539 s, 71.0 MB/s
real 0m1.540s
user 0m1.522s
sys 0m0.138s
$ time dd if=biggestwords of=/dev/null bs=10240 count=102400
10642+1 records in
10642+1 records out
108981378 bytes (109 MB) copied, 0.0407698 s, 2.7 GB/s
real 0m0.043s
user 0m0.007s
sys 0m0.036s
Biggestwords is simply /usr/share/dict/words concatenated to itself 22 times so as to provide ~100 MB of data.If you can get good enough compression it might still be worthwhile to compress. But it's pretty rare in my experience.
[0] https://coderwall.com/p/bmv0nw/dump-postgres-databases-throu...
# from host1:
cd $DIRECTORY && tar -jcf - . | ssh host2 "cd DESTINATION_DIR && tar jxvf - "
And 'scp -c' will automatically compress and decompress your file, and 'scp -R' will walk a file tree for you.
This isn’t me telling you to implement some scary arcane wire-protocol, either. All an AuthorizedKeysCommand script/binary has to do is spit out a stream of SSH pubkeys considered valid to authenticate a login attempt on a given username. The “implicit default” AuthorizedKeysCommand is `cat “/home/$1/.ssh/authorized_keys”`. Your implementation just needs to do the same thing that that command does: take “pubkeys that mean this user could log into this box” from some source, and spit them at stdout. (Don’t want that user logging in to that box? Don’t write anything to stdout.)
I wrote my own little AuthorizedKeysCommand binary a while back (https://github.com/tsutsu/github-auth3) for using Github’s user-SSH-keys and user-org-membership APIs as such a repository. You tell it a Github org name, and it’ll stream out the username’s equivalent Github user’s SSH pubkeys, if-and-only-if that Github user is a member of the specified Github org. (The code is, like, 20 lines. Read it yourself!)
——
This is also one case where specific ecosystems can really smooth things over, though.
If you’re running in Google Cloud, for example, you don’t need to do any of the above. Instead, just configure “OS Login” (https://cloud.google.com/compute/docs/oslogin/), and then log into the gcloud(1) tool on your workstation as an IAM user that you’ve granted the “OS Login” role. Then it’s as simple as:
SSH: `gcloud compute ssh instanceName`
SCP: `gcloud compute scp ./f.txt instanceName:` (or vice-versa)
On first use, IAM will generate a new SSH keypair for the OS Login user. Your gcloud(1) keystore will grab the private half when it needs it; Compute Engine instances will hit IAM to ask for the public half when anyone tries to log in (probably using an SSH `AuthorizedKeysCommand` stanza; I haven’t looked into it.) The user account (`me_example_com` if your IAM user is `me@example.com`) will be created on the instance if it doesn’t already exist (but you can set up your instance template such that it does already exist, if you like, or set up roaming profiles using Filestore as an NFS host, or whatever.)
You can also log into your OS Login account through regular direct SSH/SCP to the instance’s external IP (this isn’t some custom proprietary version of SSH or anything), but you won’t have access to the IAM-held private key if you’re not going through gcloud(1), so you’d want to configure your IAM user with a custom authorized pubkey first (which your instances will also automatically see.)
$ export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
$ gpg-agent --enable-ssh-support
If you get an error[2] when you are trying to ssh into a machine, you may need: $ gpg-connect-agent updatestartuptty /bye > /dev/null
For information as to how to create an authentication subkey: https://www.gniibe.org/memo/software/gpg/keygen-25519.html[1] You need to add your authentication subkey's keygrip which you can get using: gpg --list-keys --with-keygrip or the like. Separate the keygrips with a newline, and IIRC you need to have a newline at the end of the file as well.
[2] For example: "sign_and_send_pubkey: signing failed: agent refused operation".
I'm guessing it already exists and I don't know what it's called? (Maybe it's basically cheat-sheets? But they tend to be cues for syntax, rather than concepts).
[0] http://johnbokma.com/blog/2019/05/27/ssh-public-key-authenti...
Yubikey currently supports 4096 bit RSA keys as a part of GPG applet. There's a PIV module, however in terms of elliptic curves it only has ec256 and ec384 and I still can't get ssh and pkcs11 to pick up anything other than built-in 2048 RSA keys.
Like zmodem back in the old days (which should work with SSH, but I didn't get it to ..?)
Anyone have a suggestion?
alias upload='ssh username@server'
Then when you need to upload something, just type: upload 'something'
s/ssh/scp/
alias bcp='rsync -avzu --progress'
[EDIT: That link gives basic instructions for rsync between your current machine and a remote one. I haven't confirmed that both endpoints can be remote.]
Also in those instructions `-e ssh` might not be needed unless specifying additional ssh options or a different port, as later rsync versions ssh is often the default connection method.