Friday, October 15, 2010

Configuring Postfix SMTP as your MTA

     Postfix is one of the most popuar MTAs around.  Postfix has a modular design that improve security,speed and east of configuration.  In this design, a master daemon controls individual light weight processes (modules) that performs specific tasks.  The master deamon binary is "/usr/sbin/postfix" and the daemon configuration file is /etc/postfix/mster.cf.  But this file rarely needs change unless you need to enable / disable some sub processes(modules).  The MTA configuration is in  /etc/postfix/main.cf.  There are other configuration files for specific purposes and all of them lies under the folder /etc/postfix.  Following is a minimal configuration of main.cf that will let you run a postfix mail server for your own domain.

Most of the configuration parameters in main.cf will have a commented example version, you can either uncomment and edit them, or add a new line.  I will just list out important configuration parameters with comments added.  The example configuration is for running an MTA for safeer.in domain.

## The configuration file is in "key = value" format.  The key defined previously in the file
## can be referred to as $key in the coming sections.

## The domain for which you are configuring MTA
mydomain = safeer.in

## FQDN of the mail server where postfix is being configured
myhostname = smtp.safeer.in

## The domain name that locally sent and received mail appears to be from and/or delivered to.
## When you are running mail server for a domain, set as follows, default if unset is to use hostname.
myorigin = $mydomain

## By default postfix listens only on loopback, make it listen an all interfaces.
inet_interfaces = all

## The SMTP server will accept mails to the email ids addressed to the following domains and/or hostnames.
## In our setup, this will include the mail server (smtp.safeer.in) and the mail domain safeer.in
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

## Define trusted networks from which clients can connect to the smtp server without any restrictions.
mynetworks = 192.168.4.0/24, 10.10.5.0/24

## Allow smtp clients only from $mytnetworks and reject un authorized clients
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination

    
     This will get you started off with a minimal SMTP server.  Make these changes and restart your postfix server.

sudo /usr/sbin/service postfix

Ensure postfix has started listening by running

sudo netstat -atnp|grep :25|grep LISTEN

To test your server is working from command line, visit this link

Test your SMTP server with telnet

To know more about postfix configuration parameters check the official website of postfix or look at the man page by running "man 5 postconf"

Friday, October 1, 2010

Perl Snippets Part 2 - CSV to XLS

This program will convert a CSV ( Comma Separated Value ) file to an XLS ( Windows Excel ) spreadsheet. The script should be provided with the CSV file name as the first command line argument. It takes an optional second argument as the output XLS file name. If no output filename is given, the output will be saved to out.xls in the current directory.

This script requires Spreadsheet::WriteExcel perl module. On my Ubuntu box, this was installed with the command:
safeer@penguinpower:~$sudo apt-get install libspreadsheet-writeexcel-perl

#!/usr/bin/perl -w

use Spreadsheet::WriteExcel;

if (!defined $ARGV[0]) { die "You must provide a csv file"; }
else {$CSV_FILE = $ARGV[0];}

if ( defined $ARGV[1] ) { $XLS_FILE = $ARGV[1]; }
else { $XLS_FILE = "out.xls"; }

unless ( open ( CSV,$CSV_FILE))
{ die "Unable to open ".$CSV_FILE;}

my $workbook = Spreadsheet::WriteExcel->new($XLS_FILE);
if ( !defined $workbook ) {
die "Unable to create excel file\n";
}
$worksheet = $workbook->add_worksheet();
$col = $row = 0;

while (<CSV>)
{
chomp;
my @line = split(",",$_);
for $cell (@line){
$worksheet->write($row, $col,$cell);
$col++;
}
$row++; $col = 0;
}
$workbook->close();
close (CSV);

Sunday, September 12, 2010

Bash Recipes Part 1 - Changing extensions for multiple file names

I have came across many situations where a bunch of files with one filename extension has to be renamed to another extension. Here is the way to do it in bash.

We will rename a number of post script files to PDF files ( .ps to .pdf )

safeer@penguinpower:~/Documents$ ls
book0.ps book1.ps book2.ps book3.ps book4.ps
safeer@penguinpower:~/Documents$ for file in $(ls *.ps);
do
mv $file ${file/%.ps/.pdf};
done

safeer@penguinpower:~/Documents$ ls

book0.pdf book1.pdf book2.pdf book3.pdf book4.pdf

Saturday, August 14, 2010

Perl Snippets Part 1 - XLS to CSV

For parsing Microsoft excel files (.xls) using Perl, we can make use of the module Spreadsheet::ParseExcel.
On my Ubuntu system this module is installed by:

safeer@penguinpower:~$sudo apt-get install libspreadsheet-parseexcel-perl

Following program will take an XLS file as input and print the csv format to standard out.


#!/usr/bin/perl -w

use strict;
use Spreadsheet::ParseExcel;

my $parser = Spreadsheet::ParseExcel->new();
if ( !defined $ARGV[0] ) { die "Please provide an excel file"; }
my $workbook = $parser->parse($ARGV[0]);
if ( !defined $workbook ) { die $parser->error(), ".\n"; }

for my $worksheet ( $workbook->worksheets() ) {

my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();

for my $row ( $row_min .. $row_max ) {
for my $col ( $col_min .. $col_max ) {

my $cell = $worksheet->get_cell( $row, $col );
if ( defined $cell ) { print $cell->value(); }
if ( $col < $col_max ) { print ","; }
}
print "\n";
}
}

Sunday, June 20, 2010

Configuring NTP service

     The network time protocol ( NTP ) is used to synchronize a computer system's time with an accurate time source. Interconnected and communicating systems should have their times in sync with each other to preserve the order of communication / sotring of information ( and and many more applications ).

     The ultimate source of accurate time is called a reference clock and will usually be an atomic/nuclear clocks ( usually using cesium as the element ).  Another variety of reference clocks will be gps receivers receiving time from satellites ( which in turn uses an atomic clock ). Other computer systems sync their time from reference clocks directly or from servers that sync from reference clock directly.

    NTP supports a hierarchy of time sources, the accuracy of each level of this hierarchy is referred to by the term startum.  A startum number is given to each source based on its reliability, smallest startum being most accurate.  Thus reference clocks are startum 0, the servers that sync time directly from them are startum 1, and servers that sync from these servers will be startum 2 and so on.  Basiaclly if the upstream NTP server is startum X, the server syncing from that server is startum X+1 upto a maximum value of 15.  NTP protocol/service has inherent mechanisms to determine the accuracy of upstream NTP server as well as its own by calculating different parameters like offset,resolution,jitter etc..

NTP is a UDP base protocol and uses port 123. Let us look at a basic NTP configuration

    First install the  NTP software, on ubuntu it is openntpd with main configuration file /etc/openntpd/ntpd.conf and optional include files kept under /etc/openntpd.  On a redhat system it will be ntp ( with configuration file at /etc/ntp.conf and include directory /etc/ntp.d/).

safeer@ntpc:~$sudo yum install ntp
safeer@ntpc:~$sudo /sbin/service ntpd status
 * ntpd is stopped

     First you have to determine from which NTP server you want to sync time.  This can be another server in your network, or one publicaly available.  You can even setup a standalone ntp server which syncs from its own hardware clock and provide time service to other servers in your network ( though not very much recommended )

     Now there are two ways to sync time from a server.  You can use the ntpdate binary, which will sync with the server time immediately, but this can have adverse effect on the server of the time difference between ntpserver and client and bigger.  The other option is to configure ntp service, which will allow the server to gracefully sync time.

How ntpdate works:

Check if the server is up and available:

safeer@ntpc:~$sudo ntpdate -q ntp1.safeer.in

The output will list one ore more servers behind the ntp dns name and its time details.  This indicates the sever is good, so go ahead and sync with it.

safeer@ntpc:~$ sudo ntpdate ntp1.safeer.in

You can provide multiple space separated NTP server to ntpdate.  If the command shows no error, the time will be set by now.  Check your system with date command.

Now let us see how the ntp server can be configured:

First add one or more servers:

server 1.1.1.1
server 2.2.2.2
server ntp1.safeer.in


NTPD can detect the time drift between system clock and the reference clock ( or server ) over a period of time and need to store this somewhere to adjust the system time.  This drift value has to be written to some file.  The user running NTP daemon should have write access to the file.

driftfile /var/lib/ntp/drift


     This much was about how you receive the time from upstream servers.  Now let us see what it takes to sync the server's own system clock or downstream servers. 
     First case, let us assume we just need to sync the time on our server and not provide time to any downstream servers ( ntp client mode )

    The configuration parameter to use here is "restrict" in the following syntax: restrict < host ip/hostname/network id > [mast < mask >] [flags .. ..]
     The mask is optional ( need only when u are defining access for networks and not single servers), if the flags are omitted the server will be having unrestricted access to ntp service.  Also you can use the entry "default" in place of host/network for setting default access policy.  If access is not explicitly defined for a host/network the default policy will be used.

    Since we are planning to sync only the local server we have to restrict everything except localhost from accessing ntp service. 

## This will deny ntp service to any host that done have an explicit "restrict" entry
restrict default ignore
## Allow access to localhost through loopback interface ( by omitting flags section )
restrict 127.0.0.1


If we are configuring our server to server other hosts, say the local network - 192.168.1.0/255.255.255.0 this is how you do it:

restric 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer
     The flag nomodify prevent clients from modifying servers ntp configuration, notrap prevents from sending log collection trap messages, nopeer prevents peering/associating the clients with the server to be "co-servers"

     If the upstream server becomes unavailable, the host will not be able to sync time, so as a fall back we configure the local clock as a time source, in ntp language the ip "127.127.1.0" indicates local clock

server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10


If you want to log the ntp activity add the entry

logfile /var/log/ntp.log

Finally, let us consilidate everything in one place:

server 1.1.1.1
server 2.2.2.2
server ntp1.safeer.in

restrict default ignore
restrict 127.0.0.1

restric 192.168.1.0 mask 255.255.255.0 nomodify notrap nopeer

server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10

driftfile /var/lib/ntp/drift
logfile /var/log/ntp.log



Before starting ntp service, run ntpdate with one of the servers listed as an initial sync, then start ntp service


safeer@ntpc:~$sudo ntpdate ntp1.safeer.in
safeer@ntpc:~$sudo /sbin/service ntpd start

For more on NTP, check official website and RFC page.