Ubuntu Jaunty Setup - Part 1

Your Ubuntu Jaunty Slice will be a bare-bones install when it's created. We need to connect via SSH and secure it as soon as possible.


Your new slice

These two articles will take you from a 'barebones' Ubuntu 9.04 (Jaunty Jackalope) Slice to a secured and up-to-date Slice ready for your server software (or whatever you use the Slice for). Not only that, you will have a better understanding of what is going on and, more importantly, why it's going on.

This first part will walk you through setting up a new user and securing login access to your slice.

For convenience when we refer to running a command on your local workstation we will give the command as it would be entered into a Mac or Linux terminal window. For Windows you should be able to adapt the command based on the context. For instance, if you're told to edit a file as part of a step, you would use a text editor like NotePad instead of running the "nano" command.

Intro to SSH

SSH stands for "secure shell". It's a protocol that encrypts data that gets sent back and forth through its connection, making it much harder for someone to intercept that traffic and scan it for passwords or sensitive information. In these articles we'll have you using SSH to connect to your slice to run most administrative commands.

If you're running a Linux desktop, you'll be able to run the ssh commands we list here by using them in a terminal window.

If you're running Mac OS X you'll also be able to run the ssh commands in a terminal window. You can open a terminal by running the 'Terminal' application that was installed with your system.

On Windows you won't have command-line access to SSH by default, so you'll need to download a client. We recommend a program named PuTTY, both because it works well and because it's free. You might also want a nice interface for running scp (which uses the SSH protocol to transmit files over an encrypted connection). We recommend another free program, WinSCP, though there are other options like FileZilla that also work well.

First login

As soon as you have your IP address and password for your Slice, login via SSH:

ssh root@123.45.67.890

As mentioned earlier, on a Windows machine you'll need to run an SSH client like PuTTY in order to make the connection.

If you rebuilt your Slice, you may get a message informing you that the 'remote host identification has changed'.

When you log into a Slice via SSH, one of the security features is matching the remote host with known keys. When you rebuild a Slice, the remote host key changes. As such, your computer thinks there is something dodgy going on.

All you need to do is remove the older entry for the Slice IP. On your LOCAL computer, edit the SSH known_hosts file and remove any entries that point to your Slice IP address.

nano ~/.ssh/known_hosts

If you are not using Linux or a Mac on your LOCAL computer, the location of the known_hosts file will differ depending on the program you are using. You'll need to refer to the documentation for that program for details. For example, PuTTY stores its known hosts in the following registry entry:

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys

User administration

Now we're logged in to the VPS, immediately change your root password:

passwd

Apart from this initial setup, you should never log in as the root user. It's safer and more secure to create a new administrative user and use the 'sudo' command from that user. Having to use sudo to run superuser commands can help prevent some potentially system-breaking accidents, and it also means that any root-level commands run through sudo will be logged to '/var/log/secure' if later review is needed.

To make managing administrative access to your slice easier let's create a group, 'wheel', that will contain users with sudo privileges. To make the group, run:

/usr/sbin/groupadd wheel

With the group ready, let's issue the 'visudo' command to edit the sudo configuration:

/usr/sbin/visudo

The visudo command runs a default editor, and will check the configuration for any syntax errors before saving it. The default editor for Ubuntu is 'nano'.

Scroll down to the bottom of the file. Add the following two lines to the end of the file:

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

Save and exit the file, and sudo is all set. Members of the 'wheel' group will now have full sudo privileges.

NOTE: Some users will find that while working in the nano editor, the backspace/delete key works backwards, deleting characters in front of the cursor rather than behind it. This can be resolved by editing the '/etc/nanorc' file (with nano, for example) and either uncommenting or adding the line:

set rebinddelete

The corrected behavior will take effect after the file has been saved and nano has been opened again.

Add a new user

Time to create a new administrative user (I've used the name demo here but any name will do).

/usr/sbin/adduser demo

You will be asked to set a password for the new user. The values for Full Name and the rest can be left blank.

Since you'll want to use this user instead of 'root' to manage your system, it will need to be able to use the sudo command. We've already granted that permission to the 'wheel' group, so we just need to add the new user to 'wheel':

/usr/sbin/usermod -a -G wheel demo

SSH keygen

One feature of SSH is the ability to require users to use, instead of a password, a "key pair" for authentication. Under this approach a user generates a public and private key pair on their workstation and then uploads the public half of the key pair to the server. When they go to connect later the server tries to match up its public key with the user's private key in order to authenticate the connection.

Using a key pair with SSH is good security policy, which is why we'll walk you through the process here. A password can be guessed through sheer brute force (running a program to try different character combinations until it gets a match), but a key pair is vastly more complex. It is almost impossible to crack a key pair with a brute force approach.

Note that using a public/private key pair is impractical if you need to log in to your slice from a workstation that is shared with other users. While you can copy the private key to another workstation, putting that key on a shared workstation would defeat the purpose of the key pair's security. In that environment continuing to use a password for SSH access would make sense.

The first step to using key pair authentication is to create a folder to hold your keys. On your LOCAL workstation:

mkdir ~/.ssh

That's assuming you use Linux or a Mac and the folder does not exist. For Windows users we have a separate article on key generation using Puttygen.

To create the ssh keys, on your LOCAL workstation enter:

ssh-keygen -t rsa

If you do not want your key to require a passphrase when used then just press enter when prompted.

That created two files in the .ssh directory: id_rsa and id_rsa.pub. The pub file holds the public key. This is the file that is placed on the Slice.

The other file is your private key. Never share this file with someone else or store it on a public computer.

SSH copy

Now we need to get the public key file onto the Slice.

We'll use the 'scp' command for this as it is an easy and secure means of transferring files.

Still on your LOCAL workstation enter this command, substituting your new username and the IP address of your slice:

scp ~/.ssh/id_rsa.pub demo@123.45.67.890:

When prompted, enter the your user password. When that's done you should see scp copy the file to your user's home directory.

On a Windows machine you'll want to use a third-party client like WinSCP, using the information above to make the connection.

SSH Permissions

OK, so now we've created the public/private keys and we've copied the public key onto the Slice.

Now we need to sort out a few permissions for the ssh key.

On your Slice, create a directory called .ssh in your home directory and move the pub key into it:

mkdir ~demo/.ssh
mv ~demo/id_rsa.pub ~demo/.ssh/authorized_keys

If you haven't run into it before, that squiggly character is the 'tilde', and it's usually in the upper-left of your keyboard. In the Linux shell it can be used as a reference to a user's home directory. Using '~' by itself refers to the current user's home directory, while using it like we did above, '~demo', refers to the home directory of user 'demo'. It's a handy shortcut to know.

Now we can set the correct permissions on the key:

chown -R demo:demo ~demo/.ssh
chmod 700 ~demo/.ssh
chmod 600 ~demo/.ssh/authorized_keys

Again, replace the 'demo' user and group above with the name of the user you created.

Additional users

If you need to add more users to your system, now or after you finish this initial setup, you can just run through the steps above again for each user.

If the user doesn't need to have administrative privileges, skip the part where you add the user to the 'wheel' group.

If the user will be accessed from the same workstation as your administrative user, you can re-use the same public SSH key for the new user.

SSH config

Next we'll change the default SSH configuration to make it more secure:

nano /etc/ssh/sshd_config

You can use this ssh configuration as an example.

The main things to change (or check) are:

Port 30000                           <--- change to a port of your choosing
Protocol 2
PermitRootLogin no
PasswordAuthentication no
UseDNS no
AllowUsers demo

NOTE: The port number can readily be any integer between 1025 and 65536 (inclusive), but should be noted for reference later when any additional listening processes are setup, as it will be important to avoid conflicts.

If you need to allow remote logins for more than one user, add the additional users to the 'AllowUsers' setting separated by spaces.

The labels are fairly self explanatory, but the main security changes to make are to move ssh from the default port of 22 to one of your choosing (we use 30000 in the example), turn off remote root logins, and define which users can log in remotely.

PasswordAuthentication has been turned off because we setup the public/private key earlier. Do note that if you intend to access your slice from different computers you may want leave PasswordAuthentication set to 'yes'. Only use the private key on a secure workstation.

Note that we haven't enabled the new settings — we will restart SSH in a moment, but first we need to create a simple firewall using iptables.

iptables

Right, now we have the basics of logging in and securing SSH done.

Next thing is to set up our iptables (firewall) so we have a more secure installation. It's possible to skip this step, or to disable iptables entirely, but we recommend that if you follow the Slicehost tutorials, you set up iptables with our default rules. It's a good hindrance to would-be intruders. Furthermore, the comments in the file you'll create can help you remember why you made a particular change later, and you can use the examples there to take some of the headache out of figuring out what new rule to add and where.

The default rules

Let's have a look at the default iptables rules:

/sbin/iptables -L

Remember that if you come back to this part of the tutorial as a non-root user later, you'll need to put a 'sudo' in front of the iptables command to make it work.

The default setup will output something similar to this:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

As you can see, we are accepting anything from anyone on any port and allowing anything to happen.

When we're done, the output of that command should look something like this:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             127.0.0.0/8         reject-with icmp-port-unreachable 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https 
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:30000 
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request 
LOG        all  --  anywhere             anywhere            limit: avg 5/min burst 5 LOG level debug prefix `iptables denied: ' 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere

There's too much there to go into much detail in this article, but the basics to pay attention to when you skim those firewall rules are 'ACCEPT', 'REJECT', 'INPUT', and 'OUTPUT'. Fortunately those are reasonably understandable in context. Rules can refer to incoming traffic ('INPUT') or outgoing traffic ('OUTPUT'), and they can describe whether to 'ACCEPT' or 'REJECT' the described connections. The rest of it determines the sort of traffic being controlled, like what port or packet type it's looking for.

Roll your own

Now to set up those iptables rules we want. If the output of 'iptables -L' wasn't an empty ruleset, or if you just want to be thorough, you'll want to flush the current rules from memory:

/sbin/iptables -F

We can now set up our own rules that allow local connections and keep established connections (which is how the root SSH connection on port 22 will still work when we apply the SSH port changes and apply the new iptables rules).

We'll also open port 80 and port 443 (the normal HTTP and HTTPS ports) and, of course, allow connections to our custom SSH port. Then we'll allow pings to the Slice and, effectively, reject all other attempts to connect to a port.

To make it easier to keep track of the rules you want iptables to use and to change them later, let's create a file to store them:

nano /etc/iptables.up.rules

Now check out our example iptables rules file. Copy and paste those rules into your new file, and edit the rules however you see fit. The comments should help you decide what to change. In particular, make sure you change the line opening port 30000 to whatever you chose as your custom ssh port.

The lines opening ports for a web server should provide a good template for opening ports for other services you may add to your slice later.

If you want more complex firewall rules (restricting outbound traffic as well as inbound, for example), you might do well to research iptables more after you're done with this basic setup.

Once you're happy with your iptables rules, save the file.

Implement your rules

To tell iptables to use your new rules, run the command:

/sbin/iptables-restore < /etc/iptables.up.rules

That will read in the custom rules from the file you just created. You can confirm that it worked by checking the rules again:

/sbin/iptables -L

See the difference between the first time we entered that command and now? Again, have a look at each line of the output and see where it marries up with the rules we entered earlier.

Although the rules are up and running, they are only active for the current session. If the Slice were to be rebooted they would be lost.

As such, let's ensure they are restored on a Slice reboot. We'll add a small script that the system will run when your network interfaces are started. Create the file by running:

nano /etc/network/if-pre-up.d/iptables

Add the following lines to the new file:

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules

Save your changes, and then make the new script executable:

chmod +x /etc/network/if-pre-up.d/iptables

That should ensure that whenever your network interfaces are brought up (usually just at boot time), the firewall will be too.

Editing iptables later

You can repeat these steps if you decide you've made a mistake, or if you want to change any rules later. Just edit the rules file you created, flush the current rules from memory, then restore the edited rules.

The commands you'd use (without all the commentary) are:

nano /etc/iptables.up.rules
/sbin/iptables -F
/sbin/iptables-restore < /etc/iptables.up.rules

Good work surviving the iptables setup.

Note that if you decide to use a control panel type of program like virtualmin that can manage your firewall rules you'll want to either not use that part of the control panel, or remove what we've been using to manipulate iptables. A similar choice would have to be made if you look into using another method of managing firewall rules, like UFW or Shorewall. Having two processes controlling iptables rules can lead to some real conflict. If you find an alternative, just be sure that you choose it alone or that you go back to using /etc/iptables.up.rules exclusively.

Onward!

Reload sshd

Now we have our basic firewall humming along and we've set the ssh configuration. Time to test it. Reload ssh so it uses the new ports and configurations:

/etc/init.d/ssh reload

Don't logout as root yet...

Logging in with the new user

On your LOCAL computer, open a new terminal and log in using the administrative user (in this case, demo) to the port number you configured in the sshd_config file (for our example, 30000):

ssh -p 30000 demo@123.45.67.890

The reason we use a new terminal is that if you can't login you will still have the working root connection to try and fix any errors.

Slicehost also has an excellent ajax console so if it all goes horribly wrong, you can log into your slice from the Slicehost management area.

You should be greeted with a plain terminal prompt like this:

[demo@yourvpsname ~]$

Success!

We now know that the firewall and sshd_config work and we can log in.

Let's move on to part 2 which includes updating the install and installing some base programs.

  • -- Jered

Article Comments:

Allen commented Sat Apr 24 17:35:43 UTC 2010:

Seemed like there was a step missing. Set the group privileges and tried to add user to group but...group did not exist. I did a "groupadd wheel" to get it going.

Allen commented Sat Apr 24 17:36:22 UTC 2010:

In the Reload SSH section: "/etc/init.d/sshd reload" was not found, "/etc/init.d/ssh reload" worked, I hope that's right.

Jered commented Sat Apr 24 17:37:33 UTC 2010:

Gah! I knew I'd miss something, sorry about both of those. You got both corrections exactly right. I've added the changes to the article. Thanks for pointing them out.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)