Gentoo setup - Page 1

These Gentoo articles will take you from a ‘barebones’ Gentoo Slice to a secured and up to date Slice ready for your server software (or whatever you use the Slice for).

Securing your Slice as soon as possible is a great way of starting your Slice administration.


Log in

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

ssh root@123.45.67.890

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. Please refer to your own OS for details of where this file is kept.

User administration

Once logged in to the VPS, immediately change your root password to one of your choosing:

passwd

Add an admin user (I’ve used the name demo here but any name will do). The -m causes gentoo to automatically create the users’ home directory in /home/demo.

adduser -m demo

Give this user a password:

passwd demo

Enter the new password twice as prompted. Please note that it will not echo back your keystrokes, just type normally. If you make a mistake just hit Enter and it will start the process again.

SUDO

As you know, we never log in as the root user (this initial setup is the only time you would need to log in as root). As such, the main administration user (demo) needs to have sudo (Super User) privileges so they can, with a password, complete administrative tasks.

We will give sudo privileges to all users who belong to the wheel group.

To configure this, give the visudo command:

visudo

Find the line that reads:

# %wheel        ALL=(ALL)       ALL

and uncomment it by removing the '# ' (hash and space), so it looks like this:

%wheel        ALL=(ALL)       ALL

Save the changes by hitting these key combinations: CTRL+O to write out the file, Enter to confirm the filename, CTRL+X to exit the program.

Now we’ll add demo to the wheel group; giving him the ability to use sudo:

usermod -aG wheel demo

Again, replace demo with whatever user name you chose above.

SSH keygen

One effective way of securing SSH access to your slice is to use a public/private key. This means that a public key is placed on the server and the private key is on our local workstation. This makes it impossible for someone to log in using just a password - they must have the private key.

The first step 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. There will be a separate article for key generation using Putty for Windows users.

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

ssh-keygen -t rsa

If you do not want a passphrase then just press enter when prompted.

That created two files in the .ssh directory: idrsa and idrsa.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 show, give away or keep this file on a public computer.

SSH copy

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

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

Still on your LOCAL workstation enter this command:

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

When prompted, enter the demo user password.

Change the IP address to your slice and the location to your admin user’s home directory (remember the admin user in this example is called demo).

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, there’s a directory called .ssh in the demo user’s home folder, lets move the pub key into it:

mv /home/demo/id_rsa.pub /home/demo/.ssh/authorized_keys

Now we can set the correct permissions on the key:

chmod 600 /home/demo/.ssh/authorized_keys

Done. It may seem a long set of steps but when you have done it once, you can see the order of things: create the key on your local workstation, copy the public key to the Slice and set the correct permissions for the key.

SSH config

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

nano /etc/ssh/sshd_config

The main things to change (or check) are:

# Change the default port to something else:
Change: #Port 22
to:     Port 30000 # (Actually change it to something generic, 30000 is just an example)

# Don't allow root to login through ssh
Change: #PermitRootLogin yes
to:     PermitRootLogin no

# Don't use PAM for authentication
Change: UsePAM yes
to:     UsePAM no

# Specify which users can login via ssh. Add this line to the bottom of the file.
# More users can be addded using `space` as a separator, eg. demo anne jenny
AllowUsers demo

Once done, save the file and exit the editor using the same commands as earlier. I think the settings are fairly self explanatory but the main thing is to move it from the default port of 22 to one of your choosing, turn off root logins and define which users can log in.

PasswordAuthentication (off by default) and UsePAM have been turned off as 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 if the local computer is secure (i.e. don’t put the private key on a work computer).

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

As said, the next thing is to set up our iptables so we have a more secure installation. To start with, we’re going to have three ports open: ssh, http and https.

Note that we are logged in as the root user. This is the only time we will log in as the root user. As such, if you are completing this step at a later date using the admin user, you will need to put a sudo in front of the commands.

iptables works by applying rules to network packets that move through chains. The packets we care most about start in the INPUT chain and end up in either the ACCEPT or REJECT chains.

Now let’s see what’s running at the moment:

iptables -L

You will see 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.

One theory is that if there are no services running then it doesn’t matter. I disagree. If connections to unused (and popular) ports are blocked or dropped, then the vast majority of script kiddies will move on to another machine where ports are accepting connections. It takes ten minutes to set up a firewall - is it really worth not doing?

Seeing as we’ve come so far, let’s assume you’ve decided that you want a firewall.

iptables - Adding rules

Lets start adding rules to our iptables. Run these commands in the shell. Remember to change 30000 to whichever port you chose to run ssh on:

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -d 127.0.0.0/8 -i ! lo -j REJECT --reject-with icmp-port-unreachable  
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 30000 -j ACCEPT    
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT    
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT   
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT 
iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable

Once you’ve entered these commands you can see that iptables is fully loaded with:

iptables -L

Notice the change? (If there is no change in the output, you did something wrong. Try again from the start).

iptables - Saving, loading and undoing

Have a look at the rules and see exactly what is being accepted, rejected and dropped; make sure this is what you want. If something goes wrong, you can start again by typing:

/etc/init.d/iptables reload

Once you are happy with the rules, it’s time to save our rules permanently:

/etc/init.d/iptables save

The table is saved to /var/lib/iptables/rules-save.

iptables - Making live changes

Suppose we wanted to remove the ‘https’ port opening. To do this we can:

iptables -D INPUT 6

We get 6 from counting down from the first rule in iptables -L. Running iptables -L again now will show that the ‘https’ rule has been removed. Lets put it back again:

iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

Here we’re inserting the rule in position 6. Run iptables -L again to see the change. We can’t use the -A to append the rule to the end of the input chain, as it would never be read. As the packet passes through the REJECT rule, it would be moved out of the INPUT chain and so no more INPUT rules will be run on it.

Suppose we put the wrong ssh port in and we wanted to use 30301 instead. We could replace the old ssh rule with:

iptables -R INPUT 4 -p tcp -m state --state NEW -m tcp --dport 30301 -j ACCEPT

Here we’re replacing rule 4 with our new rule.

If you change iptables this way, be sure to save the changes when done.

More information can be found on iptables by referring to it’s man page:

man iptables

iptables - Run on boot

At the moment iptables won’t be effective when the slice boots up. You can check this with:

rc-update show | grep iptables

Notice the different output when checking for ssh:

rc-update show | grep ssh

There are two run levels by default in Gentoo. SSH is an application so it boots in the default run level. iptables is something that a lot of other software may depend on so we want it to load first, and therefore put it in the boot run level like this:

rc-update add iptables boot

You can see all things that will load on boot like this:

rc-update show

When gentoo boots it will run all the scripts in the boot level first, either alphabetically or using the dependency information within the scripts; then it does the same for all the scripts in the default run level.

Logging in as the new user

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

/etc/init.d/sshd reload

Don’t logout yet…

As you have an already established connection you will not be locked out of your ssh session (look at the iptables config file: it accepts already established connections).

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

ssh -p 30000 demo@123.45.67.890

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

If all goes well you should login without a password to a plain terminal:

demo@yourvpsname ~ $

Success!

We now know that the firewall and ssh works and we can log in.

Let’s move on to page 2 of the Gentoo install which shows you how to update your system.

matiu

Article Comments:

Nicolas Miyasato commented Sun Jan 18 04:19:21 UTC 2009:

/etc/init.d/iptables panic

That's what I executed and I immediately got logged off. And then couldn't log back in via ssh

Now I'm struggling with the web console to fix this stuff...

Does anyone know what that panic stuff is good for ?

AFAIK you only execute it when you are in front of the server, as it blocks absolutely everything...

dunno what happened over here... :(

matiu commented Thu Jan 22 05:55:56 UTC 2009:

My apologies Nicolas. I should have put 'reload' instead of 'panic'.

'panic' does empty the iptables, but then stops all network packets.

I'll fix this up ASAP

Ken commented Mon Feb 23 16:16:36 UTC 2009:

If you will always be using ssh from one of a small set of IP addresses, you might as well use the -s switch with the line allowing in SSH traffic. That will reject all inbound SSH traffic that is not from the IP address you specify. No sense letting anyone anywhere beat on your SSH door and see if they can get it to let them in.

(They can spoof their IP address, but then (unless they're attacking from your slice's subnet) they won't get a response from SSH and they won't be able to negotiate an encrypted session with it and they won't be able to feed it any input.)

If you ISP changes your IP address on you infrequently, then when it happens, you can always log into the console and change the allowed IP address. If they change it every day, that could get annoying of course.

matiu commented Mon Feb 22 13:22:48 UTC 2010:

I had a report of:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

Causing an error like:

iptables: No chain/target/match by that name.

Here it's actually complaining about the -m state part of the equation. The solution is simple, just run this as root:

depmod

This will organise all the kernel modules and make things work .. be careful as it can break any custom kernel modules you may have compiled.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)