Typing your username for every host is a pain. In addition, ssh has a large variety of special options (e.g., compression, agent forwarding, host-specific private keys, etc.) that may differ on a per-host basis. In your ~/.ssh directory, create a file named config to set host aliases and options. Example ~/.ssh/config:
Host feynman
User foobar
ForwardAgent yes
Host hawking 192.168.1.1 router
Hostname hawking
User root
ForwardAgent yes
Port 222
Host *.cc.gatech.edu
User bmcm
ForwardAgent yes
Compression yes
Run man ssh_config to view documentation about ssh config files.
Change ssh cipher for rsync
Ever rsync over ssh to CPU-limited devices (e.g., VIA CPUs, ARM, Atom, contended shared servers, etc.)?
SSH Compression
ssh features built-in compression:
This is particularly helpful for X forwarding over WAN connections or even multi-segment LANs (combine with -Y for trusted X11 forwarding). It can make the difference between unusable and tolerable forwarding.
SSH Pseudo TTY Allocation
ssh -t forces pseudo-tty allocation. By default, when you ssh without a command to execute (just to log in), a pseudo tty is allocated. When you specify a command to execute, ssh does not allocate a pty. Forcing it is necessary if you want to run something that's not just plain text output, like screen or top.
Why wouldn't you want a pseudo-tty? Well, consider piping binary data:
You don't want a pseudo tty in that case. It will molest your data by interpreting escapes and such (unless you want to over-complicate things with uuencode).
SSH Host Keys
When you connect to a new host via ssh, the host key is stored in ~/.ssh/known_hosts, establishing the host's identity.
StrictHostKeyChecking option
When you first connect to an unknown host via ssh, it asks you to confirm:
$> ssh star2.cc.gt.atl.ga.us
The authenticity of host 'star2.cc.gt.atl.ga.us (143.215.129.169)' can't be established.
RSA key fingerprint is fe:82:da:4d:76:f7:fa:b4:40:6f:7d:3e:1b:b3:01:bb.
Are you sure you want to continue connecting (yes/no)?
This explicit confirmation is good for security, but sometimes you want to script commands via ssh and don't want to be prompted. Personal example: 52 node cluster without shared home directories; do it the naive way, and you'd need ~(N^2) different confirmations. Even if you do it on one host and then copy the known_hosts file to the other nodes, it is annoying to go through all of the prompts. Solution:
$ ssh star2.cc.gt.atl.ga.us -o StrictHostKeyChecking=no
Warning: Permanently added 'star2.cc.gt.atl.ga.us,143.215.129.169' (RSA) to the list of known hosts.
On a cluster, you could do something like this to pre-seed the files:
HashKnownHosts option
Default in many cases; hashes hostnames in ~/.ssh/known_hosts. Entries look like the following (top is hashing on, bottom is hashing off):
|1|QxEMrKqPTNuBtHIEYSbztjaOkF8=|Y1387YZhibtug9rr4ZVXenyRXb4= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAg...
boar3.almaden.ibm.com,9.1.112.221 ssh-rsa sAAAAB3NzaC1yc2EAAAABIwAAAg...
Some people prefer to disable by setting HashKnownHosts no in ~/.ssh/config. Hashing breaks tab-completion based on ~/.ssh/known_hosts (but not via other means — like parsing ~/.ssh/config — so it may not be a big deal).
Want to convert an old, non-hashed ~/.ssh/known_hosts file to hashed? Run ssh-keygen -H
ssh-keygen -R & -F
When a host's key changes, ssh will make you remove the offending key from ~/.ssh/known_hosts before it will let you connect (unless you force it to ignore). Some people edit this file by hand (why?), but ssh-keygen has specific options for this:
This works whether or not ~/.ssh/known_hosts is hashed, so don't waste your time editing things by hand.
View a host's key fingerprint?
Use ssh-keygen: ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub (or dsa). Add -v to get an ASCII art depiction:
ssh keys allow you to log in to remote machines with a public/private key pair. In your ~/.ssh directory you will use ssh-keygen to generate a key pair, and you will have to distribute the public half of the key pair to remote machines. You keep the private half of the key pair private (as if that isn't obvious).
A passphrase is a password that unlocks the generated key. It may be blank, but we suggest only making it blank if you have other security measures (one of those is detailed below). A stolen but password-protected private key will not compromise your accounts.
$> ssh-keygen -t rsa
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): (enter passphrase)
Enter same passphrase again: (enter passphrase)
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/.ssh/id_rsa.pub.
The key fingerprint is:
2c:3f:a4:be:46:23:47:19:f7:dc:74:9b:69:24:4a:44 user@mydesktop
$> cat .ssh/id_rsa.pub | ssh user@server "mkdir -p ~/.ssh/ && cat - >> ~/.ssh/authorized_keys"
The above command appends your public key to the list of authorized keys on a given host. Now when you login, instead of asking you for a password, ssh will ask you for the key's passphrase (or it will just let you in, if your passphrase is blank).
You can limit the power of keys to run certain commands, to only connect from certain hosts, and disallow things like port forwarding, X forwarding, etc.
Concrete example:
I use a restricted ssh key to run fetchmail. My mailhome is baobab.cc.gatech.edu, and I've set up a special entry in my ~/.ssh/config for email checking:
Host email
Hostname baobab.cc.gatech.edu
User davidhi
IdentityFile ~/.ssh/mail_check
LogLevel QUIET
The mail_check key is a special password-less key. In my ~/.ssh/authorized_keys file, I have the following prepended before the public key:
command="/usr/sbin/imapd",no-X11-forwarding,no-port-forwarding, no-agent-forwarding,no-pty ssh-dss A...
This restricts connections made via the key to only running imapd and disallows X11 forwarding, port forwarding, agent forwarding and pty access. This means that the password-less key is locked down (assuming imapd is not compromised) [0].
List of things:
Notes:
[0] Not sure of the original source of this since I've been using it since at least 2003. This might be it, though: http://mah.everybody.org/docs/mail/fetchmail_check
[1] Hint from: http://www.oreilly.com/catalog/sshtdg/chapter/ch11.html
Wouldn't it be convenient to enter a key's passphrase only once, and have it unlock your key for the entire terminal session? ssh-agent is a background service that keeps track of your unlocked keys. It can manage multiple keys, and you can add or remove keys or identities dynamically. When you use ssh to login to a server with key authentication, ssh will ask your agent if it already has the key unlocked. That way, you don't have to type your password every time.
Sometimes your distribution's X server will start up the agent automatically. If it doesn't, you can either start it manually each time, or add it to an environment appropriate startup script. For Gnome, you might put this in /etc/X11/gdm/PreSession/Default.
$> eval `ssh-agent -s`
The above command will start up the agent, and set some environment variables which ssh will later use to connect to this agent.
Note: the above command is for Bourne-style shells. Use ssh-agent -c for csh-like variants.
Before things will start working, you must add your key(s) to the agent. You can do this automatically when you login to Gnome by adding it to your Gnome session (Startup Programs). There are several X11-based ssh-agent password prompting programs (ssh-askpass, ksshaskpass, etc.).
$> ssh-add
By default, the above command will try to add ~/.ssh/id_rsa and ~/.ssh/id_dsa, which are the most popular key filenames. If you have a different filename, just provide the name of the key as a command-line argument to ssh-add. If your passphrase is not blank, it will prompt you for the passphrase, but this will be the only time you have to enter it (until the agent stops or you manually remove the identity from the agent). Confirm that the agent has the key by running:
$> ssh-add -l
Say you want to access services local to a private network (not publicly exposed), but from outside you can only ssh to a host on that network. For example, you want to access an internal website running on webhost. You can't access it from a web browser at home normally, but ssh local port forwarding will let you tunnel the request through the ssh connection to it:
$> ssh -L 80:webhost:80 sshhost
This will bind the local port 80 (the first 80) to a tunnel, with the other end pointing to port 80 (the 2nd 80) of the webhost. You may then access the website by pointing your browser to http://localhost (because localhost port 80 forwards to webhost port 80). Port forwarding can be used to access any TCP service, not just websites (see below for an email example). In fact, dynamic forwards (see below) are often better for websites.
Notes:
Here is an example for accessing pop3 via a tunnel. The command below sets up the forwarding and then leaves the connection open in the background without a shell.
$> ssh -L 9999:mailserver:110 shellserver -N -f
After that, you can setup your mail app to use localhost:9999 instead.
Also, as illustrated in the last example, you may use -N -f:
Host home-with-tunnel
Hostname homemachine.com
RemoteForward 2222:localhost:22
User joe
Now, when you ssh to 'home-with-tunnel', it will set up a remote forward from port 2222 on your home machine to your work desktop's port 22. At home, ssh to localhost over port 2222 (using the -p option) and the request will be forwarded through the existing ssh connection, granting you access to an otherwise unreachable host. Note that this example also illustrates how to set up forwards using your ~/.ssh/config file. Sometimes setting up a remote forward can get confusing, but the localhost in the RemoteForward entry above refers to the machine you are ssh-ing from.
Note: the above scenario establishing potentially unauthorized outside access to a work machine may be against the Network Usage Policies of your place of employment. Use with caution.
Use -D to create a SOCKS proxy.
$> ssh -D 8080 helsinki.cc.gatech.edu
Now set your web browser to use localhost:8080 as a SOCKS 5 proxy. For Firefox, set network.proxy.socks_remote_dns = true (in about:config) and DNS resolving will occur via the proxy, too. That means you can use resolve internal network DNS hostnames. SOCKS proxies are very flexible. Instead of forwarding a specific remote TCP port to a local TCP port, -D runs a flexible proxy server which can be used to tunnel arbitrary requests with the right support. Also check out the very useful tsocks wrapper tool.
Use ControlMaster auto to speed up remote filename tab completion, sshfs, or other ssh operations to the same host. New connections to a host will use an already established session (if present), which makes operations a lot faster.
Add to ~/.ssh/config:
Host *
ControlMaster auto
ControlPath ~/.ssh/.sock_%r@%h:%p
Usage:
$> ssh -Nf helsinki.cc.gatech.edu
$> ls ~/.ssh -la | grep sock
.sock_davidhi@helsinki.cc.gatech.edu:22
Escape sequences are only recognized after a newline and are initiated with a tilde (~) unless you modify it with the -e flag. Hit <ENTER> ~? on a running ssh session to see a list of escapes:
~. and ~# are particularly useful.
Did you know that ssh can do layer 2 and 3 VPN tunneling? Check out ssh -w. Example from manpage:
$> ssh -f -w 0:1 192.168.1.15 true
$> ifconfig tun0 10.0.50.1 10.0.99.1 netmask 255.255.255.252