This HOWTO describes a couple things that you can do to secure your SSH server on a Linux machine (Ubuntu, RedHat, Suse...).

This is useful because there are script kiddies all around trying to break into computers. And I imagine that botnets writers will take more interest in Linux as it's market share increases.

The pattern that I have seen is of many many requests from the same IP address trying to guess users and passwords. Most of the requests are trying to guess the root password.

There are a couple things we can do to slow these attackers. The most obvious is to configure ssh to only allow logins from a couple select users. And to disallow remote login by the root user. We can also use IPTables to only allow a limited number of connections per minute. And finaly, we can move the SSH server to a different port on the machine. I don't know if this actually causes the attackers any pause however. They may just be trying all of the open ports.

There are more complex solutions to the problem. Port knocking or log parsing come to mind. But I've opted for the simplest solution that doesn't impact usability in my case.

The use of IPTables to limit repeated connections is based on work by Kevin van Zonneveld. You can see his approach on his blog

## What is IPTables

IPTables is part of the kernels network stack (I think). It is a user configurable state machine that can be used to filter packets as they are received, before they are forwarded or before they are transmitted.

Our configuration will drop incoming packets that meet a specific set of rules.

## SSHD configuration

The file /etc/ssh/sshd_config is used to configure the ssh server on your linux machine. The changes I made to mine were to change "Port 22" to "Port xxxx" and to add "AllowUsers yyyy zzzz wwww" where xxxx is the new port you want SSH to listen to. yyyy, zzzz and wwww are the users that you want to have remove access. I also made sure that the line "PermitRootLogin no" existed and was not commented out.

## SSH configuration

If you have changed the port that sshd listens to then you will probably want to configure your ssh clients on any machine that you would like to access your server from. In your home directory on each of these machines you should find "~/.ssh/". In that directory you can create a config file. It's just called config. Put the following in that file. Again, xxxx is the new port that your ssh server is listening to.

Host your.server.name
Port xxxx


## Network scripts

In Ubuntu there are directories that contain scripts to run when an interface comes up or goes down. These are convenient places to put the IPTables commands needed to drop attackers packets. The directory for scripts to run when a network interface comes up is /etc/network/if-up.d. And the directory for scripts to run when a network interface goes down is /etc/network/if-down.d. We will create one file in the if-up.d directory and a symlink in the if-down.d directory. We do this to consolidate the logic in a single location. We can use the MODE variable to determine if the interface is coming up or going down.

In /etc/network/if-up.d/ssh-protection put the following.

#!/bin/bash

SSH_IFACE="eth1"
SSH_PORT=xxxx   # This should be the port you've moved your ssh server to, or 22 if you haven't moved it.
SSH_PERIOD=60
SSH_COUNT=8

#
# Only add the rules to the interface that SSH is actually listening on.
#
if [ "$IFACE" != "$SSH_IFACE" ]; then
exit 0
fi

case "$MODE" in start) IPTABLES_ACTION="-A" ;; stop) IPTABLES_ACTION="-D" ;; esac /sbin/iptables$IPTABLES_ACTION INPUT \
-i $IFACE \ -p tcp \ --dport$SSH_PORT \
-m state \
--state NEW \
-m recent \
--set \
--name SSH
/sbin/iptables $IPTABLES_ACTION INPUT \ -i$IFACE \
-p tcp \
--dport $SSH_PORT \ -m state \ --state NEW \ -m recent \ --update \ --seconds$SSH_PERIOD \
--hitcount $SSH_COUNT \ --rttl \ --name SSH \ -j DROP  This file needs to be executable by root. You can use the following command line to make it so. chmod u+x /etc/network/if-up.d/ssh-protection  And in /etc/network/if-down.d create a symlink to the ssh-protection file in if-up.d using the following command line. This command line assumes you're in the if-down.d directory. ln -s ../if-up.d/ssh-protection  Comment This HOWTO describes the steps required to setup your RedHat (well any Linux distro) firewall to forward the port used by gtk-gnutella to a machine on your internal network. This is useful because it allows your gtk-gnutella client to behave in a non firewalled mode and thus more of the gnutella network is available to you. In particular, other machines that are behind firewalls that can handle push requests will become available to you. ## What is Port Forwarding? Port forwarding is a feature of the IPTables system. It allows one computer to forward connections made to it so that another computer can actually process the request. If you want a very simple metaphor you can think of it as mail forwarding. Each computer has a number of addresses called ports, and IPTables allows (among other things) connections to these ports to be sent to another computer. The most common use of port forwarding that I am aware of is allowing servers to run on machines that would normally be hidden behind a firewall. ## Firewall script I am going to assume that you are using the default firewall script that comes with RedHat or whatever distribution you are running. My system is currently running RedHat 8.0 (heh, not anymore). And I am using a firewall script called rc.firewall-2.4. You should be able to find it in your /etc/rc.d directory. If you don't find it it may be that I had to install it and just don't remember. :) You can search for rc.firewall-2.4 on Google and find many copies. ## Setup My goal was to make gtk-gnutella work in a non-firewalled mode from within my firewalled LAN. To do this people suggested a line of the form: $IPTABLES -t nat -I PREROUTING -p tcp -i $EXTIF --dport 6346 -j DNAT --to 192.168.0.2:6346  Where$IPTABLES is the iptables executable, $EXTIF is the external ethernet interface (I use two ethernet cards in my firewall), port 6346 is the gtk-gnutella port and 192.168.0.2 is the machine on my internal network on which I wished to run gtk-gnutella. With the rc.firewall-2.4 script this doesn't quite work. The reason is that by default any connection that would open a new session from the outside world is dropped. This is done with the line: $IPTABLES -P FORWARD DROP


The solution is to add a rule into the FORWARD chain that causes connections from the outside world to port 6346 to not be dropped, but instead to be accepted. Then the PREROUTING rule above will be encountered and the connection will be forwarded to the internal machine as desired. The line to accomplish this is:

$IPTABLES -A FORWARD -i$EXTIF -o $INTIF -p tcp --dport 6346 -j ACCEPT  I placed this right before the line: $IPTABLES -A FORWARD -j LOG


I did this because this line will will add a rule that causes all rules added after it to not be checked.

Comment

All right, now that we have some blogs up. We will want to enable SSL/TLS security, also known as https. The reason you want this may be obvious to some. But to spell it out for you, if you don’t use https to connect to your administrative pages in Movable Type while you’re sipping on your latte, then everyone else that’s on that wireless network can see you type your password in, plain as day. And by “can”, I mean there is nothing preventing them from watching your traffic. Most likely, no one is, but you never know.

There are a couple of complications that we will need to work through though. Firstly, SSL and name based virtual hosting are mostly incompatible. And secondly, unless you get a Certificate Authority, such as Verisign, to sign your SSL key you and your security conscious visitors will be presented with an ugly message from the browser saying that your site is trying to identify itself with an invalid security certificate.

First you need to enable SSL in your Apache configuration. In the Apache2 configuration for Ubuntu these files are located in /etc/apache2. You’ll need to make sure that your ports.conf file contains something like the following:

Listen 80

<IfModule mod_ssl.c>
Listen 443
</IfModule>


This causes Apache to listen on port 443 for connections as well as port 80. Port 443 is the https port. And your conf.d/namevirtualhosts file should look something like:

NameVirtualHost *:80
NameVirtualHost *:443


This tells Apache to look up virtual hosts by name for traffic coming in on either port. Next you need to make sure that your conf.d/ssl_certificate file looks something like:

SSLCertificateFile    /etc/apache2/ssl/serverwide.crt
SSLCertificateKeyFile /etc/apache2/ssl/serverwide.key


You can see that I’ve called my certificate and key files serverwide to make it obvious that they are used by all domains served by this server. It is very important that these files have their permissions set so that only root can read them. You’ll also need to make symlinks from the ssl.conf and ssl.load files in your mods-available directory to your mods-enabled directory.

Now we’re ready to generate and sign our key and certificate. Once you have generated the certificate you can inspect it’s contents with this command.

openssl x509 -in serverwide.crt -noout -text


To generate a key use the following command. You will be asked for a pass phrase. It is important that you remember this pass phrase or your key will be lost to you forever. Or at least until computers are powerful enough to brute force crack your key.

openssl genrsa -des3 -rand /dev/urandom -out serverwide.key 1024


Once you have a key you can create and sign a certificate with the following command. You will be asked for the pass phrase you entered above. This is because the key is protected by that pass phrase and can’t be used without it. This certificate will be valid for one year.

openssl req -config server.config -new -key serverwide.key -out serverwide.crt -x509 -days 365


Most of the options we need to pass to OpenSSL to create and sign the certificate can be passed in a configuration file. The command line above assumes the configuration file is called server.config. Below is an example server.config file, the main lines of interest are in the alt_names section. The alt_names section is where you can put all of the virtually hosted domains on your server. The browser will look for a match with any of those domains when the server passes it the certificate we have just generated. I also found that subjectAltName had to be in both the v3_req and v3_ca sections.

[ req ]
default_bits       = 1024
default_md         = sha1
distinguished_name = req_distinguished_name
prompt             = no
req_extensions     = v3_req
x509_extensions    = v3_ca

[ req_distinguished_name ]
countryName            = &lt;country code&gt;
stateOrProvinceName    = &lt;state&gt;
localityName           = &lt;city&gt;
organizationName       = &lt;whatever, could be your name&gt;
organizationalUnitName = &lt;again, whatever&gt;
commonName             = www.domain1.com

[ v3_req ]
basicConstraints       = CA:FALSE
keyUsage               = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName         = @alt_names

[ v3_ca ]
subjectAltName         = @alt_names

[ alt_names ]
DNS.1 = www.domain1.com
DNS.2 = www.domain2.com
DNS.3 = www.domain3.com


The key that we have generated will have a pass phrase associated with it (the one you entered when you generated the key). This pass phrase will need to be entered every time you restart your apache server. There are ways of removing this extra security, but if you want to do that I’ll let you look that one up elsewhere. For me with a server running on a UPS, I reboot or restart apache a couple of times a year at most. The added security is well woth it. If your server get’s compromised, and it will eventually, then your security key will be coppied. And that is as they say, a bad thing.

And finally, in your site configuration file, probably in /etc/apache2/sites-available, you will need to add the following:

<VirtualHost *:443>
ServerName   www.domain1.com
ServerAlias  domain1.com *.domain1.com
DocumentRoot /var/www/domain1

SSLEngine    On
</VirtualHost>


This is the Virtual host configuration file for your secured site. You’ll want to add any additional configurations to it from your normal *:80 configuration section.

Comment

It was a lot harder than I anticipated to get Movable Type to run from a single global install on all of my virtually hosted domains. So in the spirit of sharing, here’s how I did it.

First, install movable type into a directory at the root of your web servers directory structure. I put mine in /var/www/shared/. The resulting directory structure contained:

/var/www/shared/cgi-bin/mt
This directory contains pretty much everything in the Movable Type tarball.
/var/www/shared/mt-static
This directory is the mt-static directory from the Movable Type tarball. I moved it out to the top level of the shared directory because I have Apache configured to not serve documents from the cgi-bin directory.
/var/www/shared/conf
This directory will contain the configuration files for all of the sites you will be virtually hosting.

Next configure apache for each of your virtually hosted domains. I assume you already have virtual hosting up and running. The configuration file for socialhacker.com looks like this:

<VirtualHost *:80>
ServerName   www.socialhacker.com
ServerAlias  socialhacker.com *.socialhacker.com

DocumentRoot /var/www/socialhacker

SetEnv       MT_HOME     /var/www/shared/cgi-bin/mt
SetEnv       MT_CONFIG   /var/www/shared/conf/socialhacker.cgi
ScriptAlias  /cgi-bin/   /var/www/shared/cgi-bin/
Alias        /mt-static/ /var/www/shared/mt-static/
</VirtualHost>


The important bits here are how you set up the alias’ and the environment variables. And all of this is covered in this article.

Finally, you need to create a configuration file in the shared/conf directry for your site. I did this by hand, which you’ll need to do as well since Movable Type won’t set most of these options in the configuration file it generates.

CGIPath             /cgi-bin/mt/
StaticWebPath       /mt-static/
StaticFilePath      /var/www/shared/mt-static/
PluginPath          /var/www/shared/cgi-bin/mt/plugins/
TemplatePath        /var/www/shared/cgi-bin/mt/tmpl/
WeblogTemplatesPath /var/www/shared/cgi-bin/mt/default_templates/

ObjectDriver        DBI::mysql
DBHost              localhost

MailTransfer        smtp


And there’s the real magic. You have to specify paths to the Static content as well as both Template directories, and the Plugin directory. If you forget the first template directory you won’t get very far as the administrative pages won’t load. But if you forget the second template path you’ll get all the way to making a post and find that all of the files in your blog directory are zero length. If you forget the Plugin path you’ll be missing all of your plugins.

Hopefully you’ve found this useful in setting up your own Movable Type blogs.

Comment