File Transfer with SSH, Tee, and Base64
susam.in
susam.in
I think the binaries were named 'zs' and 'zr'. It's been a long time since I needed to do this anywhere...
Wikipedia (https://en.wikipedia.org/wiki/ZMODEM) says that this came out of the BBS days. Boy, that takes me back.
Last time I used one of these (don't remember which) was when my ISP booted me off cause of not paying bill, but minicom still worked, and gave me a shell. This was around 2005.
I used the crap out of them dialing-in to systems back in the day. I had TELNET and FTP access to the Internet out of a dial-in to a shell on a Unix host in the mid 90s (no SLIP, PPP, or SLiRP from the provider at the time. It was great to be able to ftp down files to my home directory then 'sz' them back home.
scp and sftp are great, but the nice thing about in-band file transfers is that your shell session already has the current context for simplifying the transfer. For example, you often want to send to or receive from the current working directory, or something nearby, and interactive file globbing is just a single tab key away, without having to switch sessions, login all over again, copy paths, etc.
[1] I don't miss automatic printing without confirmation, though. The prank of `cat /vmlinuz | write user` wasn't that funny when the service desk hands you an entire ream of garbage along with a reprimand.
I’ve used it in datacenters where I’m ssh’d through three intermediate hosts, or when I’m inception-ing down into containers and vm’s
Tweeted about zmodem just last night! https://twitter.com/ryancnelson/status/1306444057602711553
ssh hostname tar cvjf - /path/to/folder | tar xjf -
Basically I ask ssh to execute tar on the remote host to create a compressed archive. ssh will output the archive contents on the local host; this data is then passed on to a local tar for extraction.Doing it on your time means you delay delivering on your project and you let whoever did this get away with wasting everybody elses time.
> Doing it on your time means you delay delivering on your project and you let whoever did this get away with wasting everybody elses time.
While it may be distasteful, what's the alternative? Refusing on principle to use a system configured in a way you don't like is way more likely to hurt you than it is to hurt anyone else, especially the person who configured the system.
Even if you are doing work for someone else (which, I think, is not indicated in the post), so that that person will be affected by your principled refusal, there's no guarantee that they're the ones who misconfigured the environment in which you're operating.
Rather than pull via SSH I login to the remote interactive shell and dump the file onto my own server via SSH from that remote shell.
ssh hostname -qt 'bash -lc "tar czf - /path/to/folder 2>/dev/null | base64"' | base64 -id | tar xvzf - "... base64 | sed -e 's/^/~/'" | sed -ne 's/^~//p' | base64 ...`
BTW, base64 isn't a standard command (nonexistent on OpenBSD), and the options can vary based on implementation even when it exists (decode is -d for GNU coreutils base64, but -D for the macOS command). You can whip up an alternative using od(1) and printf(1): #!/bin/sh
# encode as backslash-escaped octal (\0NNN)
export LC_ALL=C
od -An -to1 -v \
| sed -ne 's/\([01234567][01234567]*\)/\\0\1/gp' \
| tr -cd '\\01234567\n'
#!/bin/sh
# decode backslash-escaped octal
export LC_ALL=C
while read -r L; do
printf "%b" "$L"
done
It might not be strictly POSIX compliant, but I don't think there are any environments where printf isn't 8-bit clean in the C locale. I've tested something similar (see below) on various versions of bash and d?ash, as well as /bin/sh on AIX, FreeBSD, macOS, OpenBSD, NetBSD, and Solaris.You can implement base64 as a shell script using the above techniques, and do so without relying on awk, which isn't always available. If od(1) isn't available you can use dd(1) to extract stdin byte-by-byte and convert with printf(1), but that gets really slow. I've written an implementation that only needs an 8-bit-clean but otherwise POSIX compliant shell, printf, and either dd or od. It doesn't need tr, but it's even slower without it. It just converts the bytes to decimal and uses plain shell arithmetic for the primitive encoding and decoding, similar to how it would be done in any language.
... | openssl enc -base64" | openssl -base64 -d | ... ... | openssl enc -base64" | openssl enc -base64 -d | ... ssh -L 9000:127.0.0.1:8000 user@host
But when I visit http://127.0.0.1:9000/ on my local system, I get a connection reset by peer error. At the same time, in the terminal where I have set up the port forward with the ssh command above, I get this error: open failed: unknown channel type
The SSH gateway is forbidding port forwarding as well.A possible workaround for this specific scenario would be to use 'sshutle' which runs a python script on the remote end to terminate the traffic.
Except in your specific scenario you'd have to somehow trick it to execute using a login shell like one of the other comments shows.
Having said all of that, I would just do what you did :)
ssh user@host cat remote_file > local_file
to copy the contents of "remote_file" on the server to "local_file" on your local machine.scp is deprecated [1]; use sftp instead. At the very least, sftp should be your preference over scp.
[1] https://unix.stackexchange.com/questions/571293/is-scp-unsaf...
I'm not 100% sure I buy those "it's less secure" arguments in that Stack-exchange post, but even if true - lots of people use SSH to move stuff around inside an intranet, where both ends of the connection are trusted. In that kind of context, scp works great.
The fact that a remote server gets to silently respond to the request "Hey, I'd like funny-cat-noises.mp3" by writing two files, funny-cat-noises.mp3 and also .security/overrides.conf ?
Maybe your understanding of the protocol was that you allow a remote server to write whatever files it wants to your disk. That seems like a pretty crazy thing to want, but OK.
Most people assume it does what it seems like it does. You name one or more files on one machine, and they're copied to the other machine. SFTP can deliver without nasty surprises, but SCP can't really do so, although the OpenSSH team have worked pretty hard to make the worst surprises less likely to bite you.
Maybe not an issue if you trust the machine you're copying to/from.
Maybe you shouldn't. After all, the remote machine doesn't have root on your machine. Even if you are root on the remote machine, how can you know the server isn't compromised? You can't.
the sftp command has lousy ux, it's unlikely people will switch to it en masse.
> From The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]:
> deprecated adj.
> Said of a program or feature that is considered obsolescent and in the process of being phased out, usually in favor of a specified replacement. [..]
On *ix things stay around for pretty long. You still have ed and ftp on Ubuntu 20.04!
Without this constraint, yes, I agree what you mention would be the obvious straightforward solution.
Host rcpu-tun
User YOURLOGIN
IdentityFile ~/.ssh/YOURSECRET
ProxyCommand ssh -q -W HOSTBEHINDFW:22 -l PROXYLOGIN SSHGATEWAY
HostName HOSTBEHINDFW ssh system1 'cat payload' > temp
cat temp | ssh system2 'cat > payload'
Or cut out the middleman, as long as getting two password prompts isn't too confusing: ssh system1 'cat payload' | ssh system2 'cat > payload'
I've found the base64/copy-paste trick useful when I can't do a conventional SSH. Usually this is when one of the machines is accessed via a serial console.In that scenario, it can help to compress the data before base64-ing it:
machine1$ cat payload | gzip | base64
<output>
machine2$ base64 -d | gzip -d > payload
<paste output>I do wonder if there's a workaround for that, though. "bash" has the "-l" option for "Make bash act as if it had been invoked as a login shell", and also "-i" forces interactive mode. For ssh, "-t" is "Force pseudo-terminal allocation"; would that work?
I've found zssh can be quite handy for that, it layers an extra pty over the SSH connection, for file transfer. By default it uses the ZMODEM protocol via rz/sz, but any pair of programs can be plugged in instead - useful if the connection isn't 8-bit clean.
$ aws ssm start-session --target i-XXXXXX | tee base64.txtRather than copying the file to the jump host, then to the remote host, I'll just gzip and base64 encode it, then copy and paste it to the remote host.
Edit: Just to be clear, I'm talking about transient situations-- like when I'm working with another contractor on a day-long gig, etc. Obviously, for an established LAN piping files to each other over isn't a sensible or secure file transfer method.
For myself I have written two shell functions; nc_send and nc_recv. It uses Nmap's ncat with SSL. It uses GPG and to verify data integrity, I use b2sum. Simple, yet perfect for the task. I use it often besides scp, but of course sometimes netcat is all I need.
> Give me the last two octets of your APIPA address
Is not APIPA Windows-only, by the way?
I can definitely give you two octets of an IP address through using awk, sed, or using C and bitwise operations. Do I pass? :D
Huh. I'm surpised this works, because $ is not escaped.
https://pubs.opengroup.org/onlinepubs/007904975/basedefs/xbd...