READ ME FIRST
This article is provided as a courtesy and is intended as a general guide. Installing, configuring, and troubleshooting third-party applications is unsupported by (mt) Media Temple. Our support staff will be unable to assist you should you run into any complications installing this software. Please take a moment to review the Statement of Support.
Logging in as Root
By default, all of the distributions offered with your (ve) Server have only the root user installed. For security reasons we do not include the root password in your Service Activation Letter. To obtain the root user password, you will need to visit the "SSH Access" section of your (ve) Control Panel in the AccountCenter. Then you can change the password to one you know.
After you change the pasword, you can simply use a ssh client to connect to your server using your new password and root as the user.
ssh root@ve.example.com
Once connected you will have root access to your server.
Adding a User
For security reasons, we strongly encourage setting up an "admin" user that has 'sudo' privileges. With 'sudo' you can give selected users temporary "root" privileges. This is a good safeguard to prevent misuse of the root user. Follow the steps below to add a user with sudo access:
- Create the new user. We will use the name jsmith
adduser jsmith
- We now need to grant jsmith sudo privileges using the visudo command.
visudo
This will launch the '/etc/sudoers' file for editing. Using root as an example, just add another line for jsmith, and save the file using ctrl-O:
Filename: /etc/sudoers
# # This file MUST be edited with the 'visudo' command as root. # # See the man page for details on how to write a sudoers file. # Defaults env_reset # Host alias specification # User alias specification # Cmnd alias specification # User privilege specification root ALL=(ALL) ALL jsmith ALL=(ALL) ALL # Uncomment to allow members of group sudo to not need a password # (Note that later entries override this, so you might need to move # it further down) # %sudo ALL=NOPASSWD: ALL
- To test your new user and sudo privileges, log out as root and log back in as jsmith.
Now that you have sudo enabled you can simply run any command typically run by root as the jsmith user. Just add sudo to the beginning of your command. You will be prompted to enter your password.
Updating Your Server
It is very easy to keep your Debian server up to date using the apt-get packaging system. This system uses a private database to keep track of which packages are installed, which are not installed and which are available for installation. The apt-get program uses this database to find out how to install packages requested by the user, and to find out which additional packages are needed in order for a selected package to work properly.
To keep this database current run the following command:
sudo apt-get update
This command looks for the package lists in the archives found in '/etc/apt/sources.list'. It's a good idea to run this command regularly to keep yourself and your system informed about possible package updates, particularly security updates. You should see output similar to:
Output:
Get:1 http://ftp.de.debian.org lenny Release.gpg [1032B]
Get:2 http://ftp.de.debian.org lenny/volatile Release.gpg [189B]
Get:3 http://ftp.de.debian.org lenny/updates Release.gpg [835B]
Get:4 http://ftp.de.debian.org lenny Release [73.6kB]
Get:5 http://ftp.de.debian.org lenny/volatile Release [40.7kB]
Get:6 http://ftp.de.debian.org lenny/updates Release [40.8kB]
Get:7 http://ftp.de.debian.org lenny/main Packages [5245kB]
Get:8 http://ftp.de.debian.org lenny/contrib Packages [71.8kB]
Get:9 http://ftp.de.debian.org lenny/non-free Packages [88.0kB]
Get:10 http://ftp.de.debian.org lenny/volatile/main Packages [7485B]
Get:11 http://ftp.de.debian.org lenny/volatile/contrib Packages [14B]
Get:12 http://ftp.de.debian.org lenny/volatile/non-free Packages [14B]
Get:13 http://ftp.de.debian.org lenny/updates/main Packages [142kB]
Get:14 http://ftp.de.debian.org lenny/updates/contrib Packages [14B]
Get:15 http://ftp.de.debian.org lenny/updates/non-free Packages [14B]
Fetched 5712kB in 4s (1212kB/s)
Reading package lists... Done
After updating your database you can simply install all available updates with:
sudo apt-get -u upgrade
APT will then download the latest versions of each package and will install them in the proper order, taking care of all dependencies.
This is just a general overview of keeping your server updated. For more information, we strongly suggest Debian's authoritative page on package management.
Clean-up default packages most LAMP servers won't need
apt-get autoremove --purge libx11-data \
ttf-dejavu \
ttf-dejavu-core \
ttf-dejavu-extra \
x11-common \
lprng \
lynx \
lynx-cur \
wwwconfig-common \
dosfstools \
smbfs \
mtools \
libdb1-compat \
portmap \
samba-common \
snmp \
talk \
talkd
Installing Developer Tools
CAUTION:
You should only install developer tools if you plan to compile software, under normal circumstances, HTTPD servers do not need these.
(ve) distributions do not have any developer tools installed by default. All developer tools, including GCC C/C++ compilers, make and others, can easily be installed using the apt-get command. There is a convenient meta-package called 'build-essential' that will install all the Developer Tools with just one command.
CAUTION:
You should never compile software as root, under any circumstance, unless you know the risks of doing so.
Run the following command to begin:
root@debian:~# sudo apt-get update && sudo apt-get install build-essential
You will see text scroll by as the server determines what packages need to be installed. A base install should output the following packages to be installed/updated. Please enter 'Y' for yes when prompted. At this time all the packages will be downloaded and installed. There is no need to reboot your server. All changes are made live on the server. Please take note of any warnings displayed and act accordingly.
Output:
Hit http://ftp.de.debian.org lenny Release.gpg
Hit http://ftp.de.debian.org lenny/volatile Release.gpg
Hit http://ftp.de.debian.org lenny/updates Release.gpg
Hit http://ftp.de.debian.org lenny Release
Hit http://ftp.de.debian.org lenny/volatile Release
Hit http://ftp.de.debian.org lenny/updates Release
Ign http://ftp.de.debian.org lenny/main Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/contrib Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/non-free Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/volatile/main Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/volatile/contrib Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/volatile/non-free Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/updates/main Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/updates/contrib Packages/DiffIndex
Ign http://ftp.de.debian.org lenny/updates/non-free Packages/DiffIndex
Hit http://ftp.de.debian.org lenny/main Packages
Hit http://ftp.de.debian.org lenny/contrib Packages
Hit http://ftp.de.debian.org lenny/non-free Packages
Hit http://ftp.de.debian.org lenny/volatile/main Packages
Hit http://ftp.de.debian.org lenny/volatile/contrib Packages
Hit http://ftp.de.debian.org lenny/volatile/non-free Packages
Hit http://ftp.de.debian.org lenny/updates/main Packages
Hit http://ftp.de.debian.org lenny/updates/contrib Packages
Hit http://ftp.de.debian.org lenny/updates/non-free Packages
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
The following extra packages will be installed:
cpp cpp-4.3 dpkg-dev g++ g++-4.3 gcc gcc-4.3 libc6-dev libgmp3c2 libgomp1 libmpfr1ldbl libstdc++6-4.3-dev
linux-libc-dev patch
Suggested packages:
cpp-doc gcc-4.3-locales debian-keyring g++-multilib g++-4.3-multilib gcc-4.3-doc libstdc++6-4.3-dbg gcc-multilib
manpages-dev autoconf automake1.9 libtool flex bison gdb gcc-doc gcc-4.3-multilib libmudflap0-4.3-dev libgcc1-dbg
libgomp1-dbg libmudflap0-dbg glibc-doc libstdc++6-4.3-doc diff-doc
The following NEW packages will be installed:
build-essential cpp cpp-4.3 dpkg-dev g++ g++-4.3 gcc gcc-4.3 libc6-dev libgmp3c2 libgomp1 libmpfr1ldbl
libstdc++6-4.3-dev linux-libc-dev patch
0 upgraded, 15 newly installed, 0 to remove and 0 not upgraded.
Need to get 15.8MB of archives.
After this operation, 51.3MB of additional disk space will be used.
Do you want to continue [Y/n]?
Installing packages without extra clutter
By default most system administrators use apt-get to install packages, apt-get does not have a clean way of installing packages, even though apt-get does have super cow powers, it's powers are obviously weak in some areas of package management. To install packages without all the extra unneeded stuff (unneeded stuff is subjective to package management not space used) you should be using aptitude.
aptitude install package-name --without-recommends
An example of apt-get install package-name:
Output:
apt-get install mysql-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
bsd-mailx exim4 exim4-base exim4-config exim4-daemon-light libdbd-mysql-perl libhtml-template-perl
libmysqlclient15off libterm-readkey-perl mailx mysql-client-5.0 mysql-common mysql-server-5.0
Suggested packages:
mail-reader eximon4 exim4-doc-html exim4-doc-info libmail-spf-query-perl swaks libipc-sharedcache-perl tinyca
The following NEW packages will be installed:
bsd-mailx exim4 exim4-base exim4-config exim4-daemon-light libdbd-mysql-perl libhtml-template-perl
libmysqlclient15off libterm-readkey-perl mailx mysql-client-5.0 mysql-common mysql-server mysql-server-5.0
0 upgraded, 14 newly installed, 0 to remove and 0 not upgraded.
Need to get 39.7MB of archives.
After this operation, 116MB of additional disk space will be used.
An example of a clutter free install with aptitude:
aptitude install package-name --without-recommends
Securing Your Server
This guide is a general overview of how to get started with your (ve) Server. It covers a good general overview of basic security philosophy and a number of specific examples of how to better secure your (ve) Virtual-Environment server when first getting started. If you have any improvements, constructive criticism, additions, or corrections, please feel free to provide feedback on the discussion page.
(Optional) Expiring Passwords
When creating user accounts, you might want to consider expiring passwords after a given amount of time. This will force you and your users to change passwords every so often.
To easily view the current status of a user account, use the following syntax:
sudo chage -l jsmith
The output below shows interesting facts about the user account, namely that there are no policies applied:
Output:
Last password change : Aug 13, 2009
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7
To set any of these values, simply use the following syntax, and follow the interactive prompts:
sudo chage jsmith
The following example will set a maximum password age (-M) of 90 days and a warning time period (-W) of 14 days before password expiration.
sudo chage -M 90-W 14 jsmith
To verify changes, use the same syntax from above:
sudo chage -l jsmith
The output below shows the new policies that have been established for the account:
Output:
Last password change : Aug 13, 2009
Password expires : Nov 11, 2009
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 90
Number of days of warning before password expires : 14
Disabling Root Login
Allowing the root user to login directly via ssh is a major security issue. You can still use the root account after logging in as another user first.
SSH into your server as 'jsmith' Open the /etc/ssh/sshd_config file using your editor of choice. We will use nano.
sudo nano /etc/ssh/sshd_config
Change the PermitRootLogin directive on Line 26 to 'no':
Filename: /etc/ssh/sshd_config
...
21 SyslogFacility AUTH
22 LogLevel INFO
23
24 # Authentication:
25 LoginGraceTime 120
26 PermitRootLogin no
27 StrictModes yes
...
Save the file and make sure to restart the SSH server:
sudo invoke-rc.d sshd restart
Please note that you will no longer be able to login directly as root unless you revert these changes. Make sure you remember both passwords moving forward.
Alternate (PAM) method
To disable root using the PAM method (which SSH uses by default) and to prevent root from terminals if they ever exist simply do the following:
touch /etc/nologin
Securing SSH
Using SSH Keys
SSH keys should only be used on a computer that is not shared, or one that has multiple logins or accounts. If you share your computer with others under the same username you should NOT follow the steps outlined in this article.
Generating your key
The first step we need to take is generating a key on your local computer using strong encryption:
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -C "Enter an optional comment about your key?
You should receive a prompt asking for a password. Please use a strong password. If you plan on using your key for automated tasks that don't require interaction, such as rsync, you might want to leave this blank. Once you have entered your password twice make sure you have the permissions set properly for your .ssh directory and your newly created ssh files on your local computer using the following commands:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
Installing your key
Your public key now needs to be uploaded to your server. The code below reads the content of your key, creates your ssh directory on your (ve), and creates a new file called 'authorized_keys' with the same information.
cat ~/.ssh/id_rsa.pub | ssh user@ve.example.com 'mkdir ~/.ssh;cat - >> ~/.ssh/authorized_keys
We should also change the permissions for the ssh directory and files as we did up above. On your (ve) run the same commands:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
Changing default SSH Port
By default SSH uses the standard port 22 for all connections. To help prevent malicious automated attacks on this port it is best to use a non-standard port. Please note that you will have to use the '-p' flag with the ssh command to specify the port you choose. SSH into your server as 'jsmith' Open the /etc/ssh/sshd_config file using your editor of choice. We will use nano.
sudo nano /etc/ssh/sshd_config
Change Line 5 to use your new port number. In the example we will use 4791. Please make sure to choose a port higher than 1024 to prevent conflicts with reserved port numbers:
Filename: /etc/ssh/sshd_config
...
1 # Package generated configuration file
2 # See the sshd(8) manpage for details
3
4 # What ports, IPs and protocols we listen for
5 Port 4791
6 # Use these options to restrict which interfaces/protocols sshd will bind to
7 #ListenAddress ::
8 #ListenAddress 0.0.0.0
...
Save the file and make sure to restart the SSH server:
sudo invoke-rc.d sshd restart
Allowing SFTP but not SSH login
usermod -s /usr/lib/sftp-server username
echo '/usr/lib/stfp-server' >> /etc/shells
Using Deny/Allow users/groups instead of /bin/false
Using /bin/false to prevent logging into SSH is not true security, if security at all since the server is still vulnerable to DOS (DDOS if you do not limit connections) and users can still use non-shell based SSH (forwarding, etc...) By default SSH allows you to use DenyUsers, AllowUsers,DenyGroups and AllowGroups to prevent or allow logging in based on groups and users. The order they are processed in is: Deny,Allow.
An example of a basic secured sshd_config
Filename: /etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 2048
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
#change to without-password for keybased root or no for no root
PermitRootLogin yes
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
PasswordAuthentication yes
KerberosAuthentication no
X11Forwarding no
X11DisplayOffset 0
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
MaxStartups 10:30:60
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes
Fixing OpenSSH bind to a specific IP on Virtuozo bug
Many users will notice that if they try to bind OpenSSH to a specific IP SSH will not bind properly because venet0 is not handled the same way most virtualization is handled. This is also because Debian refuses to simply remove /etc/network/if-up.d/openssh-server and move /etc/rc2.d/S16ssh to /etc/rc2.d/s21.ssh and because SSH is started and never rebound using /etc/network/if-up.d/openssh-server when eth0 is detected. Under normal circumstances it's much more viable to simply go the clean route and remove /etc/network/if-up.d/openssh-server and adjust the run time of the start up script to avoid this bug, however if you feel the need you can adjust /etc/network/if-up.d/openssh-server to detect venet0 instead of eth0, to go the proper route do the following:
rm /etc/network/if-up.d/openssh-server
mv /etc/rc2.d/S16ssh /etc/rc2.d/S21ssh
Fixing error writing /proc/self/oom_adj: Operation not permitted
echo 'unset SSHD_OOM_ADJUST' >> /etc/default/ssh
Allowing or denying root or user login based on IP
By default all Debian installs come with PAM, most notably used as an ACL for SSH, PAM is enabled in SSH by default, this gives you massive control over who can login to what user with SSH and from where. To take control over this feature you should edit your /etc/security/access.conf and /etc/pam.d/sshd like the following:
First edit access.conf to something like (noting it's very important authorizations come before denials):
Filename: /etc/security/access.conf
+:root:10.0.0.5
-:ALL:ALL
Then edit sshd and uncomment the line below:
Filename: /etc/pam.d/sshd
account required pam_access.so
Using rsyslog instead of sysklogd
Many true Debian users will notice that their images come with the lighter (by installed size not memory usage), less configurable, less secure and non-auto-rotating sysklogd log daemon. The new recommended daemon for Debian since Lenny is rsyslog, to install rsyslog do the following (ignore the kernel warnings):
apt-get autoremove --purge sysklogd
aptitude install rsyslog --without-recommends
Using iptables
iptables is a powerful firewall that comes pre-installed with Ubuntu. Using iptables you can lock down your server, allowing access based on port numbers and IP addresses. Although you can create very sophisticated rules for your server, this brief introduction will just show you how to only allow access to ports 80/443 (http/https) and port 22, the default port for ssh. We will elaborate more on iptables usage in future articles.
Defining your rules
Out of the box you can see that no rules are defined by running:
sudo iptables -L
You should see very minimal output:
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
As you can see we are allowing all traffic in and out of the server. We will need to create a file that includes new rules to only allow certain ports.
Create a file using your favorite text editor named iptables.rules in the /etc directory.
sudo nano /etc/iptables.rules
I personally prefer to use /etc/default/firewall but to make this easier you can use /etc/default/iptables.ruls
Once inside the editor place the following code and save the file:
Filename: /etc/security/access.conf
*filter
# Allow loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use the lo0 interface
-A INPUT -i lo -j ACCEPT
-A INPUT -i ! lo -d 127.0.0.0/8 -j REJECT
# Accept established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow all outbound traffic
-A OUTPUT -j ACCEPT
# Allow HTTP and HTTPS connections
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
# Allow SSH
# -A INPUT -s 10.0.0.5 -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A INPUT -s 12.34.56.78 -p tcp -m state --state NEW --dport [[MySSH Port OR 22]] -j ACCEPT
# Allow ping requests
# Some might want to block this altogether.
# Just omit this rule if you don't want to accept pings, in theory you should not respond
# Security 101 to prevent scans on ports is to reject ICMP(8)
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT
Filename: /etc/iptables.rules
*filter
-A INPUT -i lo -j REJECT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -s 10.0.0.5 -p tcp -m state --state NEW --dport 22 -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT
Now that we have our rules in place let's test them. Using the iptables-restore command we can load these rules:
sudo iptables-restore < /etc/iptables.rules
We can now verify the rules using the same command above:
sudo iptables -L
You should see the following output:
Output:
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:ssh
ACCEPT icmp -- anywhere anywhere icmp echo-request
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
Once you have verified your rules you can save them. See the next section for ensuring these rules run at boot time.
sudo iptables-save /etc/iptables.rules
Making your rules permanent
Now that we have our rules in place we need to configure the server to load these rules upon reboot. This is very easily done using the file we already created. We will need to edit the template file 'etc/network/interfaces.template' which contains network interface configuration info for your server.
sudo nano /etc/network/interfaces.template
Add line 3 below to your file:
Filename: /etc/network/interfaces.template
1 auto lo
2 iface lo inet loopback
3 pre-up iptables-restore
Now that we have our rules defined and configured to run on boot we should do one last test. Reboot your server and make sure your rules are loaded.
sudo reboot
Filtering iptables rejection logs into /var/log/iptables.log
Switch rsyslog to syslog if you use sysklogd
echo ':msg,contains,"iptables" -/var/log/iptables.log' /etc/rsyslog.conf
invoke-rc.d rsyslog restart
Customizing your MOTD
echo 'My cool new MOTD that is simple' /etc/motd.tail