Posts Tagged ‘security’
As anybody who has used Canonical’s wildly popular Linux distribution, Ubuntu, you know that you automatically get 5GB of complementary cloud space on Ubuntu One, Canonical’s cloud service. If you want more than that, you obviously have to pay, but 5GB of cloud data can be very useful, especially now that the Windows Ubuntu One client is out. Perhaps I’ve just got used to using Google’s Chrome so much with it’s marvellous bookmark sync that I’ve been seeing the benefits of having a little data everywhere. Love it or hate it, having a Windows client makes Ubuntu One even more useful. There’s even an Android client available.
So, a dash of data in cloud. Nice. However, I’m still not trusting enough to keep important information in the cloud without a little encryption. Ironic I know, since I have a Google account and GMail tied to my Android phone and all that. But I’ve got Gmail backed up to my server and so, while I now feel I own my Google data (or at least have it backed up safely), there’s really not much you can to to protect yourself from Google itself :-)
Anyway, I digress. As I said, Ubuntu One is pretty useful now it’s multi-platform but if I’m going to store things on there, it’s nice to throw in a little encryption just to be safe. This is different to using something like LUKS encryption, because this works on a partition level, much lower than just dealing with files that you want to transfer. Even a useful encryption tool like TrueCrypt works by preparing a volume container for files, which while very good with a bunch of nice features, is not very handy for storing files on Ubuntu One.
Luckily, Ubuntu (and every other Linux out there) has a portable, standardised method for file encryption, OpenSSL. Here’s how to use it to encrypt your files before launching them off to Ubuntu One.
openssl aes-256-cbc -a -salt -in [UNENCRYPTED_INPUT_FILE_NAME] -out [ENCRYPTED_OUTPUT_FILE_NAME]
This will provide you with a standard AES 256-bit encryption scheme for your file. OpenSSL will prompt you for a pass-phrase, so be as creative as you are paranoid :-) The “aes-256-cbc” parameter specifies the use of 256-bit AES as the cipher and the “-salt” parameter adds a salt to the encryption setup for added security which helps foil dictionary attacks.
As long as somebody knows the pass-phrase (hopefully just you!), they can decrypt the file by using:-
openssl aes-256-cbc -d -a -in [ENCRYPTED_INPUT_FILE_NAME] -out [DECRYPTED_OUTPUT_FILE_NAME]
If you want to do this on the Windows side of things, you can use the Windows OpenSSL software as well. There you go – encryption for everybody :-)
If you want to encrypt a large number of files at once, you can always tar or zip then up first with (under Linux at least):-
tar -cf [TAR_FILE_NAME].tar [DIRECTORY_WITH_FILES_TO_TAR]
…and then use gzip to make the files a bit smaller before encrypting them. I don’t encrypt everything of course but it’s nice to have the option.
UPDATE 05/01/2012: There is now also an iOS Ubuntu One client available for Apple fans. I think Ubuntu One now has a client for pretty much every platform. Good going Canonical :D
ClamAV antivirus software is in most Linux distribution repositories. The problem is, ClamAV gets updated faster than the new versions can be added to the respositories, so every time you run a freshclam virus database update, ClamAV will inform you that it’s not the latest version. Not ideal, especially when you’re talking about security.
The only way to get the latest latest version is to download the stable source code release direct from ClamAV’s website and install it manually. Which is what we’re going to do :-)
First, you’ll need to grab the source code. You can download the tar.gz file here for the latest stable release version. As of the time of writing, the latest version is 0.97.1. I’m just going to copy the download URL and download it with wget.
wget http://downloads.sourceforge.net/clamav/clamav-0.97.1.tar.gz
Then you’ll need to unpack the archive.
gunzip http://downloads.sourceforge.net/clamav/clamav-0.97.1.tar.gz
tar -xf clamav-0.97.1.tar
cd clamav-0.97.1
Okay, you should now be in the ClamAV directory. I want to install my new version of ClamAV in ‘/usr/local/clamav-0.97.1′. So I’ll need to configure it to install to that directory. If you run into dependency problems, you’ll probably need to install GCC/Make if it isn’t already. If you do need to do this, you can do it under Fedora with: -
yum install gcc make
…and under Debian/Ubuntu with: -
sudo apt-get install gcc make
Once you’ve got all the prerequisites installed, you can run the configure script. Make sure you’re still in the sub-directory where you unpackged the archive and run: -
./configure --prefix=/usr/local/clamav-0.97.1
Once this is complete and you have no errors, you can run: -
make
make install
This will install the new version of ClamAV to the directory you specified in the configure script. If you have the version of ClamAV installed from your distribution’s repositories, you have two choices. You can either keep the repository version and use aliasing to run the version you want or you can uninstall the repo version and add append the path to the system $PATH environment variable. I’ll show you both.
Assuming you want to keep the version of ClamAV you have in case it ever gets updated via the repositories, you’ll need to copy your ‘/etc/freshclam.conf’ to the new location.
cp /etc/freshclam.conf /usr/local/clamav-0.97.1/etc
However, if you try to run ClamAV from anywhere but the ‘/usr/local/clamav-0.97.1/bin’ directory where the program executables are, you’ll still get the warning that ClamAV is out of date. This is because the system $PATH variable finds the old version first as it’s part of the system path. We want to override this and run our new manually installed version. Since we’re only going to be running ClamAV with the root user so that we have permissions to scan the entire file system, we’ll add a new alias.
vi ~/.bashrc
Then add the following lines:-
alias clamscan='/usr/local/clamav-0.97.1/bin/clamscan'
alias freshclam='/usr/local/clamav-0.97.1/bin/freshclam'
alias clamd='/usr/local/clamav-0.97.1/sbin/clamd'
Aliases are very handy. Basically, when the alias is typed as a command, it points to the command we specify, regardless of what is in the system $PATH environment variable. Save this file and logout. The new settings for the ‘.bashrc’ file are only picked up on login of that user. Once you login again you should be running the latest version of ClamAV.
If you want to remove the repo version of ClamAV, you’ll need to uninstall it. Under Fedora, use: -
yum remove clamav-*
…and under Debian/Ubuntu use: -
sudo apt-get remove clamav-*
Once this is done, you’ll need to add the new ClamAV to the system path. Under Fedora, this is: -
vi /etc/profile
Under Debian/Ubuntu, this is under: -
vi /etc/environment
Find the following section, or something that looks similar: -
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
Above this line add the line: -
export PATH=$PATH:/usr/local/clamav-0.97.1/bin
This appends the path to the binary directory of our new ClamAV to the system path. Again, for this to take effect, you’ll need to logout and log back in again. You can verify the path by typing: -
echo $PATH
When you simply run freshclam to update, it should find the configuration file under it’s own /etc directory and you should now be able to scan the filesystem using ‘clamscan’ without having to type in the absolute path to the new binary executable.
One thing you might want to be aware of is that quite a lot of distributions have pre-set up cron to periodically update the version installed from the distribution repositories. But of course now, even though you have the newer version of ClamAV installed in /usr/local, it will keep issuing system log or e-mail alerts saying it is out of date. This is all the fault of the default cron task that runs it’s own absolute path to the repo-installed version of ClamAV. You can deal with this in two ways, either simply remove the ClamAV that is already installed with: -
yum remove clamav-*
or disable the cron task. This is a small script file which resides in ‘/etc/cron.d/clamupdate’ (at least in Fedora). Either delete this file or commend out it’s contents.
With residential broadband, you only get one IP address typically and that isn’t even usually static – pretty unsuitable for servers at home. You can get round this problem with dynamic DNS services which allow you to update your DNS record each time your ISP-assigned IP address changes. But this still means that the only machine visible to the Internet at large is that server and only that server. All your other machines behind your router have DHCP-assigned IP addresses which are private to that internal network, like 192.168.1.43. These machines are not visible to the Internet, only the router is.
A router is really just a specialised computer server that directs Internet traffic to the right destination. A Linux server itself might be the gateway server. Indeed, to get dynamic DNS to work, you also have to configure traffic to route the traffic from the outside to your Linux server.
For the purposes of this article, I’ll assume the router and gateway are the same machine. If not, the router will be configured in such a way that it routes all traffic to the gateway server so that, in practical terms, they are the same.
So what happens if you want to have a web server on a separate machine on your network? Well, technically you can’t – it only has a private (or ‘local’) IP address. But you can cheat using a method called port forwarding. This allows the gateway server to change the destination and source of the data packets based on certain criteria dynamically which allows packets destined for the gateway server to be rewritten for the new web server with it’s private IP address. The gateway server also needs to be able to send packets back out of the local network to the originating client because the internal web server will only be talking to the gateway server so it’s packets source address needs to be rewritten.
So we need a mechanism that that distinguish between traffic meant for the gateway server and traffic
So if Internet traffic is hitting the gateway server with it’s static IP address (or at least host name and DynDNS), that traffic is destined for the gateway server. It doesn’t know anything about the web server on the internal network. The gateway server’s firewall has to decide which packets are for itself and which packets should be passed to the web server which only the gateway server knows about. The easiest way to distinguish the traffic is send the web server traffic to another non-standard port. I’ll use 7070.
Think about two web servers in this scenario, the gateway and internal. Normal web traffic will hit the gateway server (public IP address of 89.232.33.123 and therefore visible to the Internet) on the standard port 80. Web traffic for the internal web server will hit port 7070 on the same gateway server and the it knows to re-route the destination for each packet to the internal private IP address of 192.168.1.43 because of the non-standard port.
So if a client requests 89.232.33.123:80 they’ll get a reply from the gateway server as normal. If a client requests 89.232.33.123:7070 (note the same IP address of the gateway) the client will get a reply that appears to be from 89.232.33.123 but is actually from 192.168.1.43, the internal web server.
If you want more than one machine visible to the outside world but only have the one static IP address, you can configure the gateway Linux server to to route traffic to anywhere you like using iptables. While iptables is primarily a firewall, the rules you can set up to deny or allow a specific packet are flexible enough to allow traffic routing as well.
On the gateway server which is accessible from the Internet, open the iptables configuration file.
vi /etc/sysconfig/iptables-config
Add the following line: -
IPTABLES_MODULES="iptable_nat"
This adds the Network Address Translation (NAT) kernel module to the system so that iptables can use NAT. This will allow iptables to hold the packets before comparing them to the NAT table we will create.
Open a new file under /etc/sysconfig called iptables.NAT-RULES.
vi /etc/sysconfig/iptables.NAT-RULES
This will hold all our iptables configuration rules. First thing we need to do define our network address translation rules. The first rules will be to reset everything so that nothing gets in.
*nat
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
Next, we’ll switch on masquerading. This is known as “many-to-one NAT”. In other words, traffic from all devices on one or more protected networks will appear as if it originated from a single IP address on the Internet side of the firewall. The masquerade IP address always defaults to the IP address of the firewall’s main interface. The advantage of this is that you never have to specify the NAT IP address. This makes it much easier to configure iptables NAT with DHCP, which we are doing as the internal web server has a DHCP-assigned address rather than a static address.
-A POSTROUTING -o eth0 -j MASQUERADE
-A PREROUTING -i eth0 -p tcp --dport 7070 -j DNAT --to-destination 192.168.1.43:80
COMMIT
The next line is the real “meat” of the NAT table. If the gateway gets a data packet on port 7070 of the main ethernet card (eth0), it should send it on to 192.168.1.43 on the internal network on it’s port 80 (HTTP traffic). These rules are then committed to the NAT table. Next, iptables deals the filters – the main firewall configuration which will allow or deny data packets.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
Again, you can see the configuration is reset first. Next, comes the first section of filter rules which are the INPUT rules, or the rules governing what the firewall does with incoming packets.
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
The first line allows data packets through to wherever they want to go assuming that the connection has already been established. The next line simply states that we will accept ICMP or (‘ping’) packets used for network diagnostics. The next section deals with the actual ports that the firewall will accept.
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7070 -j ACCEPT
The first line above appends a new rule to the rule-set accepting new connections on TCP port 22 (which is the port for remote access SSH). The next line does the same for our custom 7070 port which will handle web traffic from the internal web server. Next we come to the FORWARDing rules for the firewall, what it does with the packets it’s accepting.
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -o eth0 -j ACCEPT
-A FORWARD -p 7070 -m state --state NEW -m tcp -p tcp -d 192.168.1.43 --dport 80 -j ACCEPT
Again, it’ll accept established connections for forwarding, these are default settings for the most part. The last line is the most important, where it forwards the port 7070 to the internal web server.
Here is the completed iptables rule-set for NAT and filtering.
*nat
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
-A PREROUTING -i eth0 -p tcp --dport 7070 -j DNAT --to-destination 192.168.1.43:80
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7070 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -i lo -j ACCEPT
-A FORWARD -p 7070 -m state --state NEW -m tcp -p tcp -d 192.168.1.43 --dport 80 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
This concludes the quick n’ dirty guide to port forwarding with iptables :-)
Firstly, be warned – this is a long article. LDAP is non-trivial, but if you’ve mastered NIS/NFS, this is the next step :-)
The Lightweight Directory Access Protocol, better known as LDAP is what is known as a directory service, much like Windows’ Active Directory. Indeed, Active Directory is the Windows implementation of LDAP so you’ve probably heard to LDAP without even being aware of it :-) Like Active Directory, you can store all sorts of information in an LDAP database and because it’s standards-based and cross-platform, you can read this information securely from anywhere using any LDAP-aware application. Strictly speaking, LDAP isn’t a database system but a protocol used to access information stored in an information directory also known as an LDAP directory. LDAP is particularly useful for storing information that you wish to read from many locations, but update infrequently.
While you can store all sorts of information in an LDAP directory, we’re going to use it to store Linux user login credentials and access the LDAP directory whenever we want to login to any machine on our network rather than the local user credentials. Assuming you’ve been wanting to set up something like this, you may be asking why you don’t just use NIS/NFS. In the past encrypted passwords contained in ‘/etc/passwd’ or ‘/etc/shadow’ were distributed by NIS, thus making it act as an authentication as well as authorisation server. Nowadays, this technique is not so suitable because it involves moving the password over an open and insecure network where a sniffer could capture it and, with the processing power currently available, unencrypt it in a few machine hours. NIS is fine for simple solutions on an trusted intranet but unsuitable as an enterprise solution. Also, unlike NIS, LDAP is expandable, which means that the type of data it can represent is not established beforehand by the protocol, but can be changed by the administrator by adding schemas. NIS operates on “flat” domains and is therefore unsuitable for large organisations which due to their nature may be organised hierarchically in a “tree” structure.
Fedora ships its own LDAP based server but we will be using the OpenLDAP implementation with Berkley Database (bdb) as the database backend. Data is entered into the LDAP server via plain text LDIF (LDAP Data Interchange Format) files.
This exercise assumes that you’ve got a networked Fedora install working and that you’ve assigned it a host name that is reachable via DNS. If you don’t have a static IP address that you can assign a host name, you can set one up using Dynamic DNS. Make note of the IP address of the server – for the purposes of this, I’ll assume it’s ’192.168.1.2′ internally as we’re using this on a home network.
If you want to test that your server which you’re going to use as a LDAP server on your network has a fully qualified domain name (FQDN), you can run: -
dig [your_host_name]
Configuring the LDAP server
Obviously, you’ll also need to be root for this :-) Okay, let’s get started. First you’ll need to install the OpenLDAP packages.
yum install openldap-servers migrationtools openldap openldap-clients openldap-devel nss_ldap
Next, you’ll need to create an LDAP root user – this is similar to a regular Linux root user in that it has entire control over your LDAP directory service. Do so with: -
slappasswd
This will ask you to enter a password and return the SHA-encrypted hash of the password. It will be something like: -
{SSHA}MP0BeMJzmCoCi5olBhwcRDYJaGBFgN5D
Make a note of this string, as you will need it later on.
First you need to set up an LDAP user. Enter the following commands: -
useradd ldap.ldap
and set a password for it.
passwd ldap
Next, you need to set up a directory for your database and give is the right access permissions. We’re going to use the domain ‘ldap.test.lan’
mkdir /var/lib/ldap/ldap.test.lan
…and similarly give our LDAP users access permissions: -
chown -R ldap.ldap /var/lib/ldap/ldap.test.lan
The base configuration
Now we need to set up our base configuration. You’ll need to delete the /etc/openldap/slapd.d directory or rename it as else Fedora will ignore our configuration and use the one under slapd.d. I’m just going to rename it.
mv /etc/openldap/slapd.d /etc/openldap/slapd.d.DEFAULT
Then we’ll create a configuration file. This is actually the “old” way of doing things, but it’s far simpler than running through the mess of auto-generated configuration files under the slapd.d sub-directory.
vi /etc/openldap/slapd.conf
Add the following, changing the example host for yours.
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
database bdb
suffix "dc=ldap,dc=test,dc=lan"
rootdn "cn=admin,dc=ldap,dc=test,dc=lan"
rootpw {SSHA}MP0BeMJzmCoCi5olBhwcRDYJaGBFgN5D
directory /var/lib/ldap/ldap.test.lan
TLSCipherSuite HIGH:MEDIUM:+SSLv2:+SSLv3:RSA
TLSCACertificateFile /etc/openldap/ssl/ldap-server.pem
TLSCertificateFile /etc/openldap/ssl/ldap-server.pem
TLSCertificateKeyFile /etc/openldap/ssl/ldap-server.pem
TLSVerifyClient allow
This creates database of the default type ‘bdb’ (Berkeley Database) using the domain suffix ldap.test.lan made up of domain components (DCs) ‘ldap’, ‘test’ and ‘lan’. It then creates the root user with a common name (CN) or nickname of ‘admin’ who, as expected, is part of the ‘ldap’, ‘test’ and ‘lan’ DCs. Lastly, it defines the encrypted version of the LDAP root password you created earlier as well as the location of the LDAP database within the file system and tell LDAP where to find the certificate and key files for encryption.
Because we are using LDAP for authentication across a network, we’ll need to encrypt the traffic, which is what the encryption key entries above are all about and is one of the key differences with something like NIS. We need to tell Fedora how to start the secure LDAP daemon which is done by editing the sysconfig entry for ldap: -
vi /etc/sysconfig/ldap
Add the following line or uncomment the one that’s there and set it to ‘yes’.
SLAPD_LDAPS=yes
Save this and return to the command line. We can now run LDAP on default port of 389 with TLS. Of course, we’ll have to create some encryption keys for this. Run the following which will create encryption keys in the location we specified in the ‘/etc/openldap/slapd.conf’ file:-
openssl req -newkey rsa:1024 -x509 -nodes -out /etc/openldap/ssl/ldap-server.pem -keyout /etc/openldap/ssl/ldap-server.pem -days 365
Make sure the following sections are filled in with your host details.
Common Name (eg, your name or your server's hostname) []: ldap.test.lan
Email Address []: user@test.lan
You also need to set these directories to something that the ldap user can read: -
chown -rf root.ldap /etc/openldap/ssl
chmod -rf 750 /etc/openldap/ssl
Check that the ‘/etc/openldap/ssl/ldap-server.pem’ private key file exists and is of the right format: -
cat /etc/openldap/ssl/ldap-server.pem
It should look something like: -
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDj64XGJe1uA1Ybr/1kWTsQcxktU7W9i29OkbmFwI1hc8qYXuO5
qAAGCFHHupInzy9uoXJVvGW3yEw0gasLR6hzyC2+1b8vfG3Eb0yN+Yt4mGp03iiX
c0pzQrEw+HxYcsA0KAUCQDKCo5OTBB0FLpH+ZgTqkeBabt3lNYFphAqEqLyC6q10
+WMlWY/jvLyQYldbvP3ENgahGKlv99SKytSb9MFQlnc=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC+DCCAmGgAwIBAgIJAKhuyXeddEVVMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV
BAYTAkdCMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAV
5/ncthk9QyZwLrz1/WEC/9qbST/aYGEz4lOMc8tPu9vKh9CAYI42J6zu51Y=
-----END CERTIFICATE-----
Each client will need the ‘certificate’ part of the file, so we can use the grep command to extract this information.
grep -A 100 CERTIFICATE /etc/openldap/ssl/ldap-server.pem > /etc/openldap/ssl/ldap-client.pem
The ‘/etc/openldap/slapd.conf’ file now references our key to activate TLS encryption of all incoming connections to the server. The LDAP daemon won’t start properly unless the files in the ‘/etc/openldap/ssl directory’ are owned by the ldap user. We need to make sure of this with: -
chown -R ldap.ldap /etc/openldap/ssl
The next step is to configure the migration tools used to migrate your existing users into LDAP. To do this, you need to edit the migrate_common.ph file: -
vi /usr/share/migrationtools/migrate_common.ph
The only things you need to change are the lines below. The DEFAULT_BASE should be set to your host.
# Default DNS domain
$DEFAULT_MAIL_DOMAIN = "localhost";
# Default base
$DEFAULT_BASE = "dc=ldap,dc=test,dc=lan";
You now need to copy a default DB_CONFIG file which sets cache and tuning options for the Berkley database backend (this also needs to be writeable by the ldap user). This file may be under a different directory depending on your version of Fedora, but you can find it with: -
find /usr -name "DB_CONFIG.example" -print
Assuming this is found in ‘/usr/share/openldap-servers/DB_CONFIG.example’, you need to copy this example file to your /var/lib/ldap directory and rename it as DB_CONFIG.
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
Once you’ve done this, you need to make sure that the ldap user has access to it: -
chown -rf ldap.ldap /var/lib/ldap
Lastly, test your configuration by running the command, and check that it returns ‘config file testing succeeded’:-
slaptest -u
If you have no problems, you’ve successfully completed your basic LDAP server configuration. You should now be able to start your slapd service with the following: -
service slapd start
You can test that the service started correctly and is listening on the LDAPS port with: -
netstat -lt | grep ldap
You should get back something like: -
tcp 0 0 *:ldap *:* LISTEN
tcp 0 0 *:ldaps *:* LISTEN
If everything looks good, set slapd to start on boot with: -
chkconfig slapd on
To test the server configuration, run: -
ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
which should return success as below: -
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#
#
dn:
namingContexts: dc=ldap,dc=test,dc=lan
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
We should now have a base LDAP server running and configured for our LDAP domain. However we do not have any users (People) or groups (Group) configured from our /etc/passwd, /etc/shadow and /etc/group files. So now we need to set up our base, authentication and group files. This is done via a migration of your existing local UNIX accounts already configured on the server which are converted into an LDIF file for loading into LDAP. First however, we need to create a template ‘base.ldif’ file which creates the base structure of our directory (ldap.test.lan), which we will import into the LDAP database first.
Configuring the base LDAP entry
vi ~/base.ldif
Add the following, replacing dn and dc entries with the dc’s from your host.
dn: dc=ldap,dc=test,dc=lan
dc: test
objectClass: top
objectClass: domain
dn: ou=People,dc=ldap,dc=test,dc=lan
ou: People
objectClass: top
objectClass: organizationalUnit
dn: ou=Group,dc=ldap,dc=test,dc=lan
ou: Group
objectClass: top
objectClass: organizationalUnit
Now that we have the base information for our LDAP database structure, we can import that information into our LDAP database (using the password you created above:-
ldapadd -x -W -D "cn=admin,dc=ldap,dc=test,dc=lan" -f ~/base.ldif
You should get some output similar to the following: -
Enter LDAP Password:
adding new entry "dc=ldap,dc=test,dc=lan"
adding new entry "ou=People,dc=ldap,dc=test,dc=lan"
adding new entry "ou=Group,dc=ldap,dc=test,dc=lan"
Importing users as LDAP People entries
Now, we will use the migration script whose settings we modified earlier to create an .ldif file which we will use to populate LDAP with all our existing users pulled from ‘/etc/passwd’.
/usr/share/migrationtools/migrate_passwd.pl /etc/passwd ~/people.ldif
Once you’ve created this .ldif file, the entries can be imported into LDAP:-
ldapadd -x -W -D "cn=admin,dc=ldap,dc=test,dc=lan" -f ~/people.ldif
Importing groups as LDAP Group entries
We will now do the same with the user groups with the following: -
/usr/share/migrationtools/migrate_group.pl /etc/group ~/group.ldif
…and then import the group entries into LDAP: -
ldapadd -x -W -D "cn=admin,dc=test,dc=lan" -f ~/group.ldif
Now that we have our LDAP database populated with user information, it’s time to test our work. You can use the ldapsearch command to look for your username as below: -
ldapsearch -x "cn=[user]"
You should get something back like: -
# extended LDIF
#
...
# user, Group, ldap.test.lan
dn: cn=user,ou=Group,dc=ldap,dc=test,dc=lan
objectClass: posixGroup
objectClass: top
cn: [user]
userPassword:: R2NyfXE0fDPJ=
gidNumber: 500
# search result
search: 2
result: 0 Success
...
Add new LDAP People/Group entries
That will have imported the user details present on the server into LDAP. But it’s safe to assume that you’ll want to add other users. To add a new user, you’d create a .ldif for the user account and the group. Then we import these files into the LDAP server like we did with the base, people and groups details previously.
For example, if I wanted to add a user called ‘david’, I’d create a ‘david.ldif’ file such as below: -
vi ~/david-user.ldif
…and populate it with: -
dn: uid=david,ou=People,dc=ldap,dc=test,dc=lan
uid: david
cn: David Lightman
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
userPassword: {crypt}$6$XemGNmYE5f3QAFo/vt7Uld/gUcP/2N7/R.uw5SK.
shadowLastChange: 14846
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 501
gidNumber: 501
homeDirectory: /home/david
gecos: David Ligntman
Then the same process for the group: -
vi ~/david-group.ldif
Populated with: -
dn: cn=david,ou=Group,dc=ldap,dc=test,dc=lan
objectClass: posixGroup
objectClass: top
cn: david
userPassword: {crypt}x
gidNumber: 501
You’ll notice the password has an ‘x’ in it, much like the ‘/etc/passwd’ entry for the encrypted password, as all passwords are kept in ‘/etc//shadow’ these days. Similar format, though. Lastly, these files will be added to LDAP: -
# ldapadd -x -W -D "cn=admin,dc=ldap,dc=test,dc=lan" -f ~/david-user.ldif
Enter LDAP Password:
adding new entry "uid=david,ou=People,dc=ldap,dc=test,dc=lan"
# ldapadd -x -W -D "cn=admin,dc=ldap,dc=test,dc=lan" -f ~/david-group.ldif
Enter LDAP Password:
adding new entry "cn=david,ou=Group,dc=ldap,dc=test,dc=lan"
…and you should now have a new user called ‘david’. The absolute last thing you need to do is open a port in your firewall for LDAP to listen on. Since the default LDAP port is 389, we’ll open that using iptables.
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 389 -j ACCEPT
That’s the LDAP server configuration and data migration done.
Client LDAP configuration
Right, the next next is to step up a client Fedora system to authenticate via the LDAP server. First, make sure you have installed the required packages: -
yum -y install openldap openldap-clients openldap-devel nss_ldap
LDAP clients are configured using the ‘/etc/openldap/ldap.conf’ file. You need to make sure that the file refers to the LDAP server’s IP address for the domain ‘ldap.test.lan’ which we set up. So, edit the config file with: -
vi /etc/openldap/ldap.conf
Make sure it looks something like this: -
HOST 192.168.1.2
BASE dc=ldap,dc=test,dc=lan
Next, we’ll need to tweak the ‘/etc/nsswitch.conf’ file. This configuration file defines the order in which the operating system searches login databases for login information when users attempt to login. You’ll want to configure it to first search its ‘/etc/passwd’ file. If it doesn’t find the user password information there, it goes to the LDAP server. The easiest way set this up is to use the ‘/usr/bin/authconfig-tui’ command, which provides a graphical tool.
1. Select LDAP.
2. Give the LDAP server’s IP address, which is 192.168.1.2 in this case.
3. Give the base DN as dc=ldap,dc=test,dc=lan
4. Select TLS.
5. Use MD5 and shadow passwords.
When you’re done, look at the ‘/etc/nsswitch.conf’ file and make sure it has references to LDAP. It should look something like: -
passwd: files ldap
shadow: files ldap
group: files ldap
hosts: files dns
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
netgroup: files ldap
publickey: nisplus
automount: files ldap
aliases: files nisplus
You’ll need to copy the encryption key from the server’s ‘/etc/openldap/ssl/ldap-client.pem’ location to ‘/etc/openldap/cacerts’. You can use sftp for this: -
# cd /etc/openldap/cacerts
# sftp root@192.168.1.2 -p 22
get /etc/openldap/ssl/ldap-client.pem
bye
You previously created a user named ‘ldap’ in the group on the LDAP server. You now need to make sure that this user has a home directory on the LDAP client. The example in this section creates the directory and makes ldap the owner. As you can see, the LDAP server correctly gets its user information about ‘ldap’ from 192.168.1.2; the chown command doesn’t complain about the ‘ldap’ user not existing in the client’s ‘/etc/passwd’ file.
Check that the ldap user doesn’t exist in the client’s ‘/etc/passwd’ file.
grep ldap /etc/passwd
There shouldn’t be anything returned. Next, you’ll create the home directory, copy a Bash login profile file into it, and modify the ownership of the directory and all the files to user ‘ldap’:-
# mkdir /home/ldap
# chmod 700 /home/ldap/
# chown -R ldap.ldap /home/ldap
# ls -la /home
Next you need to edit the /etc/ldap.conf file: -
vi /etc/ldap.conf
And make sure it looks something like: -
uri ldaps://ldap.test.lan/
#ssl start_tls
tls_cacertdir /etc/openldap/cacerts
Testing your LDAP client/server setup
Restart your LDAP server service to make sure all configuration is loaded and then to test, open another terminal window on the client and try to login as an LDAP-only user, such as the ‘david’ account we set up earlier: -
su - david
You should be able to login fine! :-) If not, check your /var/log/messages file for any error messages which might tell you what went wrong. But that is about it! Further documentation on the uses of LDAP can be found here.
This covers essentially 99% of all Android devices, sadly. Due to weak ClientLogin authentication protocols, users who sign into external services for data syncing on Android handsets have their authToken stored for 14 days and are apparently accessible if you know what you’re doing. After a user submits valid credentials for a Google account and other services (Facebook, Twitter, etc), the programming interface retrieves an authentication token that is sent in cleartext. Because the authToken can be used for up to 14 days in any subsequent requests on the service, attackers can exploit them to gain unauthorized access to accounts. The attacks can only be carried out when the devices are using unsecured networks, such as those offered at Wi-Fi hotspots, for example.
While Google has patched this vulnerability, only handsets that have access to Android 2.3.4 are secure – this essentially means only the Google Nexus S at present as this is Google’s reference implementation handset which gets updates way before anybody else.
If you have a Google Nexus S and aren’t sure what version of Android you have, go to Settings -> About Phone and look for the Android version. If you’re still running 2.3.3, go to System Updates and you should find that the 2.3.4 update is available for installation.
Researchers Bastian Könings, Jens Nickels, and Florian Schaub warned that the weaknesses could be used against people who use their Android devices on networks under the control of an attacker.
“To collect such authTokens on a large scale an adversary could setup a wifi access point with a common SSID (evil twin) of an unencrypted wireless network, e.g., T-Mobile, attwifi, starbucks,” they wrote. “With default settings, Android phones automatically connect to a previously known network and many apps will attempt syncing immediately. While syncing would fail (unless the adversary forwards the requests), the adversary would capture authTokens for each service that attempted syncing.”
The researchers recommend using SSL (HTTPS) connections whenever possible on unsecured WiFi networks, but frankly you should be doing that anyway regardless of device :-D Regular HTTP connections transmit an alarming amount of information in plain text, which was what the Firesheep Firefox plugin was meant to illustrate.
Upgrade if you can and if you can’t pester your carrier to roll out prompt updates. Many handsets still only have Android 2.2 or earlier and regardless of Google’s wishes, many carriers haven’t rolled out 2.3 at all as of yet. Just another reason to avoid public WiFi hotspots.
UPDATE 19/05/2011: – Looks like Google is pushing out a fix for all Android phones. From Gizmondo…
So Google’s pushing a fix right now that’ll patch up the vulnerability for every Android phone over the next few days. It’ll fix the problem for Contacts and Calendars immediately, though not for Picasa—there’s something different there technically, according to a Google spokesperson. (Any idea why, dear readers?) It won’t require you or your carrier to do anything—it’ll just like, happen, sometime in the next few days.
…so that’s a relief.
Sometimes, let’s be frank, you just want to block certain countries from accessing your server. This may be for legal reasons or because…ahem…certain countries are more likely to have hackers and other miscreants attempting to do bad things to your server. Depending on your server’s purpose, it may be easier to simply block the offending countries from accessing your server completely.
As explained in this article, I have set iptables to have a file called /etc/sysconfig/iptables.BACKUP, which is a set of iptables rules that open all the default ports that I want for the services my server offers. It’s exactly the same as the /etc/sysconfig/iptables file, except that it’s backed up. This way, whenever I do anything to the iptables ruleset, I can always be sure that the services I want are available, regardless of whatever else I do with iptables. This becomes important when using the script I am about to show you…
1 #!/bin/bash
2 TEMP_DIR=/tmp/
3 LANG_SETTINGS_DIR=/root/langblock.cfg
4 /bin/cp -rf /etc/sysconfig/iptables.BACKUP /etc/sysconfig/iptables
5 /etc/rc.d/init.d/iptables restart
6 for lang in $(cat ${LANG_SETTINGS_DIR})
7 do
8 wget --output-document=${TEMP_DIR}${lang}.zone http://www.ipdeny.com/ipblocks/data/countries/${lang}.zone
9 for line in $(cat ${TEMP_DIR}${lang}.zone)
10 do
11 /sbin/iptables -I INPUT -s ${line} -i eth0 -j DROP
12 echo "Adding...$line from file: ${TEMP_DIR}${lang}.zone"
13 done
14 /bin/rm ${TEMP_DIR}${lang}.zone
15 done
16 exit 0
Save this as “ipblock.sh” or somesuch in your root user directory and make it executable with: -
chmod u+x ipblock.sh
Next, you’ll need to create a text file called “langblock.cfg”. You can obviously change the path to this file in LANG_SETTINGS_DIR. This will contain international two-letter country codes, a list of which is available here. Each two-letter country code must be on a separate line like: -
country1
country2
...
country7
…and so on. Next, you’ll have to make sure you have the “wget” utility installed. This can be installed on Fedora with: -
yum install wget
and…
sudo apt-get install wget
…under Ubuntu. Once you’ve got all this set up, run the script above. It’s fairly simple as scripts go – first, it reloads your default iptables ruleset from /etc/sysconfig/iptables.BACKUP into /etc/sysconfig/iptables and restarts the iptables firewall. Next, it steps through each line in your langblock.cfg config file and downloads the IP address blocks for that country from ipdeny.com using wget to the /tmp directory. It then reads this file, adding each IP address block to the iptables ruleset as IP addresses to DROP upon connection. Once the end of the file is reached, the file is deleted from the /tmp directory and the program moves on to the next country code in the langblock.cfg file or, if it’s the end of the file, it quits.
You have now successfully block those countries from accessing your server :-) You could add this script to a cronjob to run every month to refresh the list if you like. Like I said, this will probably be considered by some to be an extreme measure to take in the name of security, but should you have the need to do this, you can.
Last time I talked about protecting your server from brute force attacks against your server, but what about the enemy within, like root-kits and viruses? Everybody is familiar with computer viruses these days, especially if you’re using Windows and entire industries have sprung up to combat this threat. While it’s true that viruses are commonly written to target Windows systems and rarely if ever affect Linux machines, they can still be present on your system even if they are incapable of doing any damage. Although they may be harmless on your Linux system (for now), you still want a way of getting rid of them, especially if you use your Linux server as a Windows file server with technologies like Samba.
While there are many commercial virus scanners available for Linux, I am going to concentrate on ClamAV, an open source virus scanner that is primarily intended as an email scanner for servers. While this is true, you can still use it as a stand-alone virus scanner and, being open source, the virus updates are free.
ClamAV is available for most Linux distributions, including Ubuntu and Fedora. To install ClamAV if it isn’t already on your system, you can install it with Fedora using: -
yum install clamav-*
and under Ubuntu, you can install it with: -
sudo apt-get install clamav*
If you’re using Ubuntu or Fedora as a desktop system with GNOME, you can use clamtk as a nice front-end for virus scanning by simply running: -
clamtk
After that, the user-interface is pretty straight-forward and I imagine you can work it without any help. However, I’ll concentrate on using ClamAV in a server environment, as that is my primary interest :-)
Once ClamAV is installed, you can get the latest virus definitions database with: -
/usr/bin/freshclam
and if your virus definition is up to date, you’ll see out something like: -
main.cld is up to date (version: 52, sigs: 704727, f-level: 44, builder: sven)
daily.cld is up to date (version: 12038, sigs: 132716, f-level: 53, builder: guitar)
bytecode.cld is up to date (version: 74, sigs: 10, f-level: 53, builder: edwin)
Once this is done, running ClamAV is simplicity itself: -
clamscan -r -l /var/log/scan.log /home/user
The above runs ClamAV recursively against the “home/user” directory and puts the output of the scan into file /var/log/scan.log. Once the scan is completed you can either check the log file manually, or run a quick grep to see if it found anything: -
cat /var/log/scan.log | grep FOUND >> /var/log/found.log
This outputs any “FOUND” entries to /var/log/found.log along with the complete file path to the suspect files. Very useful! I like to setup ClamAV to run as a cron job with something like the following (remember to run as root!): -
My avscan.sh bash script file looks like this: -
#!/bin/bash
/usr/bin/clamscan -r /home >> /var/log/scan.log
cat /var/log/scan.log | grep FOUND >> /var/log/found.log
This will check every user’s /home directory for viruses. Remember to make your script file executable with
chmod u+x avscan.sh
I then add a cron job by running: -
crontab -e
and adding the entries: -
0 1 * * * /usr/bin/freshclam >> /var/log/freshclam.log
0 4 * * * /root/avscan.sh
This will run a virus definition file check at 1am every day and append the output of this check to the /var/log/freshclam.log file and then run the above virus scanning script at 4am every day, appending the output to the /var/log/avscan.log. This should alert you to any viruses present on your system.
Okay, so that’s viruses out the way, what are root-kits then? A root-kit is a piece of software that enables continued privileged access to your system while actively hiding its presence from the administrator by posing as some innocuous system command. Typically, a hacker installs a root-kit on a computer after having first obtaining user-level access, either by exploiting a known vulnerability or cracking a password via brute force methods like I discussed before. Once a root-kit is installed, it allows an attacker to mask his intrusion while gaining root or privileged access to the machine. So it’s a good idea to scan for known root-kits on your system in much the same way as you would for viruses. For this, I’m going to use a utility called rkhunter, which is a root-kit scanner for *nix systems. It will scan your system for known root-kits, backdoors into your system or suspicious files and alert you if it finds anything. It works by comparing SHA-1 encryption hashes of important files with known good ones in it’s online database and searching for default directories of known root-kits, wrong permissions, hidden files, suspicious strings in kernel modules and things like that. Be warned, like all root-kit scanners, it does sometimes come up with false positives which I will cover in a bit. First we have to install it on our Fedora system with: -
yum install rkhunter
and under Ubuntu with: -
sudo apt-get rkhunter
You can even install it from source if you’re using another distribution with: -
wget -c http://downloads.rootkit.nl/rkhunter-1.3.6.tar.gz
tar -zxvf rkhunter-1.3.6.tar.gz
cd rkhunter-1.3.6
./installer.sh
Once rkhunter is installed, you should first update rkhunter’s database with the latest known root-kits to search for: -
rkhunter –update
Once you’re up to date, you can run rkhunter directly with: -
rkhunter -c -sk
This will output the results by default to /var/log/rkhunter/rkhunter.log. The -sk flag simply overrides rkhunter’s propensity of asking you to press “enter” after each section of the scan. If you want to review the output as it happens, you can miss out this switch. After a while, you’ll get a summary something like: -
System checks summary
=====================
File properties checks...
Files checked: 135
Suspect files: 0
Rootkit checks...
Rootkits checked : 250
Possible rootkits: 0
Applications checks...
All checks skipped
The system checks took: 11 minutes and 1 second
All results have been written to the log file (/var/log/rkhunter/rkhunter.log)
No warnings were found while checking the system.
In this sample, the system is clean and nothing untoward was detected.
I’ve got a positive! Is it real?
Probably not, although it doesn’t hurt to check. Remember that rkhunter stores the SHA-1 hashes of significant files on your system in it’s database. If you’ve recently updated your system, these files will be out of sync with rkhunter. If you’re unsure if you have been rooted or not, you can reinstall these files with yum or via an RPM file or a backup. For example, say that rkhunter states that the “mailx” application is actually now a root-kit, I could use yum to reinstall that package: -
yum reinstall mailx
…just to be safe. You can then update rkhunter’s database with the new hashes, so it won’t detect them in future: -
rkhunter –propupd
This way a fresh copy of your current system state will be used the next time you run rkhunter for scanning. These are pretty much all the useful flags you might want to use, but there are many more switches via the man page for rkhunter at “man rkhunter”.
It’s also useful to set up rkhunter as a cron job. First, create the bash script: -
vi rkhunter.sh
and enter the commands that will first check that rkhunter is up to date and then run a scan: -
#!/bin/bash
TODAYS_DATE=`date +%F`
/usr/bin/rkhunter --update
/usr/bin/rkhunter -c -sk --cronjob | mail -s "${TODAYS_DATE} - rkhunter Scan Report" root@localhost
This will e-mail the results to “root@localhost”, but you can change this to whatever you like, assuming your Linux box has outisde access. Enter your root user crontab with: -
crontab -e
and enter the following: -
30 4 * * * /root/rkhunter.sh
This will run my rkhunter script at 4.30am everyday, mailing the results to your system root account. If you’ve not got e-mail access, you can follow my tutorial on using sendmail to route system e-mails to any e-mail account :-)
