Debian Setup

  • Published: March 12, 2010
  • | Updated: September 14, 2011
  • Debian

Throughout this manual, we’re using nano which is a rather simple text editor. When you find the time, you should try out GNU Emacs and Vim as they are the only real editors out there. They both have a very steep learning curve, but once you get rolling with either of them, you’ll see that it was worth it.

Both editors are shipped with very good documentation and tutorials. In GNU Emacs, hit C-h t (hold down the control key, while it is down, press “h”, release the control key and press “t”). In Vim, make sure the package “Vim” is installed (by default only vim-common and vim-tiny is installed on the server, and these packages lack the tutorial). Then type “vimtutor”, and follow along.

We also recommend the following books: Learning GNU Emacs and Learning the vi and Vim Editors.

Log in

As soon as you’ve got the IP address and root password for your VPS you can log in via SSH:

me@workstation:~$ ssh root@123.4.56.123

Change the root password

example:~# passwd

Add a user

Debian is a multi-user environment. You should not do your everyday work using the root account. It is more than poor practice, it is dangerous. Root is for administrative tasks. Instead, we’ll add a normal, non-root user account through the adduser program. When running the command you’ll be asked some questions concerning the new user. It is up to you how much you fill out, but you should provide a full name at least.

Let’s go ahead and create a new user now. We’ll call him demo, but any name will do.

example:~# adduser demo

This initial setup is the only time you would need to log in as root. To administrate the VPS we need to give the main account super user privileges, so we can complete such tasks through a normal user account. For that, we need to install the sudo package

example:~# aptitude install sudo

To add a user as a sudo user (a “sudoer”), the visudo command must be run as root. visudo copies the /etc/sudoers file to be edited to a temporary file, edits it with an editor, and subsequently runs a sanity check on the input. If it passes, the temporary file overwrites the original with the correct permissions.

example:~# visudo

In the user privilege section add your user name below root

demo    ALL=(ALL) ALL

So that the section now looks like

# User privilege specification
root    ALL=(ALL) ALL
demo    ALL=(ALL) ALL

The part after the user name gives you full root privileges when you precede a command with sudo.

SSH

Secure Shell (SSH) is a network protocol that allows data to be exchanged over a secure channel between two computers. Encryption provides confidentiality and integrity of data. SSH uses public-key cryptography to authenticate the remote computer and allow the remote computer to authenticate the user if necessary.

SSH is typically used to log into a remote machine and execute commands, but it also supports tunneling, forwarding arbitrary TCP ports and X11 connections. File transfer can be accomplished using the associated SFTP or SCP protocols.

An SSH server listens on the standard TCP port 22 by default. An SSH client program is typically used for establishing connections to an sshd daemon accepting remote connections. Both are commonly present on most modern operating systems.

OpenSSH

OpenSSH (OpenBSD Secure Shell) is a set of computer programs providing encrypted communication sessions over a computer network using the ssh protocol. It was created as an open source alternative to the proprietary Secure Shell software suite offered by SSH Communications Security. It is being developed as part of the OpenBSD project.

OpenSSH is sometimes confused with OpenSSL, but the projects have different purposes and are developed by different teams. The similar name is drawn only from similar goals.

SSH Keys

A very effective way of securing SSH access to your VPS is to use SSH Keys. With these keys you can easily connect to a server, or multiple servers, without having to enter a password for each system.

The keys consist of a public and a private key. The public key is placed on the server, and the private key is placed on your computer. In the image below, the client is the system you type directly on, such as a laptop or desktop system. The server is anything connected to from the client.

Installing OpenSSH locally

Check if you have OpenSSH installed on your computer

me@workstation:~$ ssh -V

If you get something similar to

me@workstation:~$ ssh -V
OpenSSH_5.1p1 Debian-5, OpenSSL 0.9.8g 19 Oct 2007

Then you are good to go, and can skip to the next section.

If you don’t already have OpenSSH installed, that is, you get something like

me@workstation:~$ ssh -V
-bash: ssh: command not found

Then you can install it with

me@workstation:~$ sudo aptitude install openssh

At least if you are on a Debian system.

Generating SSH Keys

When OpenSSH is installed it’s time to create the keys we need. The RSA key pair must be generated on your computer. The public portion of this key will reside on the servers being connected to, while the private portion needs to remain on a secure local area on your computer system. The default is ~/.ssh/id_rsa.

The keys can then be generated by running the ssh-keygen command. It will prompt you for a location which you should leave as the default. The important part here is the passphrase, though. Do not use your account password, and do not leave the passphrase empty. Not setting a passphrase means that anyone who gets hold of your key can use it.

Time to create the keys on your computer

me@workstation:~$ ssh-keygen -t rsa

We just generated a 2048 bit long public/private RSA (-t rsa) key pair with the ssh-keygen command.

In ~/.ssh you’ll now find two files: id_rsa and id_rsa.pub. The pub file holds the public key, which is the file that is placed on your VPS. The other file (id_rsa) is your private key. Never show, give away, transfer the file over the network, or keep the file on a public computer.

Using keychain

Keychain manages one or more private keys. When initialized it will ask for the passphrase for the private key(s) and store it. That way, your private key is password protected but you won’t have to enter the password over and over again.

Install keychain on your computer

me@workstation:~$ sudo aptitude install keychain

Edit ~/.bashrc

me@workstation:~$ nano ~/.bashrc

Add the following to the file

eval `keychain --eval --nogui -Q -q id_rsa`

Close your shell and open it again. Keychain should come up and ask for the passphrase of your private key(s) if it’s the first run.

There are other alternatives to keychain. ssh-agent and x11-ssh-askpass, for example. And, several desktop environments have their own solution. The GNOME desktop, for instance, use the GNOME Keyring which can be used as an SSH agent. The goal remains the same, though. That is, to remember the passphrase so you don’t have to type it repeatedly throughout the day.

Copying the keys to the remote server

Now that we have generated the keys, we need to copy the public key to the remote server. We’ll do this with scp (secure copy). The scp man page says that it “copies files between hosts on a network. It uses ssh for data transfer, and uses the same authentication and provides the same security as ssh”.

Issue the following command on your computer

me@workstation:~$ scp ~/.ssh/id_rsa.pub demo@123.4.56.123:

Note the colon at the end of the command below. It means that the file will be copied to the user’s home directory.

Next up is to create the ~/.ssh directory and concatenate the key we just copied to the authorized_keys file on the server. We also need to sort out a few permissions.

Since we’re already logged on the server as root, we’ll switch to the demo account first, then issue the necessary commands:

example:~# su - demo

Then as the user demo

demo@server:~$ mkdir ~/.ssh
demo@server:~$ cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
demo@server:~$ chmod 700 ~/.ssh/
demo@server:~$ chmod 600 ~/.ssh/authorized_keys
demo@server:~$ rm ~/id_rsa.pub
demo@server:~$ exit

Configuring SSH

Let’s change some of the default SSH configuration to make it more secure. Edit the file /etc/ssh/sshd_config

example:~# nano /etc/ssh/sshd_config

Then replace its contents with the following:

# Package generated configuration file
# See the sshd(8) manpage for details

# What ports, IPs and protocols we listen for
Port 30000

# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2

# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key

#Privilege Separation is turned on for security
UsePrivilegeSeparation yes

# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 768

# Logging
SyslogFacility AUTH
LogLevel INFO

# Authentication:
LoginGraceTime 120
PermitRootLogin no
StrictModes yes

AllowGroups ssh-users

RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys

# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes

# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no

# similar for protocol version 2
HostbasedAuthentication no

# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes

# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelling clear text passwords
PasswordAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

X11Forwarding no
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no

#MaxStartups 10:30:60
#Banner /etc/issue.net

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

UsePAM no
UseDNS no

We changed the following in /etc/ssh/sshd_config on the server

Port  30000                     # change this to a port number of your choosing
PermitRootLogin no              # turn off root login
PasswordAuthentication no       # we use keys instead of passwords
AllowGroups ssh-users           # only allow ssh login for group members of ssh-users
X11Forwarding no                # don't allow X11 forwarding
UsePAM no                       # turn off the Pluggable Authentication Module
UseDNS no                       # don't look up remote host to check host name

The AllowGroups ssh-users means that anyone wanting to use ssh must be a member of this group. Since the group doesn’t exist, we need to create it

example:~# groupadd ssh-users

And then we need to add our main user to the group

example:~# usermod -a -G ssh-users demo

Hosts access

To further restrict access to the server, we’ll set up access based on hosts. Edit /etc/hosts.allow on the server and add your IP address to the file if you’re on a static IP address. If not, you need to add your Internet Service Provider’s IP subnet.

This file will only allow login access to certain IP addresses, so it’s important to get the IP range right or you will lock yourself out of the server. You may want to add an IP address that you know won’t change. If you are a student, having the IP address of your school or University is a good idea.

Open /etc/hosts.allow with

example:~# nano /etc/hosts.allow

Then add your IP address or IP range to the file

# /etc/hosts.allow: list of hosts that are allowed to access the system.
#                   See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: LOCAL @some_netgroup
#             ALL: .foobar.edu EXCEPT terminalserver.foobar.edu
#
# If you're going to protect the portmapper use the name "portmap" for the
# daemon name. Remember that you can only use the keyword "ALL" and IP
# addresses (NOT host or domain names) for the portmapper, as well as for
# rpc.mountd (the NFS mount daemon). See portmap(8) and rpc.mountd(8)
# for further information.
#

ALL: 20.200.0.0/255.255.0.0

Alright, we’ve now said that everyone coming from the IP range 20.200.0.0 can log in, but we have not yet restricted the access. To do that we need to edit the /etc/hosts.deny and disallow access to everyone but the IP address(es) listed in the allow file.

Edit the file /etc/hosts.deny on the server and change the last line

example:~# nano /etc/hosts.deny

Then change the last line to

# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system.
#                  See the manual pages hosts_access(5) and hosts_options(5).
#
# Example:    ALL: some.host.name, .some.domain
#             ALL EXCEPT in.fingerd: other.host.name, .other.domain
#
# If you're going to protect the portmapper use the name "portmap" for the
# daemon name. Remember that you can only use the keyword "ALL" and IP
# addresses (NOT host or domain names) for the portmapper, as well as for
# rpc.mountd (the NFS mount daemon). See portmap(8) and rpc.mountd(8)
# for further information.
#
# The PARANOID wildcard matches any host whose name does not match its
# address.

# You may wish to enable this to ensure any programs that don't
# validate looked up hostnames still leave understandable logs. In past
# versions of Debian this has been the default.
ALL: ALL

iptables

We’re going to install and setup iptables to secure the VPS further. iptables is a tool for administrating the built-in firewall capabilities of the Linux kernel.

Let’s have a look at the currently active rules

example:~# iptables -L

You’ll get the following output

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

At the moment, our VPS is accepting anything from anyone on any port and allowing anything to happen. But, we’re going to do something about that. We’ll set it up so that only three ports are open: ssh, http and https.

First we’ll create a file that will hold our rules for testing purposes. Edit /etc/iptables.test.rules

example:~# nano /etc/iptables.test.rules

Then fill it with the following rules

*filter

#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allows SSH connections
-A INPUT -p tcp -m state --state NEW --dport 30000 -j ACCEPT

#  Allow imaps
#-A INPUT -p tcp --dport 993 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Save the file, and load the rules with

example:~# iptables-restore < /etc/iptables.test.rules

Check that the rules were loaded successfully with

example:~# iptables -L

The output should now be

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             loopback/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

Save the rules permanently

example:~# iptables-save > /etc/iptables.up.rules

Our iptables rules will get lost when we reboot the server. After a reboot, we’ll go back to allowing everything from everywhere. Let’s address that by making sure our rules are applied when we reboot the server.

Edit /etc/network/interfaces

example:~# nano /etc/network/interfaces

Add the line below “iface lo inet loopback”

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/iptables.up.rules

# The primary network interface
(...)

Testing

Time to check if everything works. Reload ssh on the server so it uses the new ports and configurations

example:~# /etc/init.d/ssh reload

Do not log out. If this doesn’t work, we have effectively locked ourself out from the server. But by keeping the connection alive in another terminal, we can fix things on the server in case it doesn’t work.

Switch to a terminal on your local computer, then try to log in. You need to change the port number (30000) to the port you’re using, and you also need to change the IP address.

me@workstation:~$ ssh -p 30000 demo@123.4.4.123

If all goes well, you should login without a password to a plain terminal on your VPS.

SSH configuration tips

Your SSH session will automatically time out if it is idle. To keep the connection active, edit the file ~/.ssh/config on your local computer

me@workstation:~$ nano ~/.ssh/config

Add the following

ServerAliveInterval 180

This will send a keep alive signal to the server every 3 minutes.

One other handy tip is related to server login. When you log in to the server you would typically write

me@workstation:~$ ssh -p 30000 demo@123.4.4.123

But, we can shorten it to

me@workstation:~$ ssh example

To do that, edit your ~/.ssh/config file on your local computer

me@workstation:~$ nano ~/.ssh/config

Add the following

Host example
  Port 30000
  HostName 123.4.4.123 
  User demo

You’ll now be able to log on with ssh example.

Setting locales and timezone

Locales is “a framework to switch between multiple languages and allow users to user their language, country, characters, collation order etc.” Set your preferred locales by issuing the following command

demo@server:~$ sudo dpkg-reconfigure locales

When that’s done, we’ll just go ahead and set the timezone as well

demo@server:~$ sudo dpkg-reconfigure tzdata

Package management with aptitude

aptitude is a text-based interface to the Debian GNU/Linux package system. With it, you can view the list of packages available, and perform package management tasks such as installing, upgrading, and removing packages.

A package manager keeps track of what software is installed on the computer, and allows you to easily install new software, upgrade software to newer versions, or remove software that you previously installed.

As the name suggests, package managers deal with packages. That is, collections of files that are bundled together and can be installed and removed as a group.

A lot of the time, a package is just a particular program. For example, the network traffic monitor vnstat is contained in the Debian package of the same name. It is common, however, for programs to consist of several interrelated packages. This is the case with the gimp image editor. It consists not only of the gimp package, but also of the gimp-data package. In addition, several optional add-on packages are also available. It is also possible for several small, related programs to be contained in a single package, like the fileutils package. The fileutils package contains several common Unix commands, such as ls, cp, and so forth.

The job of a package manager, like aptitude, is to present an interface which assist users in managing the collection of packages installed on the computer. aptitude provides such an interface by building on the apt package management system.

The Advanced Packaging Tool (apt)

Being able to install and remove packages is great, but the basic software for doing this (known as dpkg) does exactly that and nothing more. This is fine if you download one or two packages by hand, but quickly becomes cumbersome when you are trying to manage a large number of packages.

When a package requires software you haven’t yet installed, you have to download the newly required software by hand. If you later decide to remove said package, these extra packages will linger on your system, consuming disk space, unless you manually remove them. All of this manual labor is a tedious chore, and so most package management systems come with software which takes care of some or all of it for you.

apt works by keeping a list of the packages that can be downloaded from Debian on your system. This list is used to find packages that need to be upgraded. In addition it is also used to install new packages.

apt solves many dependency problems automatically. When you choose to install a package, it will find any additional required packages and install those as well.

When working with a package manager based on apt, such as aptitude, you will typically perform three basic tasks. You will update the list of packages that are available by downloading new lists fromt he Debian servers, you will select which packages should be installed, upgraded, or removed, and finally, you will commit your selections by actually performing the installations, removals and so forth.

Update and upgrade the system with aptitude

The first thing to do is to modify the /etc/apt/sources.list file. The file specifies which packages can be obtained.

demo@server:~$ sudo nano /etc/apt/sources.list

The bare minimum is

deb        http://ftp.de.debian.org/debian/ squeeze main
deb-src    http://ftp.de.debian.org/debian/ squeeze main

deb        http://security.debian.org/ squeeze/updates main
deb-src    http://security.debian.org/ squeeze/updates main

Or you can replace the content with the following which has a lot more repositories

deb        http://ftp.de.debian.org/debian/ squeeze main contrib non-free
deb-src    http://ftp.de.debian.org/debian/ squeeze main contrib non-free

deb        http://security.debian.org/ squeeze/updates main contrib non-free
deb-src    http://security.debian.org/ squeeze/updates main contrib non-free

Next is to update the list of packages

demo@server:~$ sudo aptitude update

Then upgrade the packages

demo@server:~$ sudo aptitude safe-upgrade

You need to do this regularly to keep your server up-to-date. It is a good idea to join the debian-security-announce mailing list as well.

Some useful aptitude commands

# search for <package name>
aptitude search <package name>

# list installed <package name>
aptitude search <package name>|grep \^i

# search for "gcc" in the description field
aptitude search '~dgcc'

# install <package name>
sudo aptitude install <package name>

# remove <package name>
sudo aptitude remove <package name>