Take Control of SSH

The Internet was originally developed as a US research project, restricted to academics and the military. As it has become hugely popular and evolved into a critical resource for banking and electronic shopping, the original Internet communications protocols underwent severe strains. The three core "application-level" protocols before the world wide web were 1) telnet (for using remote computers), 2) FTP (file transfer protocol, for moving files between computers), and 3) SMTP (for sending mail -- receiving mail has always used a variety of different protocols).

For the past several years SMTP has been undergoing forced evolution as ground zero in the war between spammers on one side; and ISPs, anti-spam developers, and users on the other. Similarly, the original telnet and FTP protocols are no longer appropriate for today's hostile Internet, because they don't provide any protection against eavesdropping (called "packet sniffing"), particularly of identification credentials used to log into remote computers. Instead of undergoing the kind of metamorphosis SMTP has experienced to grow up into the often-malevolent Interent, telnet has instead been largely replaced by SSH, which offers the same features but blends in security features. Similarly, FTP is being gradually phased out by sftp, a secure FTP alternative included in the SSH suite.

Just as people demand SSL encryption (indicated by the lock icon in web browsers) from web sites to protect their credit card and banking details from identity fraudsters, SSH offers similar protection for logging into and moving files to and from remote computers, as well as flexible tunneling to protect other Internet communications.

http://www.isoc.org/internet/history/brief.shtml

How Much Is Too Much: Secure or Overboard?

Security is always a trade-off, usually giving up some convenience to have better security. Alternatively, you might trade money (pay) for more secure equipment, or spend more time to accomplish a task. It's a truism that the most secure computer is not only not connected to the Internet, but actually switched off. It's also mostly useless, although there are a few high-security applications which actually justify a computer which spend most of its time shut down or disconnected from the outside world.

When devising a security strategy, it's necessary to be secure enough, but also to recognize the point of diminishing returns. If the more secure way to do something takes twice as long, but reduces the chance of a successful attack by 10%, is it worth taking the more secure route? That depends on how long the action takes otherwise, how frequently it occurs, and the initial likelihood of compromise (before shaving away that 10% chance) -- it also depends on how bad a compromise would be. Missile codes and medical research demand stronger protection than everyday email. With encryption it's easy to go overboard, using too much encryption, too many keys/passwords, and too many hoops to jump through. Such problems are often "self-correcting" -- people faced with systems they consider unrealistically complicated tend to ignore them, reverting back to simpler (and less secure) systems, such as personal email accounts, telephones and faxes for communication, or posting passwords on monitors or under keyboards.

With SSH, keep in mind a) what you are protecting, b) who you are protecting it from, and c) how it's legitimately used. Infrequently accessed systems may use long and esoteric passwords, so long as you have confidence in remembering or retrieving the passwords when needed. Systems used on a weekly basis should be reasonably convenient. Daily access should be as quick and unobtrusive as you can safely manage, to avoid wasting time on security. Spend some time considering your requirements and planning how to satisfy them.

The Internet hosts a great many bad actors. The most numerous attacks are automated and indiscriminate; caused by viruses, worms, and trojan horses. They can be quite destructive, but are not personal. To date, such attacks are purely within the domain of the Internet, but as the Internet becomes more all-encompassing, it begins to encompass telephone calls (Skype, Vonage, 802.11-based voice calling), electronic faxing, electronic bank statements, etc. Calling a friend to exchange passwords, or even leaving one on voice-mail, is normally much safer than emailing it, but this line is gradually fading.

At the other extreme, the FBI uses "sneak and peek" warrants to investigate the homes and workplaces of suspects, which could easily include copying hard drives for later analysis. Similarly, several firms have recently lost laptop computers containing large amounts of customer financial data, which would provide a goldmine for identity thieves.

Once again, the key is to pick an appropriate balance point for security versus convenience. Lost or stolen computers are sufficiently common, and enough good encryption tools are available, that it's almost never a good idea to save an unencrypted password. Likewise, modern computers are sufficiently fast (especially compared to the speed of broadband Internet connectivity) that encryption rarely slows down data transfers or interactive responsiveness. For the subtleties, though, you must make your own determination.

Throughout this ebook, I explain the trade-offs, so you can decide whether they are acceptable. As a point of reference, I consider SSH Keychains indispensable, but I'm concerned enough that I put substantial effort into protecting them, including aggressively locking the screen and locking keychains (both automatically and manually), double-encrypting or destroying keys out of my physical possession (such as a laptop in an airport), and restricting my public keys as much as feasible.

Part I: What Is OpenSSH?

OpenSSH is a modern toolkit which replaces several now-inadequate tools with a modern and secure suite. The SSH tools use public key encryption to protect against sniffing, impersonation of both humans and computers, and system break-ins -- whether by amateur vandals, professional criminals, or governments. OpenSSH is a popular and free implementation of the SSH protocols, including ssh (the main program), sftp (for interactive file transfers), scp (for non-interactive file transfers), ssh-keygen (for managing SSH keys), sshd (the SSH server), and several additional supporting programs. OpenSSH is now standard on most UNIX-based systems, including Mac OS X and Linux.

http://www.openssh.org/

SSH History

SSH was originally developed by a Finn named Tatu Ylonen, in response to a password sniffing attack on systems he managed at Helsinki University of Technology (quite near where Linux was born). Ylonen published his SSH ("Secure Shell") software with source code and a non-restrictive license. The software became popular, and gradually changed into a commercial product as it developed. A group of people who wanted an open version started the OpenSSH project, keeping pace with advances in the commercial version, but retaining an open license. A variety of other SSH products are available, most based on one or the other of the two main projects (commercial products are typically based on the commercial ancestor, while free products tend to be derived from OpenSSH). As people used and evaluated SSH, they found serious flaws which inspired a new version (called SSH version 2, or SSH2) to address them. SSH1 remained popular for several years while SSH2 gradually grew in popularity (and availability).

There has been considerable friction over the years between SSH Communications Security (founded by Ylonen to develop and sell his original SSH software) and the OpenSSH project, but compatibility between the two is very good. The major limitation is that OpenSSH's scp is based on the SSH1 specification of scp, which makes it compatible with commercial scp1 (even when OpenSSH is running in SSH2 mode) but not commercial scp2. It's all very obscure, but the impact is that it may be necessary to use sftp instead of scp when communicating between commercial SSH and OpenSSH.

Over time, OpenSSH has become more popular; it's now included as part of Mac OS X, most Linux distributions, and Solaris; SSH Tectia (as commercial SSH is now called) has become correspondingly less common. On Windows, PuTTY and WinSCP (which also does sftp) are both capable and popular. On Mac OS X, Interarchy offers a good GUI with sftp support.

Privacy

As a result of the Internet's fundamental packet-switching architecture, data traveling between two computers normally flows through several others en route. The consequence of this is that there are many computers (mostly owned by ISPs) which "see" our Internet communications. To get a feel for this, you can use the traceroute command. "traceroute www.tidbits.com", for example, shows (at least part of) a path information can travel to www.tidbits.com, including systems belonging your own ISP and several other computers between you and TidBITS. Any of these computers can be configured to record the computers you communicate with, or even to make a copy of all your communications. If this concerns you, the options are either not to use the Internet (increasingly impractical) or to use encryption.

Since interception of communications is basically unavoidable, privacy is maintained by encrypting communications so unauthorized parties are unable to decipher them. There are currently three main tools which are used to provide encryption in multiple different roles: SSL/TLS, SSH, and VPN. SSL/TLS works by encrypting a single client-server connection, such as a web surfer communicating with a web server, indicated by the prefix "https" (for HyperText Transfer Protocol, Secure) in a URL. On the other hand, as described in "For Your Eyes Only: Virtual Private Networks", VPNs encrypt all traffic between a pair of VPN endpoints. In a corporate scenario this is typically all traffic, or at least all important traffic. SSH falls between these two extremes. It's often used to encrypt particular connections, roughly comparable to telnet + SSL/TLS or FTP + SSL/TLS, but SSH's tunneling capability enables it to function as a VPN alternative in many situations.

It's important to realize that no encryption system is perfect. Most modern encryption systems can be "broken" (decrypted by an unauthorized party) by applying sufficient computational power. Even the one-time pad, a so-called "perfect" encryption system, is useless if the attacker can discover the data used as the pad. In more mundane cases, encryption systems are vulnerable to the attacker somehow discovering the key (by finding the sticky note it's written on, subpoena, or discovering either party's key in some other way. The trick is to balance the difficulty of the system appropriately. An unbreakable system that took 5 years to encrypt a message and 5 more to decrypt would be useless. Similarly, a system that took a second to encrypt and decrypt with the password, but only 5 minutes for an attacker to decrypt -- perhaps by trying all of a small set of possible encryption keys -- would have little value.

A good encryption system must be quick and easy for authorized users with the key(s), yet very difficult and time-consuming to break for an attacker lacking the key. As computers get faster and researchers advance the state of the art in software, everything gets faster for both sides. As a result, encryption systems get more demanding over time, and more expensive systems gradually become practical.

Symmetric (Conventional) Encryption

In conventional symmetric encryption, information is protected (encrypted) with a "key" (a number, often derived from a password), which is used to obscure the information so it is not readable without the key. The recipient uses the same key to decrypt the received transmission, restoring the original data ("the plaintext"). The original Data Encryption Standard (DES), developed in 1975, used a symmetric 56-bit key. Due to computational advances, DES is no longer sufficient to stop a determined attacker, who could apply sufficient computing resources to defeat the encryption. In many cases, DES has been replaced by Triple DES, which repeats the DES algorithm to effectively provide 112-bit encryption. The current Advanced Encryption Standard (AES) uses 128, 192, or 256 bit keys.

Symmetric encryption is very effective, but begs the question: how can the sender and receiver agree on the key(s)? In conventional encryption, establishing the key must be done before encryption can provide privacy. Imagine if your address book contained an encryption key for each person you might want to communicate with privately. Further, imagine you had to generate this key, share it exclusively with the other party, keep it on file, and keep it secret from everybody else. It's not a practical scenario. Fortunately public key cryptography has been developed to provide a workable alternative.

http://www.ladlass.com/intel/archives/010256.html

Public Key Encryption

Cryptographers addressed the key exchange problem with public key encryption. In public key cryptography systems such as RSA and DSA (Diffie-Hellman), a pair of linked keys is created. If key #1 is used to encrypt a message, key #2 is required to decrypt it (instead of the original encryption key, as in symmetric encryption); if key #2 is used to encrypt, then key #1 is used to decrypt. One key is kept secret (the "private key") and the other (the "public key") may be distributed without restriction.

[[Sidebar:]]

Burt Kaliski has written a succinct explanation of how the RSA public-key algorithm works, but it's not simple. RSA is based on the fact that exponentiation is much easier (faster) than finding factors of large numbers, just as multiplication is easier than long division, but more extreme. Encryption with the private key is mostly exponentiation, while decryption is mostly root extraction (the reverse of exponentiation), and difficult if you know the key, but very difficult to guess at for someone who does not have the key. rsa, the other public-key algorithm used by SSH, uses discrete logarithms rather than exponentiation.

If I create such a keypair, three useful things can happen. First, I can make my public key freely available, since I don't have to worry who has it -- I can even transmit it as part of protocol establishment, before encryption has begun. Second, people can encrypt messages to me with my public key, knowing that others (even with my public key) cannot read them. And third, people can decrypt messages from me with my public key. Instead of privacy, decrypting a message with a public key provides authentication -- if my public key successfully decrypts a message, the encryptor must have had my private key.

public key cryptography underlies SSH, PGP, all VPN systems, and, SSL/TLS (used, in HTTPS, to secure web sites). Unfortunately, public key cryptography is substantially slower than conventional (symmetric) encryption. To accommodate this, public key cryptography is normally used for initial authentication (identification), and thenceforth to exchange randomly generated symmetric encryption keys. These symmetric keys never outlast a single communications session, so they are called "session keys".

Aside from performance, there are other advantages to this layered encryption strategy. With email, for example, the message itself only needs to be encrypted once (symmetrically). By encrypting the small symmetric key once with each recipient's public key, large messages can be efficiently sent to multiple recipients. This is also how "key escrow" works. Whenever a system with key escrow encrypts something, it always encrypts the symmetric key one extra time, using the escrow public key. This means the government or corporate administrator can use the escrow private key to access encrypted content, just like any other authorized recipient (or the owner, in a "private" system such as PGP Disk). Each recipient decrypts one block of ciphertext with his or her own private key; the rest of the ciphertext (containing the session key re-encrypted for the other recipients) is indecipherable and ignored. Because session keys are short-lived, breaking them is both more difficult (due to less "cyphertext" to analyze) and less worthwhile than breaking encryption keys which are valid for a longer period. Most importantly, there is no need to generate, exchange, and securely retain encryption keys for every pair of correspondents.

Public Key Authentication (Theory)

A disadvantage to any cryptosystem is that it cannot guarantee that the a key is (only) in the possession of the intended parties. If I lose my symmetric passphrase and you get it, you can read all my messages. This is worse in public key systems, because they are so useful for authentication. There are several ways to handle this. One is to have a trusted party ("Certification Authority") vouch that the key belongs to the claimed party; this is common with web sites, and can be checked by clicking on the browser's lock icon, which shows the CA and who it claims possesses the certificate. PGP uses a web of trust, which requires PGP users to personally vouch for each other, and trust their "vouchees" to vouch for others down the line. It's awkward, but effective in the right circumstances.

Because SSH is normally used between a human (running the ssh command) and a computer (running the sshd server), client-to-server authentication (of a human by a computer) is much different than server-to-client authentication (of a computer by a human). Humans may be identified by encrypting/decrypting with their personal public keys, installed by the user or an administrator (in ~/.ssh/authorized_keys) as part of account management. As a bonus, public keys help administrators avoid this all-too-common exchange:

Admin: I'm setting up a temporary password. Please change it to something I don't know, right away.
User: Sure, I will.
Admin: Now. Did you change it?
User: Uh, sure I did.
Admin: I mean it. Did you use the passwd command?
User: What command? password?
Admin: No, passwd. No "O" or "R". Do it now!
User: Um, okay. Drat. It rejected my password.
Admin: Please come up with a better one!
User: Stupid security policy! It doesn't like that one either!

Since users may connect to many computers without each computer having an individual "account" with the user, initial computer authentication is generally delegated to the Domain Name System (DNS). If I ssh to emperor.tidbits.com, I can generally trust the DNS to ensure that I'm connecting to a machine under the control of TidBITS (Adam Engst, according to the whois database). The DNS is not as secure as SSH, but it's the best we can do in many cases. After the initial communication, each SSH client retains a digital "fingerprint" of each server it's communicated with, so it can authenticate the server for future connections. In this way, all communications after the first have a cryptographic guarantee that the server connected to is at least the same as before (assuming, of course, that the keys weren't stolen). Some people pre-populate the known_hosts files with server keys, or check key fingerprints when connecting to new machines, but this is unusual.

In addition to privacy and authentication, encryption also provides tamper protection. If someone modifies the encrypted message (or it's accidentally distorted in transit), decryption will fail.

What Does OpenSSH Do?

The OpenSSH suite directly replaces a whole host of standard Unix tools, including telnet, rlogin, rsh, rcp, and ftp. In addition, OpenSSH can tunnel unencrypted TCP protocols (such as telnet, IMAP, POP, SMTP, HTTP, etc.) inside SSH encryption, to protect otherwise insecure communications when SSL/TLS is not available and VPN is either not available or too much trouble.

The classic telnet program is fairly simple -- it connects to another computer, running a telnet server (normally called telnetd, for "telnet daemon"), and allows the telnet user to log in by typing her username and password; the telnet program then transfers characters back and forth, as if the user was using a physical terminal attached to the remote computer; this can be eavesdropped on by anyone controlling a the client or server, or any computer (router) in between). rlogin, rsh, and rexec are similar, but add an option to login without authentication from trusted IP addresses. On today's Internet, unverified trust is no longer realistic. ssh offers a superior alternative to them all, by encrypting all communications and offering public key authentication, instead of the simple IP-based trust used in the "r-programs".

In addition, scp provides a cryptographic alternative to the old rcp "remote copy" program, based on an encrypted ssh connection, and sftp offers a secure replacement for the old FTP protocol, which is both insecure and difficult to manage through modern firewalls. Like scp, sftp relies on an ssh connection for transport and security.

Part II: Public Key Authentication (Practice)

Private keys are much more secure than passwords (which must be short enough for people to remember and easy to type), but fundamentally they're still large numbers which function as password equivalents. This means that anyone who has your private key can use it to authenticate as you to an SSH server. Files containing private keys (such as ~/.ssh/id_rsa) are therefore as security sensitive as passwords.

On the server side, public keys identify users. If someone can manipulate your ~/.ssh/authorized_keys file, they can insert their own key and impersonate you. To protect against this, sshd ignores authorized_keys files with insecure permissions. Unfortunately, sshd doesn't complain about this in a visible way, so mysterious failures of public key authentication are often traced back to inadequate permissions. The rule is that the ~./ssh/authorized_keys file and all the directories that contain it, up to the root of the filesystem, must not be writable by any account except the owner. File system permissions cannot stop a system administrator from accessing the key files (both private and public, although the private keys should be encrypted), of course. Similarly, anyone with access to the machine or unencrypted backups could copy the key files.

Create a Public/Private Keypair

To get started with public key authentication, first generate a new RSA key in Terminal with "ssh-keygen -t rsa". Let ssh-keygen create ~/.ssh/id_rsa, and provide a good password you will remember, because keys cannot be recovered if you forget your password. ssh-keygen will create ~/.ssh if it doesn't already exist, as well as ~/.ssh/id_rsa (your new private key, encrypted with the provided passphrase) and ~/.ssh/id_rsa.pub (your new public key).

pepperbook:~ sample$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/sample/.ssh/id_rsa): 
Created directory '/Users/sample/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/sample/.ssh/id_rsa.
Your public key has been saved in /Users/sample/.ssh/id_rsa.pub.
The key fingerprint is:
ba:d1:0c:43:93:a8:d5:5a:b8:a2:4b:29:ae:34:ee:3f sample@pepperbook.reppep.com
pepperbook:~ sample$ ls -ld .ssh
drwx------   4 sample  sample  136 Apr  6 00:22 .ssh
pepperbook:~ sample$ ls -l .ssh
total 16
-rw-------   1 sample  sample  736 Apr  6 00:22 id_rsa
-rw-r--r--   1 sample  sample  618 Apr  6 00:22 id_rsa.pub
pepperbook:~ sample$ 

To use the new public key for logging into this account on this machine, copy id_rsa.pub to authorized_keys: "cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys". Test it with "ssh 127.0.0.1". First, you will be asked to accept the public key for 127.0.0.1 (recall that keys are used to identify servers, as well as users); it's then automatically copied into ~/.ssh/known_hosts. Second, you will be asked for the passphrase for your private key, instead of the account password for the remote system (note that the passphrase might be the same same as the account password). Finally, you will get a UNIX shell dmg pt on the "remote" system once the ssh session is established. Log out to terminate the ssh session.

Warning: Some Mac OS X versions suffer confusion between the current IPv4 Internet Protocol and the newer IPv6 protocol; IPv6 enables more computers to connect to the Internet but is not yet in wide use. To avoid these issues, use 127.0.0.1 in commands instead of localhost. They should be equivalent, but are not (at least in early versions of Mac OS X 10.4 "Tiger", and I believe in "Panther" as well). Fortunately, Apple fixed this by 10.4.8, but it caused a lot of confusion before that, and still does for people using older versions.

pepperbook:~ sample$ cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
pepperbook:~ sample$ ssh 127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
RSA key fingerprint is 8a:d3:22:82:f5:2b:88:f0:20:1b:72:bd:aa:30:e0:e2.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (RSA) to the list of known hosts.
Enter passphrase for key '/Users/sample/.ssh/id_rsa': 
Welcome to Darwin!
pepperbook:~ sample$ ls -l .ssh
total 32
-rw-r--r--   1 sample  sample  618 Apr  6 00:23 authorized_keys
-rw-------   1 sample  sample  736 Apr  6 00:22 id_rsa
-rw-r--r--   1 sample  sample  618 Apr  6 00:22 id_rsa.pub
-rw-r--r--   1 sample  sample  219 Apr  6 00:23 known_hosts
pepperbook:~ sample$ exit
logout
Connection to 127.0.0.1 closed.
pepperbook:~ sample$ 

Now that you've confirmed your public and private keys work, it's time to copy authorized_keys to some other SSH servers. First, make sure there's a suitable ~/.ssh directory, next send the file, and then login using the key to confirm it works.

pepperbook:~ sample$ ssh www "mkdir -p .ssh ; chmod 700 .ssh"
The authenticity of host 'www (66.92.104.200)' can't be established.
RSA key fingerprint is 53:66:e9:b5:92:e1:5f:d9:71:fa:87:7b:35:99:f2:d3.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'www,66.92.104.200' (RSA) to the list of known hosts.
Password:
pepperbook:~ sample$ scp ~/.ssh/authorized_keys www:.ssh/
Password:
authorized_keys                               100%  618     0.6KB/s   00:00    
pepperbook:~ sample$ ssh www
Enter passphrase for key '/Users/sample/.ssh/id_rsa': 
Welcome to Darwin!
www:~ sample$ exit
logout
Connection to www closed.
pepperbook:~ sample$ 

Once that's tested, you're ready to copy authorized_keys to more computers. You can also put the id_rsa file on other machines, but be careful with this file! Don't put it on any machines you don't completely trust.

Remember that you can use multiple private and public keys. The id_rsa and id_rsa.pub filenames are just defaults -- keys don't need to have any special names, although agents tend to assume that the public key filename is the private key filename plus ".pub", and may get confused otherwise.

SSH Authentication Agents

So far you've replaced password authentication with public key authentication. This is valuable, because it means someone who controls an sshd server which you log into will not get a chance to steal your password. The way SSH handles plain password authentication (against the built-in UNIX or Windows account databases) is by taking the password typed in and sending it through the ssh connection; at the other end the username and password are decrypted and checked against the remote account's password on file. Both the local ssh program you run and the remote sshd program work with the unencrypted password. There have been major incidents in the past where a popular site (such as SourceForge.net) was broken into, and the crackers recorded all the usernames and passwords used to ssh into SourceForge until people noticed something was wrong. The crackers then used those username/password pairs to log into other sites. It was a colossal mess. Public keys avoid this risk, because the remote system only gets the public key. It doesn't need the private key, and cannot determine it from the public key.

Warning: It is possible to use unencrypted private keys, but this is generally a very bad idea, because anyone who gains access to the private key file (trivial, with physical access to the computer) then controls that identity, and can impersonate or eavesdrop on the owner. About the only time unencrypted private keys are appropriate is for automated tasks, run when nobody is available, if using an agent is not feasible. Such keys should be restricted as much as possible in authorized_keys, and the accounts they access should be restricted as much as possible as well.

Key agents make use of SSH much more efficient, at the cost of a small reduction in security. Agents read encrypted key files; the agent keeps the unencrypted key in memory (never in a file on disk), making it immediately accessible without further decryption or password entry. This makes use SSH dramatically more efficient. Without an agent, connecting to 5 systems 3 times each would require typing one's password correctly 15 times; with a loaded agent, all the connections are automatic. As an example, consider checking a file on several machines. An SSH agent automatically provides the private key for each connection, making large-scale operations quick and convenient.

The risk in using an agent is that anyone who can control the agent or its socket (such as a root user) can use it to authenticate, although the private keys themselves are not available directly from the agent. This makes agents (and agent forwarding) unsuitable for use on untrusted machines.

SSHKeychain

On the Mac, SSHKeychain is an excellent SSH agent. It can automatically load keys when needed, forgetting them when the system sleeps. SSHKeychain is accessible through the Dock or the SSHKeychain menu, and integrates with Apple's Keychain, optionally automatically loading and unloading SSH keys as the Apple Keychain unlocks and locks, and it works with other SSH-supporting programs such as BBEdit.

Once you've created and tested your private/public keypair, there are several simple steps to activate SSHKeychain.

  1. Open SSHKeychain.dmg to mount it.
  2. Install SSHKeychain (I just dragged SSHKeychain.app into /Applications).
  3. Unmount SSHKeychain.dmg.
  4. Open /Applications/SSHKeychain.app.
  5. Configure SSHKeychain's preferences (accessible from the new SSHKeychain menu on the right side of the menu bar); the critical parts are to enable "Manage (and modify) global environment variables", and configure specify your private keys if you used nonstandard filenames.
  6. Use Agent > Add All Keys from SSHKeychain's menu to confirm it can load your encrypted keys, and that now you can ssh into systems without entering a password. If you check "Add passphrase to the Apple keychain", SSHKeychain will no longer prompt you for the key's passphrase, although it may prompt to unlock your keychain to retrieve the key's passphrase.
  7. Set SSHKeychain to run automatically (I control-clicked on its Dock icon and set Open at Login).
  8. From now on, whenever you log into Mac OS X, SSH programs will use SSHKeychain for key management.

The SSHKeychain menu shows either of two icons. When it has one or more keys loaded, it shows a keyring with three keys. When it doesn't hold any keys, the ring is missing, but the keys are still shown.

There are a couple bugs in Mac OS X 10.4.x's authentication and the Apple Keychain. In theory, unlocking the screensaver should unlock the user's default keychain (if it uses the account's login password, which is Apple's default configuration), but this doesn't work properly. Additionally, while a keychain is unlocked, the system does not need to prompt the user to "unlock" that keychain again until it's re-locked, but this is also broken -- Mac OS X prompts to "unlock" keychains that are already unlocked.

In reality, if the system is running with the screensaver and Keychain locked, applications tend to bring up their own Keychain dialogs behind it. Unlocking the screensaver or the Keychain does not dismiss these dialogs. The upshot is that, with SSHKeychain set to lock the Apple Keychain on screen activation (its default behavior), unlocking the screensaver may reveal multiple Keychain dialog boxes which must each be addressed individually. With .Mac synching set to Auto, I often saw three authentication dialogs when I unlocked the screensaver.

As a partial workaround, open Keychain Access, create a new keychain (I called mine "lowsec"), select the new keychain, and use "Edit > Change Settings for Keychain "lowsec" to disable locking entirely for this keychain. Then go back to your main (login) keychain, and move the ".Mac password" item (its name will be your .Mac username) from the main login keychain into the new one. Additionally, enable "Use custom security settings" in SSHKeychain, and set "On screensaver:" to "No action". With this configuration, the lowsec keychain will be unlocked once at login time and then available until logout or reboot. For higher security I set my main login keychain to automatically lock after 30 minutes of inactivity. Ideally, both Keychain Access and SSHKeychain would allow locking specific keychains when the screen locks, leaving other keychains unlocked, but this is not currently implemented.

Key Restrictions and Forced Commands

It can be very useful to provide restricted access to an account. In SSH, this is possible by adding restrictions to specific keys in authorized_keys. Some of the possible restrictions include disabling interactive login; restricting agent, X11, or port forwarding (tunneling); and specifying a "forced command", which is always run when the associated key is used, regardless of what is requested by the ssh client. These restrictions are particularly useful for non-interactive tasks such as backup scripts. Such tasks may require SSH connectivity with unencrypted private keys, which should not provide unrestricted ssh access.

Note that multiple keys may provide access to the same account. This is handy for people sharing single accounts, or for using special-purpose keys with different forced commands. For more information on key restrictions and forced commands, see the "AUTHORIZED_KEYS FILE FORMAT" section of the sshd manual page.

Public keys can be further restricted by allowing access to carefully circumscribed accounts; unencrypted public keys which give access to "real" user or root accounts should be avoided as much as possible.

Raising the Bar: Requiring Stronger Security

There are several ways to protect a server against ssh-based attacks, including firewalls, TCP Wrapper, not creating or distributing UNIX passwords (forcing ssh public key authentication), and disabling password access for all accounts or the root account. To read about using firewalls and TCP Wrapper with ssh, please vote for Take Control of SSH on the Take Control suggestions page.

UNIX passwords present several problems for administrators. What legitimate users can remember and type (generally considered to be 8 letters and numbers) is a small enough range of possibilities for attackers to try all possibilities. "Account lockout" is a feature of some systems (including Mac OS X Server) to disable accounts after several failed guesses -- which often identifies an attack. Unfortunately, this means legitimate users get blocked when their accounts are attacked, and locking legitimate users out of their own accounts is a successful attack (although not as serious as gaining illicit access). System administrators would often prefer to avoid this by not allowing password access at all. On Mac OS X, it is difficult to set up an account without a password; it's easier to create a long random password (12+ characters -- Keychain Access can do this for you), and never write it down or give it to the account user, requiring public key authentication or some other high security authentication (such as smart cards) instead. On other systems, it's easy to simply not set UNIX passwords for accounts (although there are complications).

OpenSSH has its own features to help force users to use public keys, blocking password guessing over the Internet. If you have enabled the root account (which is technically accomplished by setting a password for it), you should definitely set "PermitRootLogin without-password" in /etc/sshd_config; this will prevent people from breaking into the root account by guessing its password -- an amazingly common and disturbingly successful Internet attack. Even better, set "PasswordAuthentication no" to prevent sshd from accepting passwords for any account -- thus requiring keys for ssh access.

Part III: Basic Usage

OpenSSH has three main programs: ssh, scp, and sftp. OpenSSH uses a directory named .ssh in the user's home directory (~/.ssh) for personal SSH files. System files either reside in /etc/ (under Mac OS X) or /etc/ssh/ (on most other systems). To enable logging into a Mac via SSH, open System Preferences, click on Sharing, and check the Remote Login item. This activates sshd (the ssh server, or "daemon").

ssh

ssh is the main (and most flexible) program in the OpenSSH suite. It establishes interactive connections to remote systems, issues remote commands, creates tunnels, and provides encrypted communications for other programs to leverage, replacing telnet, rsh, rlogin, and rexec.

"ssh myserver": log into myserver via SSH.

scp

scp is SSH's non-interactive file transfer program; it replaces rcp, which is itself modeled upon the basic cp (copy) command. In scp and rcp, a colon is used to separate the host and file path.

For example, "scp ~/.ssh/id_rsa.pub myserver:.ssh/authorized_keys" copies my public key to myserver, and installs it as the authorized key. Once it's installed, I can login without using the UNIX password on myserver. This command replaces the existing authorized_keys file on myserver, replacing any public keys previously in the file. Adding keys to an existing file is better done with copy and paste, or by appending to a file with ">>".

scp also supports copying files from one remote host to another. In this case, the local scp command actually sends an scp command to the source host, telling it to copy from the source to the destination host. This may break in unexpected ways, as the source checks the host key of the destination host, and the destination host checks the source host against its own IP restrictions (see TCP Wrapper, below). In case of trouble, the workaround is to simply scp the file from the source host to the local system, and then scp it to the destination system with a separate command.

Note: OpenSSH's scp implementation is incompatible with scp2 from ssh.com. If you run into this problem, the workaround is easy: just use sftp instead.

sftp

sftp is the suite's interactive file transfer program, offering a replacement for the venerable ftp. It is designed to emulate the ftp command-line interface, using ssh to provide secure client-server communication. Notably, sftp does not use active or passive mode, instead running entirely through port 22. As a result, sftp is much easier for network administrators to support. Additionally, the server does not provide ASCII mode transfers (line break transformations), although clients may. And of course, sftp is much safer because it does not transmit passwords or data unencrypted. Unfortunately, there are a wide variety of attempts to make ftp secure, all using similar names, and confusion as a result. In particular, sftp is totally incompatible with ftp, ftp-in-ssh (provided by some versions of Interarchy), FTP/SSL, and all "FTPS" programs.

OpenSSH's sftp is very flexible. To begin an sftp session, try "sftp myserver". This will log into myserver, starting in the remote home directory. If you'd like to start in another directory, use a command such as "sftp myserver:/etc", which instead starts in the /etc directory on myserver. If you specify a relative path (without leading slash), such as "sftp myserver:.ssh", it is relative to your home directory. This syntax is copied from scp and rcp.

Once logged into the remote host, standard ftp-style commands are available, including help, get, put, exit/quit, ls/lls, pwd/lpwd, and cd/lcd. On the other hand, many people prefer to use graphical sftp clients. Fortunately (and partially because sftp deliberately mimics ftp), a wide variety of clients is available. On the Mac, Interarchy is very good; on Windows, WinSCP is good. VersionTracker offers a wealth of alternatives.

[[Duplicates]]

Use a Different Account

On my own systems, I use the username pepper (Apple calls this a "short name"). On some other systems, I have a different username. By default, SSH attempts to log into remote systems with the username used on the local system. There are a couple ways to handle discrepancies between local and remote usernames on an SSH command line. "ssh user@host" logs into host as user, as does "ssh -l user host". This syntax, like most options, also applies to both scp and sftp.

For frequently accessed servers, the username can be set permanently by creating the file ~/.ssh/config and adding a couple lines to it. OpenSSH programs automatically use the username specified here if it exists. The example's asterisk is a wildcard, so it matches tidbits.com, www.tidbits.com, emperor.tidbits.com, etc.

$ cat ~/.ssh/config 
Host *tidbits.com
  User reppep

Debugging: Get More Information

When you are having trouble with an SSH program, it's helpful to see diagnostic information. Adding a -v to most SSH commands (including ssh, scp, and sftp) shows a great deal more information about the command's progress. Most of it is unintelligible, but some bits are very useful. I tend to make two connections, one which succeeds and another that fails, so I can compare them.

For example, "ssh -v myserver" logs into myserver with progress messages. -vv and -vvv provide even more verbosity. I often do something like the following:

  1. In Terminal: Type Command-K to clear the window and scrollback buffer.
  2. In Terminal: Run a SSH command that works, as similar as possible to the one that fails, with -v.
  3. In Terminal: Select All, then Copy
  4. In BBEdit: Paste
  5. In Terminal: Type Command-K.
  6. In Terminal: Run the SSH command that fails, with -v.
  7. In Terminal: Select All, then Copy
  8. In BBEdit: Paste
  9. In BBEdit: Select Search:Compare Two Front Documents

BBEdit will then highlight the differences between the successful and failing commands. If you don't have BBEdit, just paste into another text editor, or use two shell windows lined up alongside each other. To compare two files in Terminal, type "diff -u ", drag the two files into the Terminal window to enter their paths on the command line, and hit Return.

The SSH server (sshd) can also run verbosely. The simplest way to accomplish this is to add "LogLevel VERBOSE" to /etc/sshd_config, and then restart sshd (Remote Login) from System Preferences:Sharing:Services. When done testing, remove or comment out LogLevel and restart sshd again. Several other server logging levels are available; for details, see LogLevel in the sshd_config manual page.

known_hosts

OpenSSH uses the file ~/.ssh/known_hosts to keep track of all the servers it has contacted (OpenSSH also uses /etc/ssh_known_hosts, if it exists). Each sshd server needs one or more pairs of private/public keys to identify it; these are called host keys, and they serve a similar role to user private/public key pairs. Because private keys are used as the basis for cryptographic identification, they must be protected with appropriate permissions. The known_hosts files hold only public keys, so they don't need to be kept secret.

By default, OpenSSH warns whenever it encounters a host key that does not match an existing known host key. When contacting a new server for the first time, the message looks like this:

pepper@pepperbook:~$ ssh www.openssh.org
The authenticity of host 'www.openssh.org (129.128.5.196)' can't be established.
RSA key fingerprint is 20:ad:fa:70:cf:85:54:9d:ee:7f:6c:a3:98:77:94:4e.
Are you sure you want to continue connecting (yes/no)? no
Host key verification failed.
pepper@pepperbook:~$ 

If you answer yes, the key is added to known_hosts, and that future connections will silently accept that key from that host. If ssh ever receives a new key from a host, which doesn't match a key already on file, it displays a much more alarming warning:

pepperbook:~ sample$ ssh www
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
53:66:e9:b5:92:e1:5f:d9:71:fa:87:7b:35:99:f2:d3.
Please contact your system administrator.
Add correct host key in /Users/sample/.ssh/known_hosts to get rid of this message.
Offending key in /Users/sample/.ssh/known_hosts:2
RSA host key for www has changed and you have requested strict checking.
Host key verification failed.
pepperbook:~ sample$ 

There are two explanations for the mismatch. Most likely something was upgraded or reinstalled, and the SSH host keys were regenerated. If this is so, a quick check with the system administrator will confirm that it's safe to edit ~/.ssh/known_hosts and remove the offending key, conveniently identified by line number -- "/Users/sample/.ssh/known_hosts:2", above, means line 2 (with wrapping off).

The other possibility is the reason for the warning. It could appear if the ssh server was subverted -- either replaced by another machine to record submitted passwords and other information, or modified for the same purpose. This is less common than upgrades, but quite possible (I've seen it once, and the people who ignored the warning felt pretty stupid afterwards. ssh-keygen can display the fingerprint of a key file -- fingerprints are a quicker way to compare keys than comparing the full keys, which are several hundred characters each.

Use BBEdit and bbedit

BBEdit has good SSH support, starting with the sftp client Bare Bones built into BBEdit (File:Open File from FTP/SFTP Server). Alternatively, the included bbedit command-line tool can be used to edit files via sftp, or to receive files piped in from other programs, including ssh. BBEdit works well with SSHKeychain.

Remote Commands

One of the simplest ssh tricks is remote command execution. Rather than logging into a computer, issuing a single command, and then logging out, it's also possible to include a command on the ssh command line. ssh will then execute this command on the remote machine and return the results. For example, to see if the server www has rebooted recently, use "ssh www uptime". To see www's hostconfig file, use "ssh www cat /etc/hostconfig". To find out if www normally runs an AppleShare server, use "ssh www grep AFPSERVER /etc/hostconfig".

I'm fond of reviewing long files such as logs in BBEdit this way, to review remote files and manual pages (when I need to see the Linux or Solaris syntax, for example). I use something like "ssh www man shutdown | col -b | bbedit".

Remote commands work best with public keys, so entering a password doesn't bog the process down. Further, it becomes feasible to execute the same command across a set of remote machines. The dsh perl script streamlines this process. dsh is intended for use in Beowulf clusters -- groups of Linux machines all sharing computation workloads -- but it is also extremely useful for general system administration across multiple systems.

Part IV: Advanced Tricks

Compression

There are several factors which control the speed of SSH connections:

If either computer is slow or overloaded, compression will slow things down as it requires that computer to work even harder to (de-)compress the data. On the other hand, if any part of the network connection between the two computers is slow (perhaps due to a long wireless link, or a low-speed ADSL circuit, or cable or DSL service with low upstream bandwidth), using compression can reduce the amount of traffic going through the slow link, and make SSH faster. To use compression, add -C (capital 'C') to the ssh command line.

Tunnel X11

The X Window System, used for displaying graphics on UNIX/Linux systems (including Mac OS X, via Apple's optional X11 package), includes (unencrypted) network support, meaning passwords and other data can be intercepted. To address this, OpenSSH can automatically tunnel X11 sessions alongside ssh login sessions. X11 defines the DISPLAY variable to identify the X11 display to use; if it is set before an ssh session is established, ssh can automatically create a virtual DISPLAY on the remote system, and connect it through an ssh tunnel to the local DISPLAY. This means X11 "just works" automatically over ssh, as long as "X11Forwarding yes" is set in sshd_config on the server, and "ForwardX11 yes" is set in ssh_config on the client ("ForwardX11Trusted yes" may also be required for use of certain X11 applications, such as Red Hat's administration tools).

To set this all up on a Mac, configure sshd_config & sshd_config, then go to System Preferences:Sharing:Services, turn off Remote Login if it was on, and turn it back on to restart sshd with the new settings.

A common problem with X11 tunneling is explicitly setting the DISPLAY variable on the remote machine, which disconnects X11 from the ssh tunnel. People often set DISPLAY in their shell initialization files, and later forget it's there.

Authentication Agent Forwarding

It may not be possible to ssh directly into the desired computer. If it's necessary to go through an intermediate system before reaching the intended destination, it's very useful to still have access to encrypted keys on the original client for connecting to the eventual destination, even though the client with the keys cannot directly contact the final destination. ssh supports this with authentication agent forwarding.

For example, I might be at home, using a machine named client with SSHKeychain running, and need to reach destination at work, but prevented from connecting directly from client by a corporate firewall. If I can ssh into another machine (call it gateway) from client, I can then ssh from gateway to destination. It may not be a good idea to keep my private keys or run an authentication agent on gateway, and password authentication is less secure (if it is even allowed on destination). By setting "ForwardAgent yes" in the ssh_config file on client (or using "ssh -a gateway", to enable forwarding for a single connection), I can instruct client to handle indirect authentication requests, passed back along the ssh chain from destination through gateway. For most people this will never be necessary, but when using public key authentication across partitioned networks, agent forwarding improves both security and convenience.

Use a Different Port

ssh, scp, and sftp all work by communicating with sshd, the SSH server. Normally, sshd listens on TCP port 22, and all SSH communication goes through that port. It's fairly simple to run SSH on a nonstandard port, should that prove necessary (most likely to co-exist with another sshd already using on port 22, or perhaps through an ssh tunnel.

To move sshd onto a different port, set the Port directive in /etc/sshd_config and restart sshd. To access sshd on a different port, use ssh -p port, scp -P 2222, or sftp -oPort=2222, as needed.

Tunnel (VPN Lite)

A VPN (Virtual Private Network) works by passing most or all Internet traffic through an encrypted tunnel, to protect traffic in transit. OpenSSH offers several types of tunnels. "ssh -L" securely connects a local port (on the client) to a remote port (accessible from the server). This is useful in a wide variety of scenarios, when a network connection doesn't inherently provide sufficient security, such as X11, POP, SMTP, VNC, etc.

Despite VPNs' greater simplicity and coverage, SSH tunnels offer one important advantage. With a VPN, everything between the endpoints (typically a laptop or home desktop, and the VPN gateway) is encrypted. This means that traffic from the VPN gateway to the actual server is typically unencrypted. Since sshd typically runs on the server itself, unencrypted traffic between the VPN gateway and the server is avoided.

Note: UNIX systems (including Mac OS X) require root-level access to listen for incoming connections on low ports (below 1024). As a result, some tunnels require administrative access (managed by sudo in Mac OS X) to establish. Additionally, ssh with sudo is a bit odd, because sudo uses the root account to actually run the ssh command. As a result, ssh attempts to log into the remote root account unless otherwise specified, and uses ~root/.ssh/known_hosts instead of the regular user's known_hosts.

pepperbook:~ sample$ ssh -L 1023:127.0.0.1:110 www
Privileged ports can only be forwarded by root.
pepperbook:~ sample$ ssh -L 1024:127.0.0.1:110 www
Enter passphrase for key '/Users/sample/.ssh/id_rsa': 
Welcome to Darwin!
www:~ sample$ logout
Connection to www closed.
pepperbook:~ sample$ 

Because the ssh connection is carrying tunneled traffic, if a tunnel is still in use after exiting from the main remote shell, ssh will remain connected to maintain the tunnel. Once the tunnel is no longer in use, ssh exits and returns to the local shell. It's also possible to create a tunnel without establishing an interactive login session; in this case, the options "-aNTx" may be appropriate; see the ssh manual page for details.

If you SSH through an existing tunnel, ssh may complain because the sshd on the other side of the tunnel has a different host key than is found in ~/.ssh/known_hosts. The short-term fix is to edit ~/.ssh/known_hosts and remove the entry for 127.0.0.1 or localhost, but a better option is to add NoHostAuthenticationForLocalhost yes to /etc/ssh_config, so the host key will always be ignored when connecting to 127.0.0.1.

Note that Mac OS X has some confusion between IPv4 and IPv6. To avoid problems, use 127.0.0.1 with SSH, instead of localhost, which should be equivalent, but is sometimes interpreted as an IPv6 address instead.

Tunnel VNC (Including Apple Remote Desktop 2)

VNC servers normally listen on a TCP port in the 5900-5999 range. Apple Remote Desktop 2 is VNC-compatible, and listens on 5900 when enabled (make sure System Preferences:Sharing:Services:Apple Remote Desktop is checked). Assuming ARD2 is running on both the client and server, the client side of the tunnel must run on another port, since 5900 on the client is already in use by the local copy of ARD2. I use something like "ssh -C -L 5901:127.0.0.1:5900 www" to open a new listener (fake server) on client port 5901. Everything sent to this port is encrypted and redirected to port 5900 on the ssh server (www). Once this is established, I use Add by Address, under the "+" button-menu in the main Remote Desktop window, and enter "127.0.0.1:5901" in the Address field for the new computer entry. When using this entry, ARD2 will actually communicate with the server's ARD2 agent through the tunnel.

http://docs.info.apple.com/article.html?artnum=106439

Tunneling VNC (including ARD2) offers several advantages. First, it protects all VNC traffic across the network. The VNC protocol only encrypts the initial login, not the actual keyboard/display/mouse traffic. This means authenticating to programs through the server, including unlocking a screensaver, using sudo, or authorizing programs such as Server Admin and Workgroup Manager, provides opportunity for crackers to steal passwords. Second, it is possible to not expose the raw VNC port to the Internet, using a custom firewall configuration or OSXvnc's option to listen only on the loopback interface (127.0.0.1/localhost). This means attackers scanning the Internet for VNC servers won't even see it, and further protects VNC access with SSH authentication.

Unfortunately, Remote Desktop doesn't offer complete functionality through an ssh tunnel (although plain VNC through a tunnel is completely functional). Fortunately, ARD2's one-to-one remote control is TCP-based and tunnels well. On the other hand, its one-to-many features use UDP ports, and cannot currently be tunneled.

http://docs.info.apple.com/article.html?artnum=300838

screencapture (VNC Alternative)

Mac OS X includes screencapture, a handy command-line utility for recording the contents of the screen. If you're connected via ssh, and want to see what's going on in the graphical environment without running a full VNC session, it's fairly easy to take a screenshot and download it to your client. After logging into server ("ssh server"), use something like "screencapture capture.png" to take a screenshot on server. Then from the client, use something like "scp server:capture.png ~" to download the screenshot to the local home directory, and perhaps "open ~/capture.png" to view the file.

Full VPN (not yet available on Mac OS X)

OpenSSH 4.3 introduces an experimental full VPN feature, which should offer comparable functionality to IPsec VPN (although it may never be as fast). This should be extremely useful when it becomes available on Mac OS X. As of the OpenSSH 4.3 release, however, full VPN is not supported on Mac OS X.

Reverse Tunnel (Meet in the Middle)

This is a somewhat strange but very powerful feature. One of the problems with modern-day networking is that most computers are protected behind firewalls and/or Network Address Translation (NAT), meaning it may not be possible to connect directly to the computer you want to reach. For example, I sometimes want to remotely control my father's PowerBook to help with a problem, but he has a private dynamic address, behind an AirPort Extreme base station which itself has another dynamic address and provides NAT. Even if my father told me his IP address and his base station's address, I wouldn't be able to reach his PowerBook. Reverse tunneling works around this by allowing him to "project" a tunnel to another computer. If I can reach that computer, the tunnel connects back to his computer. Because he establishes the reverse tunnel from his computer as a client, he doesn't have trouble with (Network Address Translation) NAT, and he doesn't even have to know his own IP address. For reverse tunneling to work, my father and I both need access to a computer running sshd. In this example, my PowerBook is called pb, his is called dad, and the server is www.reppep.com.

Note that reverse tunneling provides access to the tunneling computer, and so could be a violation of network security policies. The tunnel is restricted (only accessible from the gateway computer, or other systems with access to it), but it is important to check with the network administrators before implementing a reverse tunnel. In addition, reverse tunneling is fairly complicated. A simpler option is to make SSH directly accessible, but unfortunately this often cannot be arranged. See below for more on configuring dynamic DNS and firewalls for direct SSH access.

To use Remote Desktop through a reverse tunnel and an intermediate system, there are several steps (this can be simplified if the client is directly on the Internet and accessible via ssh). There might be as many as 3 separate encryption/decryption cycles in this scenario, but performance is generally decent.

These instructions were originally written for Apple Remote Desktop 2, but apply equally to Remote Desktop 3. Generally, I strongly suggest connecting with Remote Desktop 3's "Encrypt all network data (more secure)" option, but in this case it doesn't do quite what is needed, and would only add a redundant extra layer of encryption.

  1. On the computer to be controlled (dad in this example), make sure Apple Remote Desktop is enabled in System Preferences:Sharing:Services.
  2. On the computer to be controlled (dad), open a couple ports on the server and point them at the ssh and VNC servers on dad, by typing the following into a Terminal window. The sleep command ensures the tunnels will be accessible for at least an hour -- they stay open automatically while in use:
    ssh -R 6900:127.0.0.1:5900 -R 6922:127.0.0.1:22 www.reppep.com sleep 3600
  3. On the machine running Remote Desktop.app (pb in this example), set up tunnels to those ports on the server:
    ssh -C -L 6900:127.0.0.1:6900 -L 6922:127.0.0.1:6922 -o HostKeyAlias=dad www.reppep.com
  4. Now you can log into dad with:
    ssh -p 6922 www.reppep.com
  5. Alternatively, you can connect to 127.0.0.1:6900 with Remote Desktop (or port 6900/display 1000 in a VNC client), and control dad.

Note that if the firewall in Mac OS X (non-Server) is on, and any services are enabled in System Preferences:Sharing:Services, the appropriate network ports are automatically opened in the firewall, accessible to the entire Internet; this is overly exposed. OpenSSH can be restricted with TCP Wrapper; the Apple Remote Desktop agent (which is a VNC server at its core) cannot; VineServer has an option to only listen on the loopback address, so external hosts cannot connect -- or even detect the presence of a VNC server -- without first establishing an ssh tunnel.

http://www.redstonesoftware.com/products/vine/server/

To make this easier for my father, I made sure he uses the same login name on www.reppep.com as on dad, and I gave him a double-clickable file (ssh-tunnel.command) to run step #2 (the part he has to do each time I'm going to help him), in his Dock, to establish the ssh tunnel. Files ending with .command are automatically executed by Terminal when opened in Mac OS X.

To see what TCP ports are accepting connections, use "netstat -an | grep LIST". Step #2 creates tunnels on the server's ports 6900 & 6922 (connected back to dad), and step #3 opens the same port numbers on the client (pb), tunneled to the server.

When tunneling ssh connections through ssh, the ssh program tends to show a "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!" alert, because ssh gets confused about which ssh server it's connecting to. The cause was addressed earlier, in the known_hosts section. The short-term fix is to edit ~/.ssh/known_hosts and remove the entry for 127.0.0.1 or localhost, but a better solution is to add NoHostAuthenticationForLocalhost yes to /etc/ssh_config, so the host key will always be ignored when sshing to tunnels on localhost. If you do not want to edit either file, the warning can be avoided for a single connection by adding "-o HostKeyAlias=realhost to the ssh/sftp/scp command line, where realhost is the remote ssh server, which is providing the host key for the tunneled ssh connection. It's all somewhat obscure.

Dynamic DNS (Reverse Tunnel Alternative)

If you have a single computer, directly plugged into your cable or DSL modem with DHCP, without NAT or an intervening firewall, reverse tunneling may be unnecessary. If the Mac is directly accessible, but does not have a static IP address, dynamic DNS is a much simpler option. Dynamic DNS servers provide stable DNS hostnames for computers with variable IP addresses, using a DDNS software agent which notifies the DDNS servers of the new IP address each time the computer acquires a new address. The DDNS servers then change their records to reflect the new IP, so a certain domain name (such as stevejobs.dyndns.org) always points to the computer's current address. This works very well for accessing home systems, including via SSH and AFP-over-TCP (AppleShare). DynDNS is one popular DDNS provider, offering both free and paid services.

http://www.dyndns.com/

Firewall Configuration (Reverse Tunneling Alternative)

Most home routers/firewalls, such as Apple's AirPort base stations and the popular Linksys WRT54G, are configured by default to allow connected computers full access to the Internet (including web browsing and email), but to block all "inbound" access to these computers from the rest of the Internet. In order to run Internet-accessible services (including sshd) on a computer behind such a router/firewall, some configuration is required. Note that this is a simpler alternative to the reverse tunneling described above, and doesn't require manual establishment of the reverse tunnel before use. Unfortunately, there are two issues with direct SSH access through a router/firewall. First, it makes the sshd server easier to find and attack from the Internet. Second, it requires control of the router/firewall and DHCP server (often the same device). On a managed network, such control is typically unavailable, and direct SSH access (or a reverse tunnel) might violate the security policy.

SSH normally runs on port 22, and if Remote Login is enabled in System Preferences:Sharing:Services, port 22 is automatically allowed through the Mac OS X (client) firewall. Most home access points (routers) use NAT to provide security; on these SSH must be enabled on the router as well. For example, in the Linksys WRT54G's administrative web interface, under Applications & Gaming is a Port Range Forward tab. On mine, Application ssh, range 22 to 22, Protocol TCP, is forwarded to IP Address 10.10.10.21, and Enabled. When I used an AirPort Express as my router, I mapped Public Port 22 to Private IP Address 10.10.10.21 and Private Port 22.

Note that the computer running sshd must use the IP configured above; it cannot use a random DHCP address, or the port forward may not point anywhere. The easiest way to accomplish this is to set the Mac to Configure IPv4: Manually, but this causes trouble when traveling, because 10.10.10.21 may not be available or even valid on foreign networks. My solution was to configure static DHCP, so when the PowerBook is at home, it always gets the 10.10.10.21 IP. Unfortunately, this isn't available on any AirPort base stations, or in the WRT54G as shipped by Linksys; I had to load third-party firmware to gain static DHCP capability. Static DHCP is available in Mac OS X Server.

Another limitation of this NAT port forwarding is that typically port 22 can only be forwarded to one machine. The common workarounds are a) , or ssh into the single forwarded computer, and then ssh again to other private machines, or b) to run sshd on a nonstandard port on all computers but one, so they don't conflict and all the SSH ports can be mapped through to the appropriate machines. In Mac OS X 10.4.x (Tiger), the sshd port can be overridden in /System/Library/LaunchDaemons/ssh.plist.

Create aliases for common actions

One of the most useful SSH tricks is actually a simple shell feature called aliasing. Aliases are abbreviations or shortcuts for commonly-used commands and actions, which avoid repetitive typing (and typos). Aliases for common actions can take some of the typing out of using SSH. The problem with aliases is that there are many different ways to configure them, depending on the shell, the login method, and what shell customizations have previously been done. First decide what you'd like to alias, then figure out which file alias customizations should reside for your shell and configuration. Here are some examples for the bash shell; they normally go in ~/.bashrc, ~/.profile, or ~/.bash_login. For tcsh, remove the equals sign in the alias command, and put the commands in ~/.login, ~/.cshrc, or ~/.tcshrc instead. The first three examples are partial command lines -- type the alias and then the desired host (e.g., "stard www.reppep.com"). The server name is embedded in the last five examples.

alias  sv="ssh -v"
alias  sp="ssh -l pepper"
alias stard="ssh -C -L 5901:127.0.0.1:5900"
# Create compressed tunnel to ARD2

alias  rj='time rsync -v --archive --delete --exclude=.DS_Store /juke/ othermac:/juke/'
# rsync /juke to another machine via ssh
alias  sw="ssh www.tidbits.com"
alias stw="sudo ssh -C -L 25:127.0.0.1:25 pepper@www.tidbits.com"
# Create compressed tunnel to www.tidbits.com for SMTP
alias stwh="ssh -C -L 1025:127.0.0.1:25 pepper@www.tidbits.com"
# Create compressed tunnel to www.tidbits.com for SMTP
alias  sf="sftp pepper@www.tidbits.com"

With the SMTP tunnel established by stw, a mail client can be configured to use 127.0.0.1 as its SMTP server, and the mail will flow through the ssh tunnel. This is useful when roaming with ISPs that block outbound port 25, although using port 587 for SMTP is generally preferable. Alternatively, stwh skips the sudo, and requires the mail client to use port 1025 on 127.0.0.1 instead of port 25 (the default).

rsync

In addition to TCP tunneling, ssh can be used as a transport for other programs. For example, rsync can run over a ssh connection between two machines, to synchronize files or directories. This enables rsync to work securely without building encryption and authentication into the rsync program itself -- it simply leverages ssh. For more information, see the rsync manual page ("man rsync"), particularly the discussion of its --rsh/-e option, which can also be controlled with the RSYNC_RSH environment variable. Do not use "ssh -C"; rsync can achieve better compression with its own --compress/-z option.

Restrict Access to sshd (Firewall & TCP Wrapper)

Hunting for vulnerable SSH servers (sshd) is a popular pastime on the Internet. Many computer break-ins are accomplished by trying simple or random username/password combinations until a weak password is found. This type of attack can be blocked with a firewall that only allows ssh connections from trusted IP addresses, but there are complications.

In Mac OS X (non-Server) with the firewall active, enabling any service in System Preferences:Sharing:Services (including Remote Login), automatically opens the corresponding port(s) in the firewall to the entire Internet. This wide-open configuration may be too permissive. For tunneled services (such as VNC, which Apple calls Apple Remote Desktop), the port need not be open in the firewall at all, since the data flow is entirely through an SSH connection. It's not necessary to worry about this, but TCP Wrapper can substantially improve security for users with sshd (Remote Login) enabled.

Tips for locking down Mac OS X services with TCP Wrapper and/or the firewall:

  1. Most computers have dynamic IP addresses, and are automatically assigned an address from a block of IPs, but even a large block of IPs is a small fraction of the Internet's whole IPv4 address space.
  2. Computers on cable or DSL connections may have very large ranges of possible addresses, and ISPs do not normally publicize the address ranges assigned to their customers. Support representatives may not have this information available (or even know what it is), although whois IP-address should provide a useful hint (particularly the CIDR entry, if present).
  3. Mac OS X (except for the Server versions) does not provide any configuration for enabled services -- they're automatically open in the firewall.
  4. Foresight is required. When traveling, or using a new IP address, the address must be allowed in advance, since it's not possible to ssh in and make changes from a disallowed address.
  5. It's important to be careful when changing access restrictions on remote machines, since it can be impossible to remotely fix a mistake which blocks access. A trick for TCP Wrapper is to open one connection, make the change, and then test with a new connection. Even if TCP Wrapper accidentally blocks new connections, it won't interfere with the established session.

There are several ways to implement IP-based access restrictions for SSH, but none of them are trivial:

TCP Wrapper configuration changes automatically apply to all new connections, so there is no need to restart sshd. TCP Wrapper is relatively old code, and it is somewhat finicky. If a configuration file doesn't end with a line feed, Wrapper ignores the last line. Comments must start with a hashmark ("#") as the first character on the line. Network masks must be entered in the older /255.255.255.0 syntax, rather than the more modern /24 format. Full details and more options for hosts.allow and hosts.deny are in the manual page ("man -S5 hosts_access").

ftp://ftp.porcupine.org/pub/security/index.html#software

To configure TCP Wrapper, first block all access and confirm the change has worked. Unfortunately, sudo's behavior with file redirection is odd, so a workaround is required to append text to a file using sudo.

$ sudo sh -c 'echo "ALL: ALL" >> /etc/hosts.deny'
Password:
$ ssh 127.0.0.1
ssh_exchange_identification: Connection closed by remote host

Next, decide what hosts to allow. Visiting http://www.whatismyip.com/ is a convenient way to find the public IP of a given computer. "whois IP-address" identifies netblocks, which is helpful for identifying cable and DSL address ranges:

$ host emperor.tidbits.com
emperor.tidbits.com has address 216.168.61.78

Finally, configure /etc/hosts.allow to allow trusted hosts.

$ sudo sh -c 'echo "ALL: 127.0.0.1" >> /etc/hosts.allow'
$ sudo sh -c 'echo "sshd: 216.168.61.78 24.193.0.0/255.255.0.0" >> /etc/hosts.allow'

The additions above allow emperor.tidbits.com and a block of over 65,000 RoadRunner IP addresses to ssh in; all other IPs (aside from 127.0.0.1) will be rejected.

When an ssh connection is rejected due to Wrapper, an entry resembling the following is appended to /var/log/system.log:

Jun  6 18:00:00 pepperbook /usr/sbin/sshd: refused connect from 211.218.145.153

Files

OpenSSH uses several files to store configuration and authentication information. Generally speaking, for each type of file, there is a global configuration file shared by everybody, and an optional private version for each user. On other systems, the global files may be in different locations, such as /etc/ssh/ or /usr/local/etc/. Several of these files are security sensitive (notably authorized_keys), and will not be effective if permissions are incorrect. The most important files are listed below. For further details and additional files, see the manual pages for sshd_config, ssh_config, sshd, and ssh. Note that for security reasons, per-user configuration files generally do not allow globally configured restrictions to be relaxed, although security can be tightened.

Unfortunately, Mac OS X normally hides the /etc directory, so changing the global OpenSSH configuration files isn't quite as easy as modifying normal documents. I normally use BBEdit to access these files, typically starting from a Terminal window, with "bbedit /etc/ssh_config /etc/sshd_config". Another option is to edit the files with a character-mode text editor, such as "sudo nano /etc/ssh_config /etc/sshd_config". To see the files in the Finder, use its Go:Go to Folder command, and type /etc in the dialog box that comes up. Then just drag files onto your favorite text editor. Be sure to save as plain text when done, rather than RTF or Microsoft Word format.

Global File Per-User File Notes
/etc/sshd_config ~/.ssh/authorized_keys Configures sshd, the SSH server. authorized_keys allows users to enable public key authentication, and to place restrictions on users logging in with public keys.
/etc/ssh_config ~/.ssh/config Configures ssh, scp, and sftp client behavior.
/etc/ssh_host_rsa_key
/etc/ssh_host_rsa_key.pub
~/.ssh/id_rsa
~/.ssh/id_rsa.pub
SSH v2.x RSA keys, private and public. Private keys are equivalent to passwords; they must be protected with filesystem permissions, and should be encrypted. Host private keys cannot be encrypted, because sshd must be able to start without user intervention (to enter a decryption passphrase). SSH v1.x keys are deprecated because the SSH v1.x protocol is flawed.
/etc/ssh_host_rsa_key
/etc/ssh_host_rsa_key.pub
~/.ssh/id_rsa
~/.ssh/id_rsa.pub
SSH v2.x RSA keys
/etc/ssh_known_hosts ~/.ssh/known_hosts List of public keys for hosts.
/etc/hosts.allow
/etc/hosts.deny
-- TCP Wrapper configuration files, which may be used to limit access to sshd by client IP.

There are several additions to these files which can make using SSH easier and safer.

File Suggested addition Notes
/etc/sshd_config
Protocol 2
X11Forwarding yes
The SSH v1.x protocol is flawed, and should no longer be used; this forces SSH v2.x protocol only. X11Forwarding permits the client to request tunneling of X11 connections; by default it's disabled on Mac OS X. To confirm the validity of sshd_config, use sudo sshd -td.
/etc/ssh_config
Protocol 2
ForwardAgent yes
ForwardX11 yes
ForwardX11Trusted yes
NoHostAuthenticationForLocalhost yes
The SSH v1.x protocol is flawed, and should no longer be used; this forces SSH v2.x protocol only. ForwardAgent tells this client to set up agent forwarding when connecting to a remote machine via OpenSSH. ForwardX11 tells the client to request X11 tunneling, and ForwardX11Trusted enables compatibility with X11 applications which don't support X11 security (such as many of Red Hat's administrative tools). NoHostAuthenticationForLocalhost disables checking the host key for 127.0.0.1 (localhost), which will otherwise tend to vary and cause problems when forwarding ports.
~/.ssh/id_rsa ~/.ssh/id_rsa.pub ~/.ssh/id_rsa ~/.ssh/id_rsa.pub Create at least one key pair with ssh-keygen. Note that the private key(s) should only be on private trusted machines -- not multi-user systems, or those controlled by other people. It's fine to use multiple keypairs; just give them identifiable names.
~/.ssh/authorized_keys Put trusted public keys here on every SSH server. As much as practical, restrict use of these keys. This file may contain one or more public keys which provide SSH access to this account -- each optionally with restrictions on its use.
/etc/hosts.allow /etc/hosts.deny Restrict access to the sshd server with TCP Wrapper if feasible. TCP Wrapper is the easiest way to limit which Internet hosts (IP addresses) may connect to sshd (the SSH server) on Mac OS X.
~/.ssh/config Add per-user SSH client customizations, such as usernames for particular servers, here. Many of the configuration options from ssh_config can be set here per-user; for one, multiple, or all SSH servers.

Conclusion

You should now have a good sense of what you can do with SSH, both the basic stuff and the most useful advanced tricks. Hopefully you also have a sense of the security issues, so you can make informed trade-offs between convenience and capability versus security. Personally, I find SSHKeychain invaluable, and use forward and reverse tunneling so I work through firewalls, and help other people with their computers. I also use bbedit and rsync with SSH frequently. If you'd like to learn more about SSH internals and history, check out SSH, The Secure Shell: The Definitive Guide - 2nd edition, from O'Reilly.



Notes

I'm not going to explain the loopback address here. It's important, but way out of scope. I'm also not going to explain TCP/UDP ports. Needs a link to KvH's VPN article, and perhaps my ancient firewall article. I want to get an OpenSSH porter to review, but haven't contacted one of them yet. I'm also not explaining sudo.

To-Do


This page was last modified Friday, 14-Nov-2008 21:11:08 EST.