The 101 Uses of OpenSSH: Part II of II
Now it's time to take a step back from all this PK voodoo to discuss a simple feature of SSH that is especially important for scripting: remote commands. So far we've been using the command ssh strictly for remote shell sessions. However, this is merely its default behavior; if we invoke ssh with a command line as its last argument(s), SSH will execute that command line rather than a shell on the remote host.
For example, suppose I want to take a quick peek at my remote system's log as seen in Listing 4.
As shown in Listing 4, the host “zippy” will send back the contents of its /var/log/messages file to my local console. (Note that output has been piped to a local more process.)
Two caveats are in order here. (1) Running remote commands that require subsequent user interaction is tricky and should be avoided—with the exception of shells, ssh works best when “triggering” processes that don't require user input. Also, (2) all authentication rules still apply: if you would normally be prompted for a password or passphrase, you still will. Therefore, if using SSH from a cron job or in other noninteractive contexts, make sure you're either using a passphrase-less key or that the key you are using is first loaded into ssh-agent.
Before we leave the topic of SSH in scripts, I would be remiss if I didn't mention “rhosts” and “shosts” authentication. These are mechanisms by which access is automatically granted to users connecting from any host specified in any of the following files: $HOME/.rhosts, $HOME/.shosts, /etc/hosts.equiv, and /etc/shosts.equiv.
As you might imagine, rhosts access is incredibly insecure since it relies solely on source-IP addresses and host names, both of which can be spoofed in various ways. Therefore, rhosts authentication is disabled by default. shosts is different: although it appears to behave the same as rhosts, the connecting host's identity is verified via host-key-checking; furthermore, only root on the connecting host may transparently connect via the shost mechanism.
By the way, combining rhosts access with RSA or DSA authentication is a very cool thing to do, especially when using passphrase-less keys. See the sshd(8) man page for details on using rhosts and shosts with SSH, with or without PK authentication.
And now we arrive at the payoff (and the section for which I saved room by sacrificing a more complete discussion of rhosts/shosts): port-forwarding. ssh gives us a mechanism for executing remote logins/shells and other commands; scp adds file-copying. But what about X? POP3? FTP proper? Fear not, SSH can secure these and most other TCP-based services!
Forwarding X applications back to your remote console is extremely simple. First, on the remote host edit /etc/ssh/sshd_config and set “X11Forwarding” to “yes” (in OpenSSH version 2x, the default is “no”). Second, open an ssh session using the authentication method of your choice from your local console to the remote host. Third, run whatever X applications you wish. That's it! Needless to say (I hope), X must be running on your local system; if it is, the remote application will send all X output to your local X desktop.
After the xterm & command is issued, a new xterm window will pop up on the local desktop. I could just have easily (and can still) run Netscape, the GIMP or anything else my local X server can handle (and which is installed on the remote host, of course).
X11 is the only category of service that SSH is hard-coded to automatically forward. Other services are easily forwarded using the -L flag. Consider the session shown in Listing 6.
The first part of the ssh line looks familiar: I'm using SSH Protocol v.2 and logging on with a different username (mbauer) on the remote host (zippy) then locally (mick@homebox). The -f flag tells ssh to fork itself into the background after starting the command specified by the last argument, in this case sleep 20. This means that the ssh process will sleep for 20 seconds instead of starting a shell session.
Twenty seconds is plenty of time to start our tunneled FTP session, which is actuated via the magic following the -L flag. -L defines a “local forward”: a redirection from a local TCP port on our client system to a remote port on the server system. “Local forwards” follow the syntax local_port_number: remote_hostname: remote_port_number where local_port_number is an arbitrary port on your local (client) machine, remote_hostname is the name or IP address of the server (remote) machine, and remote_port_number is the number of the port on the remote machine you wish to forward connections to.
Note that any user may use ssh to declare local forwards on high (greater than or equal to 1024) ports, but only root may declare them on privileged ports (less than 1024). Staying with the above example, after ssh “goes to sleep” we're returned to our local shell prompt and have 20 seconds to establish an FTP connection. Note that in Listing 6 I'm using ncftp: this is because ncftp supports the -p flag, which allows me to tell it to connect to my local-forward port of 7777. Note also that I give ncftp the name of my local system rather than the remote host's; ssh will take care of routing the connection to the remote host.
After 20 seconds the ssh process will try to end, but if an FTP session using the local forward is still active, then ssh will return a message to that effect and remain alive until the forwarded connection is closed. There's nothing to stop us from opening a login shell rather than running a remote command (we'll just need to omit the -f flag and then use a different virtual console or window to start FTP, etc.). If we do use -f with sleep, we are not obliged to sleep for exactly 20 seconds—the sleep-interval is unimportant (as long as it leaves enough time to start the forwarded connection).
For that matter, you can run any remote command that will achieve the desired pause, but it makes sense to use sleep because that's the sort of thing sleep is for. One more tip: if you use a given local forward every time you use ssh, you can declare it in your very own configuration file in your home directory, $HOME/.ssh/config. The syntax is similar to that of the -L flag:
LocalForward 7777 zippy.pinheads.com:21
In other words, after the parameter name “LocalForward” you should have a space or tab, the local port number, another space, the remote host's name or IP address, a colon but no space and the remote port number. You can also use this parameter in /etc/ssh/ssh_config if you wish it to apply to all ssh processes run on the local machine.
Those are some of the advanced uses of SSH and OpenSSH. For now I must bid you adieu and refer you to the man pages for further details and still more features. Go forth and encrypt!
- Bruce Nikkel's Practical Forensic Imaging (No Starch Press)
- Transitioning to Python 3
- Progress on Privacy
- Stepping into Science
- Linux Journal December 2016
- Radio Free Linux
- The Tiny Internet Project, Part II
- CORSAIR's Carbide Air 740
- FutureVault Inc.'s FutureVault
- A Better Raspberry Pi Streaming Solution