Sunday, May 10, 2009

Beginning SSH on Ubuntu

From: http://principialabs.com/beginning-ssh-on-ubuntu/

So let’s say you have a private LAN running in your secret underground lab. Maybe you’ve got a Linux box hardwired to a WiFi router, and maybe a Mac or Linux laptop floating around somewhere, and you need a quick way to transfer files or execute shell commands remotely.

What you need is SSH, the Secure Shell. SSH is a powerful tool which allows secure remote login over insecure networks. It provides an encrypted terminal session with strong authentication of both the server and client using public-key cryptography. This tutorial will cover the basics of SSH’s most useful features:

  • Logging into a remote computer over a secure connection.
  • Transferring files and directories between computers over a secure connection.
  • Enabling public-key authentication.
  • Passwordless authentication for use with scripts and cron jobs.

The following assumptions are made about the reader:

  • You know what a terminal/command line/shell is and how to start a session.
  • You have at least a basic familiarity with Linux/Mac command-line syntax.
  • You’re on a private LAN with access to at least two Linux/Mac computers (or, you have a user account on a remote server that accepts SSH connections).

As always, comments, corrections, and suggestions for improvement are appreciated.

Installing OpenSSH

The Ubuntu (and MacOS X) flavor of SSH is called OpenSSH, a free, open-source implementation of the ssh protocol. It consists of two basic components, an openssh-client and an openssh-server. SSH clients communicate with SSH servers over encrypted network connections.

The openssh-client software should already be installed by default on Ubuntu. If you want to be able to accept SSH connections as well as request them, you’ll need the server software as well. The easiest way to ensure you have both is simply to run:

<code>sudo apt-get install openssh-client openssh-server<br /></code></pre>  <h3>Using SSH to Log into a Remote Computer</h3>  <p>Once OpenSSH is installed, you can login to a remote SSH server by using the <code>ssh</code> command:</p>  <pre><code>ssh remoteuser@remotebox<br /></code></pre>  <p>where <code>remoteuser</code> is the username of the remote account you’re trying to access, and <code>remotebox</code> is the remote server’s hostname or IP address.</p>  <p>For example, if you know that your Kubuntu desktop box (now running <code>openssh-server</code>) has a user account named <code>joebanks</code> and that the IP address of that computer on your private LAN is <code>192.168.0.12</code>, you could login remotely to that account from your Linux/Mac laptop by typing:</p>  <pre><code>ssh joebanks@192.168.0.12<br /></code></pre>  <div class="help"> If you’re unsure of a computer’s local IP address, try running <code>ifconfig</code> on that machine. This will display the status of the active network interfaces, and the local IP address of that device will be listed after <code>inet addr</code>.  It will most likely be in the form of <code>192.168.0.xx</code>. </div>  <p>Or, if you’ve got a web hosting account that allows shell access (e.g., <a href="http://dreamhost.com/">DreamHost</a>) with a domain name like <code>cooldomain.com</code>, your syntax might look like:</p>  <pre><code>ssh joebanks@cooldomain.com<br /></code></pre>  <p>Now, the first time an SSH client encounters a new remote server, it will report that it’s never seen the machine before, by printing the following message:</p>  <pre><code>The authenticity of host 'remotebox (192.168.0.12)' can't be established.<br />RSA key fingerprint is 53:b4:ad:c8:51:17:99:4b:c9:08:ac:c1:b6:05:71:9b.<br />Are you sure you want to continue connecting (yes/no)?<br /></code></pre>  <p>This is just an extra security measure to ensure that you’re actually connecting to the machine you think you are.  If you type <code>yes</code> (the most common response), you’ll see the following:</p>  <pre><code>Warning: Permanently added 'remotebox' (RSA) to the list of known hosts.<br /></code></pre>  <p>Subsequent login attempts to this machine will omit the warning message.  You’ll then be asked for the <code>remoteuser</code>’s password:</p>  <pre><code>remoteuser@remotebox's password:<br /></code></pre>  <p>And after correctly entering it, like magic, you’ll be logged into the remote machine, and instead of your local machine’s command prompt, you’ll see the following:</p>  <pre><code>remoteuser@remotebox:~sudo apt-get install openssh-client openssh-server

Using SSH to Log into a Remote Computer

Once OpenSSH is installed, you can login to a remote SSH server by using the ssh command:

ssh remoteuser@remotebox

where remoteuser is the username of the remote account you’re trying to access, and remotebox is the remote server’s hostname or IP address.

For example, if you know that your Kubuntu desktop box (now running openssh-server) has a user account named joebanks and that the IP address of that computer on your private LAN is 192.168.0.12, you could login remotely to that account from your Linux/Mac laptop by typing:

ssh joebanks@192.168.0.12
If you’re unsure of a computer’s local IP address, try running ifconfig on that machine. This will display the status of the active network interfaces, and the local IP address of that device will be listed after inet addr. It will most likely be in the form of 192.168.0.xx.

Or, if you’ve got a web hosting account that allows shell access (e.g., DreamHost) with a domain name like cooldomain.com, your syntax might look like:

ssh joebanks@cooldomain.com

Now, the first time an SSH client encounters a new remote server, it will report that it’s never seen the machine before, by printing the following message:

The authenticity of host 'remotebox (192.168.0.12)' can't be established.
RSA key fingerprint is 53:b4:ad:c8:51:17:99:4b:c9:08:ac:c1:b6:05:71:9b.
Are you sure you want to continue connecting (yes/no)?

This is just an extra security measure to ensure that you’re actually connecting to the machine you think you are. If you type yes (the most common response), you’ll see the following:

Warning: Permanently added 'remotebox' (RSA) to the list of known hosts.

Subsequent login attempts to this machine will omit the warning message. You’ll then be asked for the remoteuser’s password:

remoteuser@remotebox's password:

And after correctly entering it, like magic, you’ll be logged into the remote machine, and instead of your local machine’s command prompt, you’ll see the following:

remoteuser@remotebox:~$

And, voila! You can execute commands on the remote machine just as you would on your local box. To close the connection to the remote server, type exit, or use Ctrl-D.

Copying Files

To transfer files and directories from your local machine to the remote server and vice-versa, you’ll use SSH’s “secure copy” command, or scp. To copy a single file from your local machine to the server, use the following syntax:

scp file.txt remoteuser@remotebox:/directory

where file.txt is the name of a file in the current directory of your local machine, remoteuser@remotebox is the username and hostname or IP address of the server (just like in the above ssh examples, and /directory is the directory path on the server where you want your file copied.

For example, if you want to copy the local file.txt to the /home/joebanks/docs directory on the server you logged into above, you’ll run the following command from a local terminal session:

scp file.txt joebanks@192.168.0.12:/home/joebanks/docs
By “local terminal session,” I mean that you DO NOT first ssh in to the remote computer and then run the scp command. Secure copy opens the ssh tunnel on its own. Since secure copy uses the ssh protocol for a secure connection, whenever you run the scp command, you’ll be prompted for a password (or passphrase) if the ssh connection requires it.

You can be as verbose as you want with the local and remote filenames and directories, even changing the filename in the process, like so:

scp ~/docs/oldfile.txt joebanks@192.168.0.12:/home/joebanks/docs/newfile.txt

To copy a file from the server to your local machine, use the following syntax:

scp remoteuser@remotebox:file.txt /local/directory

where remoteuser@remotebox is the username and hostname or IP address of the server, file.txt is a file in the /home/remoteuser directory, and /local/directory is the local directory path into which the file will be copied.

Again, you can be as verbose as necessary, for example:

scp joebanks@192.168.0.12:~/docs/newfile.txt /home/joe/downloads

Copying Directories

To copy an entire directory (and all of its contents) from the local machine to the remote server, use the recursive -r switch, like so:

scp -r /local/directory remoteuser@remotebox:/remote/directory

where /local/directory is the path to the local directory you want copied, and /remote/directory is the remote directory into which you want the directory to be copied.

To copy an entire directory (and all of its contents) from the remote server to the local machine, use the following:

scp -r remoteuser@remotebox:/remote/directory /local/directory

where /remote/directory is the path to the remote directory you want copied, and /local/directory is the local directory into which you want the directory to be copied.

Stop Typing the Stupid IP Address All Day, Will You?

By now you’re no doubt getting sick of typing joebanks@192.168.0.12 or whatever. It sure would be nice to type something shorter. Let’s fix that.

OpenSSH uses a client configuration file, located at ~/.ssh/config, to simplify some of the tedious typing associated with logging into remote machines. To edit (or create) that file, we’ll use the nano text editor, but you can use vi, emacs, kate or whatever:

nano ~/.ssh/config

The simplest configuration file might look something like this:

Host volcano
HostName 192.168.0.12

This associates the Host volcano with the HostName (or IP address) 192.168.0.12, so now to login you’ll only need to type:

ssh joebanks@volcano

That’s cool, but let’s get a little more lazy, shall we? How about this:

Host BigWoo
HostName 192.168.0.12
User joebanks

Now all we need to type is:

ssh BigWoo

Far out! You can add as much configuration data as you need to this Host, and as many different Hosts as you like. And this shorthand will also work with all the scp examples:

scp file.txt BigWoo:

To learn more visit the OpenSSH docs, or run man ssh_config.

Public-Key Authentication

To increase the security of your SSH session, or to set up passwordless authentication, you can enable SSH’s built-in public-key cryptography. Then, instead of entering the remoteuser’s password on each login attempt, SSH will initiate a challenge-and-response protocol which attempts to match an encrypted public key (stored on the server) with a protected private key (stored on the local machine). This completely eliminates the need to send sensitive information (like a password) over the network, encrypted or not.

To generate a public/private key pair on your local machine, open a terminal and type:

ssh-keygen -t dsa

You’ll see the following message:

Generating public/private dsa key pair.
Enter file in which to save the key (~/.ssh/id_dsa):

Hit Enter. This selects the default location. Next you’ll see:

Enter passphrase (empty for no passphrase):

Enter a secure passphrase, ideally something unique and unguessable. Unlike a password, a passphrase is usually a phrase or complete sentence, with spaces and punctuation if you like. The longer and more obscure the phrase, the stronger it is.

Note: It is also acceptable to just hit Enter at this point, thereby selecting no passphrase. This can be appropriate in some instances (see below), but you should be aware that it is not as secure. While ssh will still use an encrypted public/private keypair (which is almost certainly more secure than typing the remote user’s password like you’ve been doing), anyone gaining access to your local account will thereby also gain unfettered access to any remote hosts which recognize your public key.

After typing a passphrase and hitting Enter, you’ll see:

Enter same passphrase again:

Enter the same passphrase again. And finally:

Your identification has been saved in ~/.ssh/id_dsa.
Your public key has been saved in ~/.ssh/id_dsa.pub.
The key fingerprint is:
42:ac:8a:81:31:81:e5:7b:d2:01:42:2d:64:32:0f:dd localuser@localbox

Now copy your public key, which is stored in the local file ~/.ssh/id_dsa.pub to the remote machine, by running the following command from a local terminal session:

ssh-copy-id -i ~/.ssh/id_dsa.pub remoteuser@remotebox

You’ll be prompted for the remoteuser’s password one last time, and then you’ll see the message:

Now try logging into the machine, with "ssh 'remoteuser@remotebox'", and check in:

.ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.
MacOSX Users: If the ssh-copy-id method doesn’t work with your version of OpenSSH, try the following command:

cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'cat >> .ssh/authorized_keys'

Or, if the ~/.ssh directory doesn’t yet exist on the remote machine, you can create the directory and copy the public key all in one swell foop, like so:

cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'mkdir .ssh; cat >> .ssh/authorized_keys'

Once the ~/.ssh/authorized_keys file on the remote machine contains your public key, you’ll be prompted for your passphrase at each login attempt, rather than the remoteuser’s system password, like so:

Enter passphrase for key '~/.ssh/id_dsa':

Finally, it’s a good idea to change the permissions of the ~/.ssh directory and the ~/.ssh/id_dsa file on your local machine, to disable any outside access to your private key.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_dsa
lt;br /></code></pre> <p>And, voila! You can execute commands on the remote machine just as you would on your local box. To close the connection to the remote server, type <code>exit</code>, or use <code>Ctrl-D</code>.</p> <h3>Copying Files</h3> <p>To transfer files and directories from your local machine to the remote server and vice-versa, you’ll use SSH’s “secure copy” command, or <code>scp</code>. To copy a single file from your local machine to the server, use the following syntax:</p> <pre><code>scp file.txt remoteuser@remotebox:/directory<br /></code></pre> <p>where <code>file.txt</code> is the name of a file in the current directory of your local machine, <code>remoteuser@remotebox</code> is the username and hostname or IP address of the server (just like in the above <code>ssh</code> examples, and <code>/directory</code> is the directory path on the server where you want your file copied.</p> <p>For example, if you want to copy the local <code>file.txt</code> to the <code>/home/joebanks/docs</code> directory on the server you logged into above, you’ll run the following command from a <em>local terminal session:</em></p> <pre><code>scp file.txt joebanks@192.168.0.12:/home/joebanks/docs<br /></code></pre> <div class="help"> By “local terminal session,” I mean that you DO NOT first <code>ssh</code> in to the remote computer and <i>then</i> run the <code>scp</code> command. Secure copy opens the <code>ssh</code> tunnel on its own. Since secure copy uses the <code>ssh</code> protocol for a secure connection, whenever you run the <code>scp</code> command, you’ll be prompted for a password (or passphrase) if the <code>ssh</code> connection requires it. </div> <p>You can be as verbose as you want with the local and remote filenames and directories, even changing the filename in the process, like so:</p> <pre><code>scp ~/docs/oldfile.txt joebanks@192.168.0.12:/home/joebanks/docs/newfile.txt<br /></code></pre> <p>To copy a file from the server to your local machine, use the following syntax:</p> <pre><code>scp remoteuser@remotebox:file.txt /local/directory<br /></code></pre> <p>where <code>remoteuser@remotebox</code> is the username and hostname or IP address of the server, <code>file.txt</code> is a file in the /home/remoteuser directory, and <code>/local/directory</code> is the local directory path into which the file will be copied.</p> <p>Again, you can be as verbose as necessary, for example:</p> <pre><code>scp joebanks@192.168.0.12:~/docs/newfile.txt /home/joe/downloads<br /></code></pre> <h3>Copying Directories</h3> <p>To copy an entire directory (and all of its contents) from the local machine to the remote server, use the recursive <code>-r</code> switch, like so:</p> <pre><code>scp -r /local/directory remoteuser@remotebox:/remote/directory<br /></code></pre> <p>where <code>/local/directory</code> is the path to the local directory you want copied, and <code>/remote/directory</code> is the remote directory <em>into which</em> you want the directory to be copied.</p> <p>To copy an entire directory (and all of its contents) from the remote server to the local machine, use the following:</p> <pre><code>scp -r remoteuser@remotebox:/remote/directory /local/directory<br /></code></pre> <p>where <code>/remote/directory</code> is the path to the remote directory you want copied, and <code>/local/directory</code> is the local directory <em>into which</em> you want the directory to be copied.</p> <h3>Stop Typing the Stupid IP Address All Day, Will You?</h3> <p>By now you’re no doubt getting sick of typing <code>joebanks@192.168.0.12</code> or whatever. It sure would be nice to type something shorter. Let’s fix that.</p> <p>OpenSSH uses a client configuration file, located at <code>~/.ssh/config</code>, to simplify some of the tedious typing associated with logging into remote machines. To edit (or create) that file, we’ll use the nano text editor, but you can use vi, emacs, kate or whatever:</p> <pre><code>nano ~/.ssh/config<br /></code></pre> <p>The simplest configuration file might look something like this:</p> <pre>Host volcano<br /> HostName 192.168.0.12<br /></pre> <p>This associates the Host <code>volcano</code> with the HostName (or IP address) <code>192.168.0.12</code>, so now to login you’ll only need to type:</p> <pre><code>ssh joebanks@volcano<br /></code></pre> <p>That’s cool, but let’s get a little more lazy, shall we? How about this:</p> <pre>Host BigWoo<br /> HostName 192.168.0.12<br /> User joebanks<br /></pre> <p>Now all we need to type is:</p> <pre><code>ssh BigWoo<br /></code></pre> <p>Far out! You can add as much configuration data as you need to this Host, and as many different Hosts as you like. And this shorthand will also work with all the <code>scp</code> examples:</p> <pre><code>scp file.txt BigWoo:<br /></code></pre> <p>To learn more visit the <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config">OpenSSH docs</a>, or run <code>man ssh_config</code>.</p> <h3>Public-Key Authentication</h3> <p>To increase the security of your SSH session, or to set up passwordless authentication, you can enable SSH’s built-in <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>. Then, instead of entering the <code>remoteuser</code>’s password on each login attempt, SSH will initiate a challenge-and-response protocol which attempts to match an encrypted public key (stored on the server) with a protected private key (stored on the local machine). This completely eliminates the need to send sensitive information (like a password) over the network, encrypted or not.</p> <p>To generate a public/private key pair on your local machine, open a terminal and type:</p> <pre><code>ssh-keygen -t dsa<br /></code></pre> <p>You’ll see the following message:</p> <pre><code>Generating public/private dsa key pair.<br />Enter file in which to save the key (~/.ssh/id_dsa):<br /></code></pre> <p>Hit <code>Enter</code>. This selects the default location. Next you’ll see:</p> <pre><code>Enter passphrase (empty for no passphrase):<br /></code></pre> <p>Enter a secure passphrase, ideally something unique and unguessable. Unlike a password, a passphrase is usually a phrase or complete sentence, with spaces and punctuation if you like. The longer and more obscure the phrase, the stronger it is.</p> <div class="help"> <b>Note:</b> It is also acceptable to just hit <code>Enter</code> at this point, thereby selecting <i>no passphrase.</i> This can be appropriate in some instances (see below), but you should be aware that it is <i>not</i> as secure. While <code>ssh</code> will still use an encrypted public/private keypair (which is almost certainly more secure than typing the remote user’s password like you’ve been doing), anyone gaining access to your local account will thereby also gain unfettered access to any remote hosts which recognize your public key. </div> <p>After typing a passphrase and hitting <code>Enter</code>, you’ll see:</p> <pre><code>Enter same passphrase again:<br /></code></pre> <p>Enter the same passphrase again. And finally:</p> <pre><code>Your identification has been saved in ~/.ssh/id_dsa.<br />Your public key has been saved in ~/.ssh/id_dsa.pub.<br />The key fingerprint is:<br />42:ac:8a:81:31:81:e5:7b:d2:01:42:2d:64:32:0f:dd localuser@localbox<br /></code></pre> <p>Now copy your public key, which is stored in the local file <code>~/.ssh/id_dsa.pub</code> to the remote machine, by running the following command from a <em>local terminal session:</em></p> <pre><code>ssh-copy-id -i ~/.ssh/id_dsa.pub remoteuser@remotebox<br /></code></pre> <p>You’ll be prompted for the <code>remoteuser</code>’s password one last time, and then you’ll see the message:</p> <pre><code>Now try logging into the machine, with "ssh 'remoteuser@remotebox'", and check in:<br /><br /> .ssh/authorized_keys<br /><br />to make sure we haven't added extra keys that you weren't expecting.<br /></code></pre> <div class="help"> <b>MacOSX Users:</b> If the <code>ssh-copy-id</code> method doesn’t work with your version of OpenSSH, try the following command: <p> <code>cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'cat >> .ssh/authorized_keys'</code> </p> Or, if the <code>~/.ssh</code> directory doesn’t yet exist on the remote machine, you can create the directory <i>and</i> copy the public key all in one swell foop, like so: <p> <code>cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'mkdir .ssh; cat >> .ssh/authorized_keys'</code> </p> </div> <p>Once the <code>~/.ssh/authorized_keys</code> file on the remote machine contains your public key, you’ll be prompted for your passphrase at each login attempt, rather than the <code>remoteuser</code>’s system password, like so:</p> <pre><code>Enter passphrase for key '~/.ssh/id_dsa':<br /></code></pre> <p>Finally, it’s a good idea to change the permissions of the <code>~/.ssh</code> directory and the <code>~/.ssh/id_dsa</code> file on your local machine, to disable any outside access to your private key.</p> <pre><code>chmod 700 ~/.ssh<br />chmod 600 ~/.ssh/id_dsa<br /></code>

Passwordless Authentication for Automated Tasks

You can use ssh and scp in shell scripts and cron jobs to automate repetitive tasks, such as remote backups of critical files. To do so, however, you’ll need to implement some sort of passwordless authentication scheme, so that scripts can run without human intervention.

Two methods are presented below, the first is the easiest to implement (and possibly the most prevalent), while the second is the most secure.

Method 1: Sans Passphrase

If you want your scripts to have access to the ssh command without requiring a password or passphrase, simply go through the steps outlined above for enabling public-key authentication, but instead of entering a passphrase when prompted, simply press Enter.

The ssh-keygen program will generate a public/private key pair for you that will allow password- and passphrase-less access to any remote server which has your public key stored in its authorized_keys file.

Is this secure? Well, no. And yes. It’s probably more secure than typing in the remoteuser’s password and sending it over the network. Sure it’s encrypted, but it could still be intercepted.

Public-key authentication sends no password or passphrase data over the network. The “challenge” sent by the server is encrypted with your public key, and can only be decrypted with your private key, which only you have.

However, as mentioned above, if someone gains access to your local computer, they’ll also have access to every remote server with your public key.

So, you’ll need to decide the level of security required. In my opinion, if you’re only communicating with machines on a private LAN, under your control, behind a router’s firewall, then this method is adequate. Others may disagree.

Method 2: Using ssh-agent and keychain

The “proper” and secure way to achieve passwordless authentication is by using the ssh-agent and keychain daemons to store your passphrase between terminal sessions, so you don’t need to type it every time.

Setup of this method is beyond the scope of this article, but the following tutorials will walk you through the entire process, as well as the theory behind it:

Go Forth and SSHify!

I hope this tutorial serves as a gentle introduction to the Secure Shell. For further reading and advanced topics, check out the references listed below, and browse the OpenSSH Documentation. Thanks for reading.

References

  1. SSH Tutorial for Linux
  2. SSH: Ubuntu Community Documentation
  3. Secure Communications with OpenSSH
  4. Getting Started with SSH
  5. Indiana University Knowledge Base: SCP
  6. Example Syntax for Secure Copy
  7. Bash Reference Manual


No comments:

Post a Comment