postfix-2.9.20110615 SRC RPM
Postfix, Realtime Maildir Replication Using Dual-primary DRBD with OCFS2
As I’ve been written on my previous post about Maildir Replication using ChironFS in postfix, I will explain step by step it can also be done by using drbd and ocfs2.
Compiling & Installing
note: if your Linux distribution is shipped with a kernel older than 2.6.33 you have to install a kernel module package and packages for the user land code. If your distribution contains a Linux-2.6.33 kernel or newer you only need to install the user land code.
In my case i have my linux distribution older than 2.6.33, so i will also compile drbd kernel module.
Download drbd source and create Binary RPMS packages
$ wget http://oss.linbit.com/drbd/8.3/drbd-8.3.10.tar.gz $ tar xvzf drbd-8.3.10.tar.gz $ cd drbd-8.3.10 $ ./configure --enable-spec --with-km $ cp ../drbd*.tar.gz `rpm -E %_sourcedir` $ rpmbuild -bb drbd.spec $ rpmbuild -bb drbd-km.spec $ sudo rpm -ivh /path/to/RPMS/drbd-*
I’ll be using loop files for this setup since I don’t have access to raw partitions.
but if you have raw block device available you can subtitute this part:
resource r0 { meta-disk internal; device /dev/drbd0; disk /dev/loop0;
Into:
resource r0 { meta-disk internal; device /dev/drbd0; disk /dev/sdxx;
sdxx can be sda1, sdb1 sdb2 or what ever your raw disk device called
# dd if=/dev/zero of=/drbd-postfix.img bs=1M count=5000 # losetup /dev/loop0 /drbd-postfix.img
Place this DRBD resource file in /etc/drbd.d/r0.res. Be sure to adjust the server names and IP addresses for your servers.
resource r0 { meta-disk internal; device /dev/drbd0; disk /dev/loop0; syncer { rate 1000M; } net { allow-two-primaries; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; } startup { become-primary-on both; } on postfix1 { address 192.168.200.18:7789; } on postfix2 { address 192.168.200.114:7789; } }
Postfix, Maildir Replication In Real Time Using ChironFS
In this tutorial I will describe how to set up postfix and maildir which can automatically replicate email when email is delivered. We will not touch the postfix configuration at all. we will manipulate maildir directory behavior using ChironFS, instead.
what is ChironFS?
This the Chiron Filesystem. It is a Fuse based filesystem. It’s main purpose is to guarantee filesystem availability using replication. But it isn’t a RAID implementation. RAID replicates DEVICES not FILESYSTEMS.
Things we need before installing chironfs
- fuse
- fuse-devel
- fuse-libs
- ChironFS source/binary from here
Compile ChironFS source
RPM:
$ rpmbuild --rebuild chironfs-1.0.0-1.fc8.src.rpm $ rpm -ivh /path/to/chironfs-1.0.0-1.fc12.rpm
postfix-2.9.20110605 rpm source
Postfix GeoIP Based Rejections
If you intend to be able to reject connections from remote IP addresses if they’re from certain countries. This is how you do it. This method will reject ip address that has been mapped in GeoIP at smtp conversation stage. However, This tutorial has never been tested. nothing more than a prototype that i created in leisure time.
Software required:
- postfix (tcp_table)
- Perl
- Perl Geo::IP module
main.cf:
127.0.0.1:2528_time_limit = 3600s smtpd_client_restrictions = check_client_access tcp:[127.0.0.1]:2528
master.cf
127.0.0.1:2528 inet n n n - 0 spawn user=nobody argv=/etc/postfix/geo-reject.pl
Postfix Bind Sender Outgoing IP, Based On GeoIP Location
This morning, when I took my daughter to school, I got the idea to experiment with postfix and GeoIP location. the idea is, if mx emails are in a geo targeted a specific location, mail delivery will be done with a certain ip address.
Ie:
- Every emails with the mx hosts that have IP addresses/host mapped to the US country code, will be bind to ip 1.2.3.4.
- Every emails with the mx hosts that have IP addresses/host mapped to the HK country code, will be bind to ip 5.6.7.8.
or
- Every emails with the mx hosts that have IP addresses/host mapped to the CN country code, will be relay to our smtp nexthop in china.
And so on..
what is geolocation?
Geolocation is used to deduce the geolocation (geographic location) of another party. For example, on the Internet, one geolocation approach is to identify the subject party’s IP address, then determine what country (including down to the city and post/ZIP code level), organization, or user the IP address has been assigned to, and finally, determine that party’s location. Other methods include examination of a MAC address, image metadata, or credit card information.
But, in this experiment we just need ip/host to country code map and perl script.
Perl module required:
Net::DNS Geo::IP Sys::Syslog
Basic Usage perl geoip
#!/usr/bin/perl use Geo::IP; my $gi = Geo::IP->new(GEOIP_STANDARD); print $gi->country_name_by_name("amazon.com");
I would still be using transport_maps and tcp_table to interact with Perl scripts. so here’s the prototype.
In Postfix part, we have custom transport like this in master.cf:
smtp-JP unix - - n - - smtp -o syslog_name=postfix-smtp-JP -o smtp_helo_name=smtp-JP.example.com -o smtp_bind_address=1.2.3.1 smtp-US unix - - n - - smtp -o syslog_name=postfix-smtp-US -o smtp_helo_name=smtp-US.example.com -o smtp_bind_address=1.2.3.2 smtp-ID unix - - n - - smtp -o syslog_name=postfix-smtp-ID -o smtp_helo_name=smtp-ID.example.com -o smtp_bind_address=1.2.3.3 smtp-CN unix - - n - - smtp -o syslog_name=postfix-smtp-CN -o smtp_helo_name=smtp-CN.example.com -o smtp_bind_address=1.2.3.4 smtp-HK unix - - n - - smtp -o syslog_name=postfix-smtp-HK -o smtp_helo_name=smtp-HK.example.com -o smtp_bind_address=1.2.3.5
Postfix Rotating Outgoing IP Using TCP_TABLE And Perl
In The last article “Postfix Randomizing Outgoing IP Using TCP_TABLE And Perl“, i was writing about my experiment randomizing outbound ip. someone asked if the script can be mimicked as in the iptables statistic module. indeed, when using the previous script, the results obtained will really random. although that is what the script was created.
I found this wiki explaining about Weighted Round-Robin Scheduling.
Supposing that there is a server set S = {S0, S1, …, Sn-1}; W(Si) indicates the weight of Si; i indicates the server selected last time, and i is initialized with -1; cw is the current weight in scheduling, and cw is initialized with zero; max(S) is the maximum weight of all the servers in S; gcd(S) is the greatest common divisor of all server weights in S; while (true) { i = (i + 1) mod n; if (i == 0) { cw = cw - gcd(S); if (cw <= 0) { cw = max(S); if (cw == 0) return NULL; } } if (W(Si) >= cw) return Si; }
anyway, I do not have much time to implement that algorithm into the script, so I use an existing perl module List:: util:: WeightedRoundRobin
Check Disk Quota Usage By Parsing Maildirsize
In the previous article, I have explained how to check the quota usage by using perl scripts. maildir quota checking is done by using File::Find function which seems a bit slow and too much consuming I/O process. same as the find function on bash script. find function in perl perform disk usage by determining the size of all files and directories recursively. all sizes of files and directories then accumulated.
find(sub{ -f and ( $size += -s ) }, $diruser );
actually, examination of maildir quota usage is also done by imap server which is written into a file called maildirsize. So, rather than wasting resources on the server. we can directly read the specified quota and usage on maildirsize file.
Maildir quota usage using File::Find
sub checksize { my $diruser = $_[0]; trim($diruser); my $size; find(sub{ -f and ( $size += -s ) }, $diruser ); if (defined $size) { $size = sprintf("%u",$size); return $size; } return undef; }
Postfix Checking Maildir Disk Usage / Quota On The Fly
Postfix does not have built-in quota inspection feature. i’ve seen people on mailing list asking how to check maildir usage on the fly. Add-ons such as VDA , vda inspect quota after email was accepted. When someone over quota, they will bounce mail, Just imagine, when bad guys sent lots of email to overdrawn account with fake return address/sender envelope, on purpose. Our mail server will be backscatter source. spamming undelivered message to innocent people.
Maildrop and Dovecot can handle quota better, but still they’re all inspect maildir usage after accepting the mail. And likely they will bounce email after the first inspect overquota maildir. Ideally, sender should be rejected at smtp conversation time. RCPT TO stage will perfect place for inspecting recipient maildir usage. Before postfix introducing tcp_table, the best solutions was creating map for overquota user. this can be done by using script by querying user quota constant specified in database, then compared to usage in maildirsize file or maildir disk usage.
I wrote this simple perl script, has functions to inspect user quota specified in database, and maildir disk usage. it runs as daemon. it’s not perfect. the script lack of ability when dealing with email address alias or email address extension. Just keep in mind tcp_table connection is not protected and the server is not authenticated.
There are two main functions which are used in this script. checksqlsize and checksize.
checksqlsize is used to check user quota specified in the database. you can adjust parameters in the script as needed,
sub checksqlsize { my $user = $_[0]; my $sqlresult; trim($user); my $dbh = DBI->connect('DBI:mysql:postfixdb:localhost', 'user', 'password', { RaiseError => 1 }); my $sth = $dbh->prepare(qq{SELECT quota FROM mailbox WHERE username='$user'}); $sth->execute(); while (my @row = $sth->fetchrow_array) { $sqlresult = $row[0]; } $sth->finish(); $dbh->disconnect; if ($sqlresult >= 0 ) { return $sqlresult; } else { return undef; } }