Mar 222016
 

When you have webmail separated from your pop3/imap4 server things can be complicated if you don’t have direct access to mysql server over the network. using poppassd will not solving the problem if you’re using mysql, pgsql or ldap backend for storing user information. because (AFAIK) it only can access/change user/password on passwd/shadow file.

using courierpassd allows us to access or modify pop3/imap4 user information store in mysql, pgsl or ldap backend. one caveat, courierpassd using courier-authlib API in order to be able accessing those database backend. we have to install or build from source. courierpassd use the same protocol as poppassd does.

i’m using centos and this is how i do it.

first using non priviledged user cccount, create rpm build environment.

$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros

mkdir $HOME/rpm
mkdir $HOME/rpm/SOURCES
mkdir $HOME/rpm/SPECS
mkdir $HOME/rpm/BUILD
mkdir $HOME/rpm/SRPMS
mkdir $HOME/rpm/RPMS
mkdir $HOME/rpm/RPMS/i386

echo "%_topdir $HOME/rpm" >> $HOME/.rpmmacros

download courier-authlib and courierpassd source

wget http://prdownloads.sourceforge.net/courier/courier-authlib-0.60.2.tar.bz2
wget http://www.arda.homeunix.net/?ddownload=375 -O courierpassd.1.1.2.tar.gz

compile and install courier-authlib

$rpmbuild -ta courier-authlib-0.60.2.tar.bz2
$sudo rpm -ivh /home/youruser/rpm/RPMS/x86_64/courier-authlib-0.66.4-1.el6.x86_64.rpm
$sudo rpm -ivh /home/youruser/rpm/RPMS/x86_64/courier-authlib-devel-0.66.4-1.el6.x86_64.rpm
$sudo rpm -ivh /home/youruser/rpm/RPMS/x86_64/courier-authlib-mysql-0.66.4-1.el6.x86_64.rpm

extract courierpassd, compile and install

#tar xzf courierpassd.1.1.2.tar.gz
#cd courierpassd-1.1.2
#./configure
#make
#make install

you want be able to access this courierpassd from other server on the network. people using xinet.d usually.

#vi /etc/xinetd.d/courierpassd
service courierpassd
{
       disable          = no
       socket_type      = stream
       protocol         = tcp
       port             = 106
       wait             = no
       user             = root
       server           = /usr/sbin/courierpassd
       instances        = 10
       only_from        = 192.168.0.101 127.0.0.1
}

Continue reading »

Jul 282011
 

In my last article about the DNSBL and memcached, I wrote how to use memcached to store the data for the DNSBL. It led me to other new ideas to make the Geo Location DNSBL. In previous article I put data into memcached with the following format:

_prefix_ip 127.0.0.2-10
_prefix_ = _a_ or _txt_
ip = ip address to blacklist
Example:
_a_192.168.1.1	127.0.0.3
_txt_192.168.1.1	Blacklisted

Each ip address has a pair of _a_ and _txt_ record.
For This experiment records will be store in following format:

_prefix_country_code 127.0.0.2-10
_prefix_ = _a_ or _txt_
country_code = country code to blacklist
Example:
_a_ID	127.0.0.3
_txt_ID	Blacklisted

dnsbl-geo.pl Perl script

#!/usr/bin/perl
use Net::DNS::Nameserver;
use Cache::Memcached;
use Geo::IP;
use strict;
use warnings;

our $our_dnsbl = ".dnsbl.example.com";

# Configure the memcached server
my $memd = new Cache::Memcached {
            'servers' => [ '127.0.0.1:11211' ],
};

my $gi = Geo::IP->new(GEOIP_STANDARD);

#sub reverse_ipv4 {
#        my $ip = $_[0];
#        my ($a1, $a2, $a3, $a4) = split /\./, $ip;
#        my $reversed_ipv4 = join('.', $a4,$a3,$a2,$a1);
#        return $reversed_ipv4;
#}

sub reverse_ipv4 {
        my @ips = split /\./, $_[0];
        my @r;
        push @r, pop @ips while @ips;
        return join('.', @r);
}

sub strip_domain_part {
        my $strip_domain = $_[0];
        $strip_domain =~ s/$our_dnsbl//ig;
        return $strip_domain;
}

sub reply_handler {
        my ($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_;
        my ($rcode, @ans, @auth, @add);
        my ($memc_a_val, $memc_txt_val);

        #print "Received query from $peerhost to ". $conn->{"sockhost"}. "\n";
        #$query->print;

        my $striped_domain = strip_domain_part($qname);
        my $reverse_striped_domain = reverse_ipv4($striped_domain);

        my $country_code = $gi->country_code_by_addr($reverse_striped_domain);

        if ($qtype eq "A" && $qname eq $striped_domain . $our_dnsbl) {
                my $vmemc_a_val = sprintf("_a_%s", lc($country_code));
                $memc_a_val = $memd->get($vmemc_a_val);
                if (defined($memc_a_val)) {
                        my ($ttl, $rdata) = (86400, $memc_a_val);
                        push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata");
                        $rcode = "NOERROR";
                }
        } elsif ( $qname eq "dnsbl.example.com" ) {
                $rcode = "NOERROR";

        } else {
                $rcode = "NXDOMAIN";
        }

        if ($qtype eq "TXT" && $qname eq $striped_domain . $our_dnsbl) {
                my $vmemc_txt_val = sprintf("_txt_%s", lc($country_code));
                $memc_txt_val = $memd->get($vmemc_txt_val);
                if (defined($memc_txt_val)) {
                        my ($ttl, $rdata) = (86400, $memc_txt_val);
                        push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata");
                        $rcode = "NOERROR";
                }
        } elsif ( $qname eq "dnsbl.example.com" ) {
                $rcode = "NOERROR";

        } else {
                $rcode = "NXDOMAIN";
        }

        # mark the answer as authoritive (by setting the 'aa' flag
        return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
        $memd->disconnect_all();
}

my $ns = Net::DNS::Nameserver->new(
     LocalAddr    => "192.168.200.18",
     LocalPort    => 5353,
     ReplyHandler => \&reply_handler,
     Verbose      => 0,
) || die "couldn't create nameserver object\n";

$ns->main_loop;

Continue reading »