Mar 25, 2012

Handling signals in bash

Due to the nature of a bash script, it is really difficult which can lead to a segmentation fault unless the script runs a binary within which can cause it afterwards. But what is the best way in bash in order to handle a segmentation fault? By catching its associated signal, that is, SIGSEGV (number 11, invalid memory reference).

In Linux, we have a great tool to do it: trap. The following script sets a handler up by means of the trap command. Its first parameter is the function or code which manages the exception, and the second one, the name (SEGV) or value (11) of the signal. We can also add more signals to the same trap.

[root@localhost ~]# cat segfault.sh
#!/bin/bash 

function trap_segfault 
{ 
    echo "We have a segmenation fault!"

    # Reset handler
    trap - 11
    exit 127 
} 

# Start handler
trap 'trap_segfault' 11
 
# Here code which can produce a segmentation fault, such as:
kill -SEGV $$ 1>&2

Apart from catching segmentation faults, we can use this technique so as to treat other signals inside a bash script. In order to take a look at all the signals provided by Linux, you might run 'trap -l' or 'kill -l'. But if you want to extend the information about them, you will have to resort to the own man.

[root@localhost ~]# man 7 signal
...
       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
...

Next example handles SIGHUP to show the PID of the script and SIGINT to terminate it.

[root@localhost ~]# cat hup_int.sh 
#!/bin/bash 

function trap_sigint
{ 
    echo "Script terminated"

    # Reset handlers
    trap - HUP INT
    exit 0 
} 

# Start handlers
trap 'echo PID: $$\n' HUP
trap 'trap_sigint' INT 

while [ true ];
do
    sleep 1
done

[root@localhost ~]# ./hup_int.sh &
[1] 3046

[root@localhost ~]# kill -HUP 3046
[root@localhost ~]# PID: 3046

[root@localhost ~]# kill -INT 3046
[root@localhost ~]# Script terminated


And finally, also say that we can use this utility to leave out signals. For instance, the following order makes the script ignore SIGTERM.

trap : SIGTERM


Mar 16, 2012

Setting up BIND to secure DNS with DNSSEC (II)

Let's continue with the second part of the article titled Setting up BIND to secure DNS with DNSSEC. First up, we have to know that the default configuration of BIND on CentOS 6 allows to use directly DNSSEC.

[root@dns ~]# cat /etc/named.conf
...
    dnssec-enable yes;
    dnssec-validation yes;
    dnssec-lookaside auto;

To begin with, we are going to generate the ZSK (it takes care of signing the records of the zone file) and KSK (it takes care of signing the ZSK) keys. Each command turns out two key pair files, public (.key) and private (.private). Pay attention to the permissions of the private keys. As you can guess, only root has access to the files.

[root@dns ~]# cd /var/named/test.local/

[root@dns test.local]# dnssec-keygen test.local

[root@dns test.local]# dnssec-keygen -f KSK test.local

[root@dns test.local]# ls -l
total 20
-rw-r--r--. 1 root root  428 Mar 11 20:33 Ktest.local.+005+05775.key
-rw-------. 1 root root 1010 Mar 11 20:33 Ktest.local.+005+05775.private
-rw-r--r--. 1 root root  602 Mar 11 20:36 Ktest.local.+005+06859.key
-rw-------. 1 root root 1774 Mar 11 20:36 Ktest.local.+005+06859.private
-rw-r--r--. 1 root root  163 Mar 11 19:15 test.local.zone

Next step is to add the public key files to the zone file. We will have a couple of extra DNSKEY records included inside the file.

[root@dns test.local]# cat *.key >> test.local.zone

[root@dns test.local]# cat test.local.zone
...
test.local. IN DNSKEY 256 3 5 AwEAAc1...
test.local. IN DNSKEY 257 3 5 AwEAAda...

At this moment, we are able to sign the zone. The last argument of the command is the zone file and through the "-o" option, we can indicate the zone origin. This order creates a new version of the zone file by adding NSEC and RRSIG records.

[root@dns test.local]# dnssec-signzone -o test.local test.local.zone

[root@dns test.local]# ls -l *.signed
-rw-r--r--. 1 root root 3429 Mar 11 20:50 test.local.zone.signed

Now we only need to update the named.conf file in order to point at the new signed file. Remember to reload the service for the changes to take effect.

[root@dns test.local]# cat /etc/named.conf
...
zone "test.local" IN {
    type master;
    file "test.local/test.local.zone.signed";
};

[root@dns ~]# /etc/init.d/named restart

I will finally write a third article so as to carry out some test about this.


Mar 12, 2012

Setting up BIND to secure DNS with DNSSEC (I)

DNSSEC stands for Domain Name System Security Extensions. From the acronym, we ought to figure out that basically, this extension takes care of adding security to the DNS protocol.

When the DNS protocol came out, like most of the initial protocols of Internet, it was not designed by taking into account the security. Over time, the DNS protocol has become one of the biggest risks related to security. We only have to remember the series of articles about ARP poisoning (I, II and III).

DNSSEC allows zones to be verified by signing them with a zone key. Thus, the information about a specific zone can be authenticated as coming from a nameserver which has signed it with a concrete private key, as long as the client has the nameserver's public key.

How does DNSSEC work? Signs all zone records with the same name and type by using a Zone Signing Key (ZSK). This process turns out a signature which is stored in a RRSIG (Resource Record Signature) record. In turn, the public part of the ZSK is a DNSKEY (DNS Public Key) record. Afterwards, ZSK will be signed by other different key known as KSK (Key Signing Key). KSK is also stored in a DNSKEY record.

So in this way, we will be able to use DNSSEC to check DNS secure results (from a signed zone validated correctly), insecure results (from an unsigned zone), and fake results (signature fails when is validated or zone is unsigned but parent says which should be signed).

Let's get started by configuring a simple zone called test.local on a CentOS 6.2 server. To begin with, we are going to install BIND (version 9.7.3) and define our zone in the configuration file. The type of zone will be master, that is, it designates the nameserver as authoritative for this zone.

[root@dns ~]# hostname
dns.test.local

[root@dns ~]# yum install bind

[root@dns ~]# cat /etc/named.conf
...
options {
    listen-on port 53 { any; };
...
    allow-query     { localhost; localnets; };
...
};

zone "test.local" IN {
    type master;
    file "test.local/test.local.zone";
};

Then we have to create the zone file. As commented before, it will be a simple file with an unique address record specifying the IP of the server (192.168.183.130).

[root@dns ~]# mkdir /var/named/test.local

[root@dns ~]# cat /var/named/test.local/test.local.zone
; Zone name
$ORIGIN test.local.

; Default Time to Live (TTL)
$TTL    86400

; Start Of Authority resource record
; (serial-number time-to-refresh time-to-retry time-to-expire minimum-TTL)
@       IN SOA dns.test.local. admin.test.local. (1 6H 1H 1W 1D)

; NameServer record (announces the authoritative nameserver for a particular zone)
        IN NS  dns.test.local.

; Address record (specifies an IP address to assign to a name)
dns     IN A   192.168.183.130

So far, this is the normal behavior of a DNS server without authenticating its zones. If you restart the BIND service right away, you could use it as a normal DNS server. Next week, I will end up by setting the configuration for DNSSEC.

[root@dns ~]# /etc/init.d/named restart


Mar 4, 2012

Mounting file systems via Samba (CIFS) or NFS through automount (autofs) (II)

This is the second part of the article Mounting file systems via Samba (CIFS) or NFS through automount (autofs). In the first one, we started to prepare autofs in order to automatically mount a couple of remote directories by NFS and Samba.

Now let's carry on by supposing that centos02 exports the directory /nfs via NFS and centos03 exports the directory /samba via Samba. I am not going to note down how to configure NFS or Samba, because next week I intend to write an article related to this.

The following file shows the content of the auto.centos file. By means of this configuration file, we are indicating the NFS or Samba paths to the autofs daemon. When someone (or something) accesses the /mnt/tmp/nfs directory, this filesystem will be automatically imported from centos02 via NFS. The same occurs for the /mnt/tmp/samba directory imported from centos03 via Samba.

[root@centos01 ~]# cat /etc/auto.centos
...
nfs     -fstype=nfs                                        centos02:/nfs
samba   -fstype=cifs,username=samba_user,password=xxxxxx   ://centos03/samba

When the timeout has expired and there has been no activity on the directories during that time, the directories will also be automatically dismounted.

Finally, you just have to restart the autofs service.

[root@centos01 ~]# service autofs restart


Feb 26, 2012

Mounting file systems via Samba (CIFS) or NFS through automount (autofs) (I)

Mounting a filesystem via Samba or NFS has the main problem that you are increasing the traffic in your network, since when the data are updated on the export server, they must also be brushed up on the clients.

Furthermore, you have to take into account another additional problem when you mount a remote directory through Samba. If the connection between the server and the client is cut off (this one is restarted, any kind of network problem turns up, etc.), Samba does not automatically reconnect it and the mount point will remain in an unstable state, with which any sort of existing synchronization would be lost.

In this way, it is very important to always mount remote directories by using automount.

Automount automatically mounts a filesystem when you use it, and unmounts it later when you are not working on it, based on a timeout. When the timeout (600 seconds by default) is used up, the filesystem is automatically dismounted. Thus, you can achieve a decrease in network traffic (there may be long periods of time that you are not accessing the filesystem) and avoid lack of synchronization. Also point out that automount is managed by the autofs daemon.

Then let's put forward our work infrastructure. It will be made up for three Linux servers (all of them running CentOS 6.2). The main server, centos01, will mount a filesystem from centos02 via NFS, and another one from centos03 via Samba.

First of all, we have to install autofs and create a directory which will be used to mount the file systems. Afterwards, we have to edit the auto.master file in order to define the mount point handled by autofs.

[root@centos01 ~]# yum install autofs

[root@centos01 ~]# mkdir /mnt/tmp

[root@centos01 ~]# cat /etc/auto.master
...
/mnt/tmp    /etc/auto.centos    -g,--timeout=300

The above line means that all available mount points for the tmp directory will be set inside the auto.centos file. With "-g" option, autofs shows the content of the directory without mounting it, that is to say, if you run for example "ls /mnt/tmp", you will see those directories which will be able to be mounted through automount. Otherwise, no directory will be output.

This last option is really useful if you want to serve a filesystem by means of Apache and import it via automount, since Apache will be able to list the content of the directory without previously mounting it.


Feb 19, 2012

Apache performance tuning: directives (II)

Let's carry on with the second part of the article Apache performance tuning: directives (I).

If you take a look at the previous output, you may identify that the first process is the parent and the other ones, its children. The most important column is RSS (Resident Set Size), whereby you can see that the size of memory taken up by a child process is around 2 MB. Thus, you might work out the maximum number of Apache processes which can be simultaneously running on your system:

MaxClients = 338 MB / 2 MB = 169

This value is relative and never should be taken into account exactly. You have to consider that at any given time, other applications running on the system (mail, FTP, database, etc.) can ask for free memory. So in the preceding case, it would be reasonable to grab 200 MB instead of 338 MB. Furthermore, you must think that is not the same task to serve dynamic than static content.

If all processes are busy, Apache launches a series of spare processes (MinSpareServers). If a given time many processes are idle, these are removed with the aim of not exceeding a maximum number of spare processes (MaxSpareServers). In general, it must be satisfied that MinSpareServers ≤ StartServer ≤ MaxSpareServers, and MaxSpareServers should be 50% higher than MinSpareServers.

When a process has handled too many requests (MaxRequestsPerChild), this is deleted and another one is created again. An optimum value for MaxRequestsPerChild is 4000, although it is appropriate to fit it based on the data served.

What happens if a connection does not respond or keeps inactive indefinitely? A connection is another resource for the system and as such, must be freed up in case of not being used. The default timeout is usually very high (300 seconds). In order to enhance the server performance is useful to turn down this value to 20 (nowadays, the speed of the networks is huge, and it does not make sense to set such a high Timeout).

Lastly, we are going to treat an important issue for a web server: the persistence. When a web page is loaded, it is normal that the web browser establishes an only TCP connection and downloads all web elements, by carrying out multiple requests over the same connection.

So as to manage this feature, Apache provides three different parameters in its configuration file.

  • KeepAlive: enables (On) or disables (Off) persistent connections.

  • MaxKeepAliveRequests: maximum number of requests allowed on a persistent connection.

  • KeepAliveTimeout: amount of time the server will keep an inactive persistent connection before closing it.

It is recommended to use a very high value for the KeepAliveTimeout parameter (2 or 3 seconds). In respect of MaxKeepAliveRequests, will depend on the amount of content that web pages have on average, but it should not usually exceed 1000.


Feb 13, 2012

Apache performance tuning: directives (I)

In this article about Apache performance tuning, I am going to deal with some Apache directives. Remember that in the previous articles (I and II), I focused on the Apache modules, and we learnt on the one hand, that we can reduce the memory used by each process by removing those modules which are not necessary, and in this way, they will be lighter. And on the other, if we take those unused modules out, we will have less software exposed to possible attacks.

One of the most important tasks when we are setting Apache up is to fit its directives, which allow to control the overall running of the web server. These directives always depend on the available hardware, as well as the type of content that you want to serve. They are located inside the httpd.conf file; bellow, I will show you the most meaningful directives.

  • StartServers: number of child server processes created on startup. This value is related to the initial HTTP load of the machine, whether there are another configured services, and so on. For example, if the computer only works as a web server, there is no problem to start with 50 processes, but if there are other running services such as FTP, mail, database, etc., and in addition, it runs low on computational resources, we should start with a small number of active processes, and afterwards, on real time, Apache itself would have to launch the needed ones.

  • MaxClients: maximum number of simultaneous processes that can be running at the same time.

  • ServerLimit: maximum number of processes for the MaxClients parameter.

  • MinSpareServers: minimum number of idle child server processes.

  • MaxSpareServers: maximum number of idle child server processes.

  • MaxRequestsPerChild: maximum number of requests that an individual child server will handle during its life.

  • Timeout: amount of time the server will keep an inactive connection before closing it.

When Apache is started, several processes are created (StartServers) in order to listen for potential connections. When a request reaches the server, this is attended by a child process, and then, the process switches to idle state, waiting for new connections. If at a given time the number of requests is greater than the number of available processes (MaxClients), these requests are queued. Must be satisfied that MaxClients ≤ ServerLimit.

We can work out the maximum number of httpd processes that our system can run based on the available memory. You have to divide the free memory of the server by the amount of memory taken by an unique Apache process.

So as to calculate the free memory of the system, you can use the following command.

[root@centos ~]# cat /proc/meminfo | grep MemFree
MemFree:          346492 kB

And in order to find out the amount of memory grabbed by an Apache process, you may run the next order.

[root@centos ~]# ps -ylC httpd
S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
S     0  1870     1  0  80   0  3404  2792 -      ?        00:00:00 httpd
S    48  1873  1870  0  80   0  2072  2792 -      ?        00:00:00 httpd
S    48  1874  1870  0  80   0  2072  2792 -      ?        00:00:00 httpd
S    48  1875  1870  0  80   0  2072  2792 -      ?        00:00:00 httpd