Tag Archives: Postfix

Linux #11 : How to implement spam filtering apps on Postfix

필자가 적용한 Spam filtering위한 방법 들을 나열해 보면 아래와 같다.

  SPF RULE Filtering  : Policyd SPF on Postfix
  SPAM Policy Filtering : SpamAssassin
  DKIM Verification Filtering : DKIMProxy - In
  Domain Key Verification Filtering : DKIMProxy - In
  Virus Detect Filtering : ClamAV
  Black List (RBL) Filtering : RBL Reject from Postfix

순서대로 하나씩 확인을 해보자. 가장 먼저 Black List (RBL) Filtering을 확인 해 보면, 이걸 가장 먼저 시작하는 이유는 postfix의 main.cf에 추가만 하면 되어 간단하기 때문이다.

# vi /etc/postfix/main.cf
...
smtpd_recipient_restrictions =
...
reject_rbl_client cbl.abuseat.org
reject_rbl_client zen.spamhaus.org
reject_rbl_client multihop.dsbl.org
reject_rbl_client unconfirmed.dsbl.org
reject_rbl_client dnsbl.sorbs.net
reject_rbl_client combined.njabl.org
...

위 reject_rbl_client를 smtp_recipient_restrictions에 추가 한 뒤 postfix를 restart하면 적용된다. 그럼, Maillog에서 아래와 같은 Log를 확인 할 수 있다.

Jul 13 15:55:43 xxxxxx postfix/smtpd[21862]: NOQUEUE: reject: RCPT from unknown[xxx.xxx.xxx.xxx]: 554 5.7.1 Service unavailable; Client host [xxx.xxx.xxx.xxx] blocked using cbl.abuseat.org; Blocked - see http://cbl.abuseat.org/lookup.cgi?ip=xxx.xxx.xxx.xxx; from= to= proto=ESMTP helo=

Clam Anti-Virus

Anti-Virus App으로 널리 사용되는 Clam Anti-Virus를 설치와 설정 부분이다. Source Download는 아래의 경로에서 받을 수 있다.

Download Clam AV : 
http://sourceforge.net/projects/clamav/files/clamav/0.96.1/clamav-0.96.1.tar.gz/download
Document : http://www.clamav.net/doc/latest/clamav-mirror-howto.pdf

# groupadd -g 8004 vscan

# useradd -g vscan -s /bin/false -c "Clam AntiVirus" -u 8897 clamav

# ./configure --prefix=/usr/local/clamav --with-group=vscan
# make;make install

# chown -R clamav.vscan /usr/local/clamav

Clam Anti-Virus를 위한 Group 및 User를 추가하고, Source로 부터 설치를 행한다.

# vi /usr/local/clamav/etc/clamd.conf
...
Example to #Example
LogFile /var/log/clamd/clamd.log
LogFileMaxSize 10M
LogTime yes
PidFile /var/run/clamd/clamd.pid
DatabaseDirectory /usr/local/clamav/db
LocalSocket /var/run/clamd/clamd.socket
#TCPSocket 3310
SelfCheck 0
ExcludePath ^/proc/
ExcludePath ^/sys/

# mkdir -p /var/log/clamd; mkdir -p /var/run/clamd;mkdir -p /usr/local/clamav/db
# chown -R clamav.vscan /var/log/clamd /var/run/clamd /usr/local/clamav/db

# vi /usr/local/clamav/etc/freshclam.conf
...
Example to #Example
DatabaseDirectory /usr/local/clamav/db
UpdateLogFile /var/log/clamd/freshclam.log
LogFileMaxSize 10M
LogTime yes
...

필자는 위와 같이 설정하였다. 그리고, Policy File을 Download 받기 위해 아래와 같이 실행하고 기동을 하면 된다.
주기적으로 Policy file을 갱신 할 수 있도록 cron에 등록을 한다.

# /usr/local/clamav/bin/freshclam

# ln -s /usr/local/clamav/bin/freshclam /etc/cron.daily/freshclam
# /usr/local/clamav/sbin/clamd

# vi /etc/inittab
...
cl:3:respawn:/usr/local/clamav/sbin/clamd
...

SPAM Assassin with Procmail

이 Procmail은 SPAM Assassin에서 Filtering한 메일 처리를 위해 설치하였다.

Download : http://www.alliedquotes.com/mirrors/apache/spamassassin/source/Mail-SpamAssassin-3.3.1.tar.gz
CPAN Site : http://www.perl.com/CPAN/

# yum -y install spamassassin procmail

SPAM Assassin의 동작을 위해 필요한 Perl Module은 아래와 같다. CPAN을 아래와 같이 설정 후 설치를 행하면 간단하게 설치할 수 있다.

CPAN Reconfiguration : cpan> o conf init
Configure HTTP CPAN Site => http://www.perl.com/CPAN/

cpan> o conf urllist push http://www.perl.com/CPAN/
cpan> o conf commit

Required and Optional Perl Module:
REQUIRED module : NetAddr::IP
REQUIRED module : Archive::Tar
REQUIRED module : IO::Zlib
optional module : Mail::SPF ( http://www.openspf.org/Implementations) : Use RPM => perl-Mail-SPF-2.006-1.el5.rf.noarch.rpm
: Dependency RPMS
perl-Error-0.17016-1.el5.rf.noarch
perl-NetAddr-IP-4.027-1.el5.rf
perl-version-0.76-1.el5.rf
optional module : IP::Country
optional module : Razor2 (http://packages.sw.be/razor-agents)
: Use RPM => perl-Razor-Agent-2.84-1.el5.rf
optional module : Net::Ident
optional module : IO::Socket::INET6
optional module : IO::Socket::SSL : http://search.cpan.org/~sullr/IO-Socket-SSL-1.33/SSL.pm
: Source Compile
optional module older than recommended: Mail::DKIM (perl-Mail-DKIM-0.36-1.el5.rf.noarch)
: Dependency RPMS
perl-Pod-Escapes-1.04-1.2.el5.rf.noarch
perl-Pod-Simple-3.13-1.el5.rf.noarch
perl-Test-Pod-1.42-1.el5.rf.noarch
yum -y install perl-TimeDate.noarch
perl-MailTools-2.06-1.el5.rf.noarch
perl-Crypt-OpenSSL-RSA-0.25-1.el5.rf
perl-Digest-SHA-5.48-1.el5.rf
optional module : Encode::Detect

설치 완료 후 SPAM Assassin 및 Procmail용 rc file을 설정한다.

# vi /etc/mail/spamassassin/local.cf
...
required_hits 5
report_safe 0
rewrite_header Subject **SPAM**
skip_rbl_checks 1 => Currently RBL Check works on PostFix

trusted_networks 10.0.0.0/8
allow_user_rules 0

use_razor2 1
use_pyzor 1

score HEADER_8BITS 0
score HTML_COMMENT_8BITS 0
score SUBJ_FULL_OF_8BITS 0
score CASHCASHCASH 0
score UPPERCASE_25_50 0
score UPPERCASE_50_75 0
score UPPERCASE_75_100 0

## PROCMAIL
# vi /etc/procmailrc
SHELL=/bin/bash
PATH=/usr/bin:/bin
#DEFAULT=/home/popmail/[email protected]$DOMAIN/new
DEFAULT=/home/popmail/$USER/new
LOGFILE=/var/log/spam/procmail.log
#LOCKFILE=/home/popmail/[email protected]$DOMAIN/.procmail.lock
LOCKFILE=/home/popmail/$USER/.procmail.lock
#VERBOSE=ON

:0fw
|/usr/bin/spamc
#|/usr/bin/spamc -u $USER

아래와 같이 chkconfig에 추가하고, 기동을 하면 된다.

# chkconfig spamassassin on
# /etc/init.d/spamassassin start

기동 시 아래와 같은 Error가 발생을 하여 제대로 기동이 되지 않는 경우가 있는데, 이런 경우는 관련 Perl Module이 부족한 경우 이므로, 추가적으로 설치를 하면 된다.

spamd[7616]: Can't locate Crypt/OpenSSL/Bignum.pm in
==> http://packages.sw.be/perl-Crypt-OpenSSL-Bignum/perl-Crypt-OpenSSL-Bignum-0.04-1.el5.rf.x86_64.rpm

cd /etc/mail/spamassassin
wget http://spamassassin.apache.org/released/GPG-SIGNING-KEY
gpg --import GPG-SIGNING-KEY

Amavisd-new

Amavisd-new는 High performance interface로 MTA와 Content checker인 Clamv, Spam Assassin과 연동하여 사용된다.

Link : http://www.ijs.si/software/amavisd
Download RPM : http://packages.sw.be/amavisd-new/amavisd-new-2.6.4-2.el5.rf.x86_64.rpm

필요 Perl Modules

Required Perl Module:
  IO::Stringy
  Unix::Syslog
  MIME::Words
   : MIME::Head
   : MIME::Body
   : MIME::Entity
   : MIME::Parser
   : MIME::Decoder
   : MIME::Decoder::Base64
   : MIME::Decoder::Binary
   : MIME::Decoder::QuotedPrint
   : MIME::Decoder::NBit
   : MIME::Decoder::UU
   : MIME::Decoder::Gzip64
  Convert::BinHex(http://search.cpan.org/~eryq/Convert-BinHex-1.119/lib/Convert/BinHex.pm)
   : Compile
  BerkeleyDB

설치 후 Group 및 User를 생성 해 주고, 아래와 같이 작업한다.

# useradd -g vscan -s /bin/false -c "Amavisd New" -u 8895 amavis

# mkdir /usr/local/amavis
# mkdir /usr/local/amavis/tmp /usr/local/amavis/var /usr/local/amavis/db /usr/local/amavis/home

# chown -R amavis:vscan /usr/local/amavis
# chmod -R 750 /usr/local/amavis

# cp amavisd /usr/local/sbin/
# chown root /usr/local/sbin/amavisd
# chmod 755 /usr/local/sbin/amavisd

# cp amavisd.conf /etc/amavisd.conf
# chown root:vscan /etc/amavisd.conf
# chmod 640 /etc/amavisd.conf
# chown -R amavis.vscan /usr/share/spamassassin

설정은 아래와 같이 하였다.

# vi /etc/amavisd.conf
...
$undecipherable_subject_tag = '';
@bypass_spam_checks_maps = (1); # controls running of anti-spam code
-> Amavisd-new와 연계하지 않고, Spam Assassin을 이용하는 경우, 또는 SPAM 대책을 행하지 않는 경우
$daemon_user = 'amavis'; # (no default; customary: vscan or amavis), -u
$daemon_group = 'vscan'; # (no default; customary: vscan or amavis), -g
$mydomain = 'ijji.com';
$MYHOME = '/usr/local/amavis';
$syslog_facility = 'daemon';

$myhostname = 'XXXX.ijji.com'; # must be a fully-qualified domain name!

#$QUARANTINEDIR = '/var/virusmails'; # -Q
$helpers_home = "$MYHOME/var";
$lock_file = "$MYHOME/var/amavisd.lock"; # -L
$pid_file = "$MYHOME/var/amavisd.pid"; # -P

##
['ClamAV-clamd',
\&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamd/clamd.socket"],
qr/\bOK$/, qr/\bFOUND$/,
qr/^.?: (?!Infected Archive)(.) FOUND$/ ],

@mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
10.0.0.0/8 );

$notify_method = 'smtp:[127.0.0.1]:10026';
$forward_method = 'smtp:[127.0.0.1]:10026'; # set to undef with milter!

$final_virus_destiny = D_DISCARD;
$final_banned_destiny = D_BOUNCE;
$final_spam_destiny = D_PASS;
$final_bad_header_destiny = D_PASS;

##### Meaning
D_BOUNCE : Mail is not delivered, but noticed to sender.
D_REJECT : same as D_BOUNCE, but noticed to sender in case of the mail is virus or mass spam.
D_DISCARD : Mail is not delivered and doesn't notice to sender.
D_PASS : Mail is delivered.

$sa_tag_level_deflt = 2.0; # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.2; # add 'spam detected' headers at that level
$sa_kill_level_deflt = 6.9; # triggers spam evasive actions (e.g. blocks mail)
$sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent
# $sa_quarantine_cutoff_level = 25; # spam level beyond which quarantine is off

$sa_mail_body_size_limit = 400*1024; # don't waste time on SA if mail is larger
$sa_spam_subject_tag = '**SPAM** ';
...

# cp amavisd_init.sh /etc/init.d/amavisd
# chmod 755 /etc/init.d/amavisd
# chkconfig amavisd on

# vi /etc/init.d/amavisd
...
prog="/usr/local/sbin/amavisd"
...

# /etc/init.d/amavisd start

Amavisd 기동 시 아래와 같은 Error가 발생할 수도 있는데, 이 경우 역시 Perl Module의 부족한 것이므로 추가 설치를 해 주면 된다.

.. ERROR>>
Starting amavisd: fetch_modules: error loading optional module MIME/Decoder/BinHex.pm: Can't locate Convert/BinHex.pm
==> INSTALL Perl Module Convert::BinHex
Problem in Amavis::DB or Amavis::DB::SNMP code: Can't locate BerkeleyDB.pm
==> INSTALL Perl Module BerkeleyDB
Starting amavisd: Problem in Amavis::DKIM code: Can't locate Crypt/OpenSSL/RSA.pm
==> INSTALL RPM :

perl-Crypt-OpenSSL-RSA-0.25-1.el5.rf
perl-Digest-SHA-5.47-1.el5.rf
perl-Mail-DKIM-0.36-1.el5.rf.noarch
perl-Carp-Clan-5.3-1.2.1.noarch : YUM
perl-Bit-Vector-6.4-2.2.2.1 : YUM
perl-Date-Calc-5.4-1.2.2.1 : YUM
perl-Net-DNS : YUM
perl(Mail::Address) : http://packages.sw.be/perl-MailTools/perl-MailTools-2.06-1.el5.rf.noarch.rpm
perl-TimeDate.noarch
perl(Test::Pod) : http://packages.sw.be/perl-Test-Pod/perl-Test-Pod-1.42-1.el5.rf.noarch.rpm
perl(Pod::Simple) : http://packages.sw.be/perl-Pod-Simple/perl-Pod-Simple-3.13-1.el5.rf.noarch.rpm
perl(Pod::Escapes) : http://packages.sw.be/perl-Pod-Escapes/perl-Pod-Escapes-1.04-1.2.el5.rf.noarch.rpm
Starting amavisd: Problem in antispam SA code: Can't locate Mail/SpamAssassin.pm
==> # /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi]$ ln -s /usr/local/SpamAssassin/lib/perl5/site_perl/5.8.8/Mail
Convert::TNEF
Convert::UUlib
Archive::Zip
Unable to load module: Can't locate Net/Server/Proto/UNIX.pm
==> http://packages.sw.be/perl-Net-Server/perl-Net-Server-0.96-1.el5.rf.noarch.rpm

Amavisd에 DKIM Checker를 추가 할 경우는 아래와 같은 설정 내용을 추가한다.

# vi /etc/amavisd.conf
...
$enable_dkim_verification = 1; # enable DKIM signatures verification
$enable_dkim_signing = 1; # load DKIM signing code, keys defined by dkim_key
dkim_key('esmtp.ijji.com', 'default', '/etc/domainkeys/default');
dkim_key('karosgame.com', 'default', '/etc/domainkeys/default');
...

위에서 설치한 Spam Assassin과 더불어 Amavisd-new가 Postfix 상에서 동작할 수 있도록 master.cf를 수정 해 준다.

# vi /etc/postfix/master.cf

#
# Content Filter amavisd-new
#

smtp-amavis unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
-o disable_dns_lookups=yes
127.0.0.1:10029 inet n - n - - smtpd
-o content_filter=dksign-in:[127.0.0.1]:10025
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8,10.36.0.0/16,10.37.0.0/16
-o receive_override_options=no_unknown_recipient_checks
-o strict_rfc821_envelopes=yes
-o smtpd_error_sleep_time=0
-o smtpd_soft_error_limit=1001
-o smtpd_hard_error_limit=1000

#
# Procmail
#
procmail unix - n n - - pipe
# flags=R user=vuser argv=/usr/bin/procmail -t -m USER=${user} DOMAIN=${nexthop} /etc/procmailrc
flags=R user=vuser argv=/usr/bin/procmail -t -m USER=${recipient} /etc/procmailrc

# vi /etc/postfix/main.cf
...
# The mailbox_command parameter specifies the optional external
# command to use instead of mailbox delivery. The command is run as
# the recipient with proper HOME, SHELL and LOGNAME environment settings.
# Exception: delivery for root is done as $default_user.
#
# Other environment variables of interest: USER (recipient username),
# EXTENSION (address extension), DOMAIN (domain part of address),
# and LOCAL (the address localpart).
#
# Unlike other Postfix configuration parameters, the mailbox_command
# parameter is not subjected to $parameter substitutions. This is to
# make it easier to specify shell syntax (see example below).
#
# Avoid shell meta characters because they will force Postfix to run
# an expensive shell process. Procmail alone is expensive enough.
#
# IF YOU USE THIS TO DELIVER MAIL SYSTEM-WIDE, YOU MUST SET UP AN
# ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER.
#

#mailbox_command = /some/where/procmail
#mailbox_command = /some/where/procmail -a "$EXTENSION"
mailbox_command = /usr/bin/procmail

#virtual_transport = virtual
virtual_transport = procmail

### FILTER
content_filter=smtp-amavis:[127.0.0.1]:10024
content_filter=dksign-in:[127.0.0.1]:10025

### PROCMAIL
procmail_destination_recipient_limit = 1
transport_destination_recipient_limit = 1
...

정상적으로 동작을 할 경우 Amavisd-new 기동 시 아래와 같은 Log를 maillog에서 확인 할 수 있다.

Jul 13 15:02:53 ca1xc131 amavis[19660]: starting. /usr/local/sbin/amavisd at esmtp1.ijji.com amavisd-new-2.6.4 (20090625), Unicode aware, LC_ALL="en_US", LANG="en_US.UTF-8"
Jul 13 15:02:53 xxxxxxx amavis[19660]: Perl version 5.008008
Jul 13 15:02:53 xxxxxxx amavis[19661]: Net::Server: Group Not Defined. Defaulting to EGID '8005 8005'
Jul 13 15:02:53 xxxxxxx amavis[19661]: Net::Server: User Not Defined. Defaulting to EUID '8895'
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Amavis::Conf 2.207
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Archive::Zip 1.30
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module BerkeleyDB 0.42
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Compress::Zlib 2.017
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Convert::TNEF 0.17
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Convert::UUlib 1.33
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Crypt::OpenSSL::RSA 0.25
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Digest::MD5 2.36
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Digest::SHA 5.48
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module IO::Socket::INET6 2.65
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module MIME::Entity 5.428
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module MIME::Parser 5.428
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module MIME::Tools 5.428
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Mail::DKIM::Signer 0.36
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Mail::DKIM::Verifier 0.36
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Mail::Header 2.06
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Mail::Internet 2.06
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Net::DNS 0.59
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Net::Server 0.97
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Socket6 0.23
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Time::HiRes 1.9719
Jul 13 15:02:53 xxxxxxx amavis[19661]: Module Unix::Syslog 1.1
Jul 13 15:02:53 xxxxxxx amavis[19661]: Amavis::DB code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Amavis::Cache code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: SQL base code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: SQL::Log code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: SQL::Quarantine NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Lookup::SQL code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Lookup::LDAP code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: AM.PDP-in proto code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: SMTP-in proto code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Courier proto code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: SMTP-out proto code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Pipe-out proto code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: BSMTP-out proto code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Local-out proto code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: OS_Fingerprint code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: ANTI-VIRUS code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: ANTI-SPAM code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: ANTI-SPAM-EXT code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: ANTI-SPAM-C code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: ANTI-SPAM-SA code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Unpackers code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: DKIM code loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Tools code NOT loaded
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found $file at /usr/bin/file
Jul 13 15:02:53 xxxxxxx amavis[19661]: No $altermime, not using it
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .mail
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .asc
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .uue
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .hqx
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .ync
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .F tried: unfreeze, freeze -d, melt, fcat
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .Z at /usr/bin/gzip -d
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .gz at /usr/bin/gzip -d
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .bz2 at /usr/bin/bzip2 -d
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .lzo tried: lzop -d
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .rpm at /usr/bin/rpm2cpio
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .cpio at /usr/bin/pax
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .tar at /usr/bin/pax
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found decoder for .deb at /usr/bin/ar
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .zip
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .7z tried: 7zr, 7za, 7z
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .rar tried: rar, unrar
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .arj tried: arj, unarj
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .arc tried: nomarch, arc
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .zoo tried: zoo, unzoo
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .lha tried: lha
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .cab tried: cabextract
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .tnef tried: tnef
Jul 13 15:02:53 xxxxxxx amavis[19661]: Internal decoder for .tnef
Jul 13 15:02:53 xxxxxxx amavis[19661]: No decoder for .exe tried: rar, unrar; lha; arj, unarj
Jul 13 15:02:53 xxxxxxx amavis[19661]: Using primary internal av scanner code for ClamAV-clamd
Jul 13 15:02:53 xxxxxxx amavis[19661]: Found secondary av scanner ClamAV-clamscan at /usr/local/clamav/bin/clamscan
Jul 13 15:02:53 xxxxxxx amavis[19661]: Creating db in /usr/local/amavis/db/; BerkeleyDB 0.42, libdb 4.3

또한, 동작 시의 Log는 아래와 같다.

Jul 13 14:30:49 xxx amavis[17786]: (17786-04) Blocked BANNED (application/octet-stream,.exe,.exe-ms,twain.dll), [209.85.212.47] [209.85.212.47] -> , Message-ID: , mail_id: 7GceC62MrFpK, Hits: -, size: 131943, [email protected],[email protected], 433 ms
Jul 13 14:30:49 xxx postfix/smtp[17907]: B396A67887E: to=, relay=127.0.0.1[127.0.0.1]:10024, delay=1.1, delays=0.67/0/0.01/0.44, dsn=2.5.0, status=sent (250 2.5.0 Ok, id=17786-04, BOUNCE)
Jul 13 16:07:04 xxxxxx amavis[19664]: (19664-15) Passed CLEAN, [xxx.xxx.xxx.xxx] [xxx.xxx.xxx.xxx] -> , Message-ID: , mail_id: TXb1emZTzJHa, Hits: -, size: 2687, queued_as: 991C9678882, [email protected],[email protected], 205 ms
Jul 13 16:07:04 xxxxx postfix/smtp[22425]: 44271678881: to=, relay=127.0.0.1[127.0.0.1]:10024, delay=46, delays=46/0/0.01/0.21, dsn=2.0.0, status=sent (250 2.0.0 Ok, id=19664-15, from MTA([127.0.0.1]:10025): 250 2.0.0 Ok: queued as 991C9678882)
Jul 13 16:13:22 xxxxx amavis[19664]: (19664-17) Blocked INFECTED (Eicar-Test-Signature), MYNETS LOCAL [10.37.114.27] [10.37.114.27] -> , Message-ID: , mail_id: SXo7SRF93r5L, Hits: -, size: 36861, 265 ms
Jul 13 16:13:22 xxxxx postfix/smtp[22787]: 4A622678881: to=, relay=127.0.0.1[127.0.0.1]:10024, delay=0.28, delays=0.01/0/0.01/0.27, dsn=2.7.0, status=sent (250 2.7.0 Ok, discarded, id=19664-17 - INFECTED: Eicar-Test-Signature)

SPF Rule Filtering

이 경로에서 해당 file을 받을 수 있다. https://launchpad.net/postfix-policyd-spf-perl/

필요한 Perl Module들은 아래와 같다.

Mail::SPF (http://packages.sw.be/perl-Mail-SPF/perl-Mail-SPF-2.006-1.el5.rf.noarch.rpm)
  perl(Error) (http://packages.sw.be/perl-Error/perl-Error-0.17016-1.el5.rf.noarch.rpm)
  perl(NetAddr::IP) (http://packages.sw.be/perl-NetAddr-IP/perl-NetAddr-IP-4.027-1.el5.rf.x86_64.rpm)
  perl(version) (http://packages.sw.be/perl-version/perl-version-0.76-1.el5.rf.x86_64.rpm)
  *** DOESN'T NEED => Mail::SPF::Query (http://packages.sw.be/perl-Mail-SPF-Query/perl-Mail-SPF-Query-1.999.1-1.2.el5.rf.noarch.rpm)
 perl(Net::CIDR::Lite) (http://packages.sw.be/perl-Net-CIDR-Lite/perl-Net-CIDR-Lite-0.20-1.2.el5.rf.noarch.rpm)
 perl(Sys::Hostname::Long) (http://packages.sw.be/perl-Sys-Hostname-Long/perl-Sys-Hostname-Long-1.4-1.2.el5.rf.noarch.rpm)

제공되는 Manual에 맞춰 설정을 하면,

1. Copy postfix-policyd-spf-perl to /etc/postfix/postfix-policyd-spf-perl

2. Add the following to /etc/postfix/master.cf:

#
# SPF Rule Filter
#
policy unix - n n - 0 spawn
user=nobody argv=/etc/postfix/postfix-policyd-spf-perl

3. Configure the Postfix policy service in /etc/postfix/main.cf:

smtpd_recipient_restrictions =
...
reject_unauth_destination
check_policy_service unix:private/policy
...

4. Add “policy_time_limit = 3600” to main.cf

### SPF
policy_time_limit = 3600

5. Restart Postfix.

아래와 같이 동작 Log를 확인 할 수 있다.

Jul 13 15:51:57 xxxxxx postfix/policy-spf[21886]: : SPF none (No applicable sender policy available): HELO/EHLO (Null Sender): omr-m12.mx.aol.com
Jul 13 15:51:57 xxxxxx postfix/policy-spf[21886]: handler sender_policy_framework: is decisive.
Jul 13 15:51:57 xxxxxx postfix/policy-spf[21886]: : Policy action=PREPEND Received-SPF: none (omr-m12.mx.aol.com: No applicable sender policy available) receiver=xxxxxx.xxx.com; identity=helo; helo=omr-m12.mx.aol.com; client-ip=64.12.207.154

DKIM Rule Filtering이 적용되었을 경우의 동작 Log는

Jul 14 12:25:56 xxxxxx dkimproxy.in[10325]: DKIM verify - pass; message-id=, signer=, from=
Jul 14 12:25:56 xxxxxx postfix/cleanup[12221]: 84BA1678850: message-id=
Jul 14 12:25:56 xxxxxx postfix/qmgr[12215]: 84BA1678850: from=, size=2946, nrcpt=1 (queue active)
Jul 14 12:25:56 xxxxxx postfix/smtpd[12295]: disconnect from localhost.localdomain[127.0.0.1]
Jul 14 12:25:56 xxxxxx postfix/virtual[12311]: 84BA1678850: to=, relay=virtual, delay=0.12, delays=0.12/0/0/0, dsn=2.0.0, status=sent (delivered to maildir)
Jul 14 12:25:56 xxxxxx postfix/qmgr[12215]: 84BA1678850: removed
Jul 14 12:25:56 xxxxxx amavis[11025]: (11025-05) Passed CLEAN, [74.125.83.47] [74.125.83.47] -> , Message-ID: , mail_id: icPExIFYk88J, Hits: -, size: 2150, queued_as: 84BA1678850, [email protected],[email protected], 381 ms

마지막으로 Mail의 처리 순서를 Incoming, Outgoing으로 나눠서 보면 아래와 같이 동작을 하게 되는 것이다.

Incoming Mail

Incoming Mail > Prot 25 : [SMTPD] > Blocking RBL(Black List) > SPF Verify : SPF RULE > 127.0.0.1:10024 [SMTPD] > Amavisd-new (Verify) With ClamAV, SpamAssassin > 127.0.0.1:10029 [SMTPD]
> 127.0.0.1:10025 [SMTPD] > DKIMProxy_IN Verify : DKIM, DomainKey > 127.0.0.1:10026 [SMTPD] > MAIL BOX

Outgoing Mail

MyNetwork (Can transfer TCP Relay or Send) > Port 25 : [SMTPD] > 127.0.0.1:10027 [SMTPD] > DKIMProxy_OUT Originating : No SIGN > 127.0.0.1:10028 [SMTPD] > Outgoing Mail
: Submission (Can transfer TCP Relay or Send) > Port 587 : [SMTPD] > 127.0.0.1:10027 [SMTPD] > DKIMProxy_OUT Originating : DKIM SIGN > 127.0.0.1:10028 [SMTPD] > Outgoing Mail

Linux #8 : How to Implement Dovecot, DKIM, DomainKey, MySQL in Postfix #2

5. Making and checking each configuration files for Postfix and dovecot

지난 시간에 이어서 각 file들의 대략적인 설정 내용을 확인 해 보도록 하자. 해당 설정 파일은 필자가 구축한 시스템에서 적용된 내용으로 모든 시스템에 적합하다고는 할 수 없다.

그럼, dovecot.conf를 살펴보자.

$ /etc/dovecot.conf
## Dovecot configuration
..
# Protocols we want to be serving: imap imaps pop3 pop3s
# If you only want to use dovecot-auth, you can set this to "none".
#protocols = imap imaps pop3 pop3s
protocols = imaps pop3s - 원하는 Protocol을 설정한다.

## Mailbox locations and namespaces
#mail_location = maildir:/home/popmail/%d/%u
mail_location = maildir:/home/popmail/%u <- Maildir 형식을 사용하고 /home/popmail을 Mailbox Directory로 지정했을 경우

# Don't use mmap() at all. This is required if you store indexes to shared
# filesystems (NFS or clustered filesystem).
#mmap_disable = no
mmap_disable=yes <- NFS나 clustered filesystem 사용 여부에 따라..

# Valid UID range for users, defaults to 500 and above. This is mostly
# to make sure that users can't log in as daemons or other system users.
# Note that denying root logins is hardcoded to dovecot binary and can't
# be done even if first_valid_uid is set to 0.
#first_valid_uid = 500
last_valid_uid = 80000 <- Mailbox에 대한 Permission을 80000으로 설정

# Valid GID range for users, defaults to non-root/wheel. Users having
# non-valid GID as primary group ID aren't allowed to log in. If user
# belongs to supplementary groups with non-valid GIDs, those groups are
# not set.
#first_valid_gid = 1
last_valid_gid = 80000

auth default {
# Space separated list of wanted authentication mechanisms:
# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi
# NOTE: See also disable_plaintext_auth setting.
mechanisms = plain login digest-md5 cram-md5 apop -> 인증 관련 mechanism을 설정

#passdb pam {
#{
<- comment passdb pam.
passdb sql {
# Path for SQL configuration file, see doc/dovecot-sql-example.conf
args = /etc/dovecot-mysql.conf
}
..
# It's possible to export the authentication interface to other programs:
socket listen {
..
client {
# The client socket is generally safe to export to everyone. Typical use
# is to export it to your SMTP server so it can do SMTP AUTH lookups
# using it.
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = root

}
}
}

다음은 postfix 설치시 mysql 연동을 위한 설정을 하였으므로, dovecot을 통해 mysql안의 user table을 참조 할 수 있도록 한다.

$ /etc/dovecot-mysql.conf
driver = mysql
#default_pass_scheme = PLAIN
default_pass_scheme = CRAM-MD5
connect = dbname=postfix user=postfix host=XXXXXXX password=XXXXXXX
password_query = SELECT password FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT concat('/home/popmail/', maildir) as home, 80000 as uid, 80000 as gid FROM mailbox WHERE username = '%u' AND active = '1'

필자는 위에서 “CLAM-MD5″를 사용하였는데, Webmail, postfixadmin, dovecot의 암호화 방식을 통일하기 위해서 입니다. PLAIN을 사용하면 dovecot의 log에서 바로 보이는게 문제가 되고, 다른 MD5를 쓰면 webmail에서 지원을 안하기도 하고 해서..

다음은 postfix의 main.cf의 설정이다. 이 또한 dovecot 연동을 위한 설정을 한다.

$ /etc/postfix/main.cf
..
# INTERNET HOST AND DOMAIN NAMES
#
..
#myhostname = host.domain.tld
myhostname = [my.domain.com] <- FQDN을 지정
..
# SENDING MAIL
#
..
#myorigin = $mydomain
myorigin = $myhostname <- Mail 송신시 Sending [email protected] Domain 명을 기입

# RECEIVING MAIL
..
#inet_interfaces = localhost
inet_interfaces = all <- 외부로부터 Mail 수신을 허가

# TRUST AND RELAY CONTROL
..
mynetworks = [Add Trust IPs] , localhost, 127.0.0.1
..
# DELIVERY TO MAILBOX
#
..
#home_mailbox = Mailbox
home_mailbox = Maildir/ <- Mailbox 형식을 Maildir로 설정
..
# SHOW SOFTWARE VERSION OR NOT
#
#smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
smtpd_banner = $myhostname ESMTP unknown <- Version 정보의 제거
..
message_size_limit = 10485760 <- 수신 Mail Size를 제한 10485760은 10MB
...
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination

...
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/pki/tls/certs/mail.pem
smtpd_tls_key_file = /etc/pki/tls/certs/mail.pem
smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_scache
tls_daemon_random_source = dev:/dev/urandom
...

local_transport = virtual
virtual_transport = virtual
virtual_mailbox_base = /home/popmail
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_alias_domains = $virtual_alias_maps
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_minimum_uid = 80000
virtual_uid_maps = static:80000

virtual_gid_maps = static:80000
mailbox_size_limit = 51200000
message_size_limit = 10240000
virtual_mailbox_limit = 51200000
#virtual_mailbox_limit_maps = hash:/etc/postfix/vquota
virtual_mailbox_limit_override = yes
virtual_overquota_bounce = yes
virtual_mailbox_limit_inbox = yes

virtual_alias_maps = mysql:/etc/postfix,virtual_mailbox_domains = mysql:/etc/postfix,virtual_mailbox_maps = mysql:/etc/postfix 위 설정과 관련 된 DB 접근을 위한 설정 파일도 준비한다. Files은 mysql_virtual_alias_maps.cf mysql_virtual_domains_maps.cf mysql_virtual_mailbox_maps.cf와 같다.

$ more mysql_virtual_alias_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = alias
select_field = goto
where_field = address

$ more mysql_virtual_domains_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and active = '1'

$ more mysql_virtual_mailbox_maps.cf
user = [db username]
password = [password]
hosts = [hostname]
dbname = postfix
table = mailbox
select_field = maildir
where_field = username

일단 여기까지라면 Postfix와 Dovecot, MySQL까지의 단계가 완료 된다.

6. Install DKIM, Domain Key Module on Postfix

• Crypt::OpenSSL::RSA
• Digest::SHA
• Digest::SHA1
• Error
• Mail::Address
• MIME::Base64
• Net::DNS
• Net::Server
• Test::More

DKIM, Domain Key Module을 설치하기 위해서 위와 같은 Perl module들이 필요하게 되고, 물론 Perl도 설치되어 있어야 한다. CPAN으로 설치가 가능한 환경이라면 아래와 같이 하면 된다.

cpan> install Crypt::OpenSSL::RSA Digest::SHA Digest::SHA1 Error Mail::Address MIME::Base64 Net::DNS Net::Server Test::More

그렇지 않다면 상당히 번거로운 작업이 되는데, 아래와 같이 각 Source들을 직접 download 받은 뒤 순서대로 작업을 하면 된다. 각 Module들이 각각 dependency가 존재 해 먼저 설치되어야만 하는 것들이 있다.

[PERL :Error] Error-0.17016.tar.gz
[PERL :Crypt::OpenSSL::RSA]
WITH Crypt::OpenSSL::Random
Crypt-OpenSSL-Random-0.04.tar.gz
Crypt-OpenSSL-RSA-0.26.tar.gz
[PERL :Net::DNS]
WITH Digest-HMAC
WITH Digest::SHA1
WITH Net::IP
WITH Digest::SHA
Digest-SHA1-2.12.tar.gz
Digest-HMAC-1.02.tar.gz
Net-IP-1.25.tar.gz
Digest-SHA-5.48.tar.gz
Net-DNS-0.66.tar.gz
[PERL :Mail::Address]
WITH Date::Format
WITH Date::Parse
WITH Test::Pod
TimeDate-1.20.tar.gz
Test-Pod-1.41.tar.gz
MailTools-2.06.tar.gz
[PERL :Mail-DomainKeys-0.80]
Mail-DomainKeys-0.80.tar.gz
[PERL :AppConfig-1.56]
AppConfig-1.56.tar.gz

위 추가적인 Perl Module을 설치해야만 Mail-DKIM과 DKIMPROXY가 설치가능하게 된다. Perl의 경우 압축 해제 후 perl Makefile.PL;make;make install 명령어로 설치한다.

[PERL :MAIL-DKIM]
Mail-DKIM-0.36.tar.gz
[DKIMPROXY : http://dkimproxy.sourceforge.net/download.html%5D
WITH PERL :Net::Server
Net-Server-0.97.tar.gz
tar zxvf dkimproxy-1.2.tar.gz
cd dkimproxy-1.2
./configure --prefix=/usr/local/dkimproxy
make;make install

이후 Rebooting시 자동으로 시작 되도록 등록하면 설치 완료.

$ cp source-directory/dkimproxy /etc/init.d/dkimproxy
$ vi dkimproxy
..
### BEGIN CONFIGURABLE BITS
DKIMPROXYDIR=/usr/local/dkimproxy
DKIMPROXYUSER=postfix
DKIMPROXYGROUP=postfix
### END CONFIGURABLE BITS
..
$ chkconfig dkimproxy on

7. Configure DKIM, Domain Key Module on Postfix

위 과정대로 설치를 하였다면 dkimproxy는 /usr/local/dkimproxy에 설치되어 있을 것이다. 그럼, inbound, outbound와 관련 된 설정파일을 설정하는데, 이 파일의 Inbound, outbound Port 즉 아래 설정 내용은 10025, 10026, 10027, 10028은 Postfix의 master.cf의 설정과 연동이 된다.

## Inbound
$ more /usr/local/dkimproxy/etc/dkimproxy_in.conf
# specify what address/port DKIMproxy should listen on
listen 127.0.0.1:10025

# specify what address/port DKIMproxy forwards mail to
relay 127.0.0.1:10026

## Outbound
$ more /usr/local/dkimproxy/etc/dkimproxy_out.conf
# specify what address/port DKIMproxy should listen on
listen 127.0.0.1:10027

# specify what address/port DKIMproxy forwards mail to
relay 127.0.0.1:10028

# specify what domains DKIMproxy can sign for (comma-separated, no spaces)
domain [each domain information]

# specify what signatures to add
signature dkim(c=relaxed)
signature domainkeys(c=nofws)

# specify location of the private key
keyfile /etc/domainkeys/default

# specify the selector (i.e. the name of the key record put in DNS)
selector default

그리고, Domain Key를 생성하고, 아래와 같이 Permission과 Ownership 설정을 한다.

mkdir -p /etc/domainkeys
cd /etc/domainkeys
openssl genrsa -out rsa.private 768
openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM
chown -R root.postfix /etc/domainkeys
chmod 755 /etc/domainkeys

$ rsa.private
-----BEGIN RSA PRIVATE KEY-----
MIIBygIBAAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGTgWIYzzY/TivZvGAaQWMW
K1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3LtQQQFUjMgc4JtAHZ13PR7
DNYWFGcF+oQh3QIDAQABAmB5VGGLHFxnmjRveIhMnVWJQ6yOzmmRC284fship3rd
12yiIczHCD9LJ3f43pWjf8s9G6NmpbYO5PZlhGMI9Sc0CM+ZOSfzQgaa2T/Jp7ol
GxgA+PIR+I8uvA7+3iNtIfUCMQDZfEaqFxl2X/Vx7HDIlkioN05Rq4JWIR0e60Ot
vZ6Swy1naK55hCmKJ4GqR+rzRu8CMQDYpTCaied2MJbAbdAf1jKB2GjqHroCCDI0
rqu4Nkp2vW/vt7k6C/I9MBTTkphtA/MCMQCkkKsPzUbREa8xsw1sWntD/gVfOv32
mjvkx3SApPi2aMWUd9t9y4l7JoWxCZY42zUCMDHXBvB2i1ZIZVYNrVS1rVbr128M
9JPlGM+/42d0rfrVJ/xJEwbEmszy08e8sO5bewIwaPvjrQG6sepZ3gSWcL+8Lg5f
dX2fJEbvJjNUFOgzqvmqaPujOR6nvhArLc/ZViDx
-----END RSA PRIVATE KEY-----

$ rsa.public
-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB

여기서 rsa.public에 있는 내용이 DNS TXT record의 p value로서 사용되게 된다. 아래 예를 참조.

k=rsa; t=y; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;

여기서 주의 할 점은 해당 Key는 한줄짜리 임으로 copy & paste 시 line 넘김이 발생하지 않도록 하는 것이다. 이것 때문에 문제가 생긴 적이 있었다.

그럼, Postfix에 dkimproxy를 적용 해 보자. Inbound, outbound에서 설정한 내용대로 Receive & Send가 적절하게 이루어 질 수 있도록 Postfix의 master.cf를 설정해야 한다.

## inbound and outbound filter
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
-o smtpd_proxy_filter=127.0.0.1:10024
-o smtpd_client_connection_count_limit=10
dksign-in unix - - n - 2 smtp
-o smtp_data_done_timeout=1200
-o smtp_send_xforward_command=yes
127.0.0.1:10026 inet n - n - - smtpd
-o content_filter=
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8
-o receive_override_options=no_unknown_recipient_checks
submission inet n - n - - smtpd
-o smtpd_etrn_restrictions=reject
-o smtpd_sasl_auth_enable=yes
-o content_filter=dksign:[127.0.0.1]:10027
-o receive_override_options=no_address_mappings
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
# -o smtpd_enforce_tls=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
smtps inet n - n - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
dksign unix - - n - 10 smtp
-o smtp_send_xforward_command=yes
-o smtp_discard_ehlo_keywords=8bitmime
127.0.0.1:10028 inet n - n - 10 smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8

여기서 일반 Mail을 보낼 때는 Port 25를 사용하면 되고 Domain Key가 Signed 된 Mail을 보낼 때는 submission Port 587을 사용하면 된다.

$ more /etc/services | grep 587
submission 587/tcp msa # mail message submission
submission 587/udp msa # mail message submission

8. Configure Domain Key on DNS

DNS는 아래와 같이 TXT 형식으로 저장을 하고,

[Zone File]
_domainkey TXT "t=n; o=-;"
[select name]._domainkey TXT "k=rsa; t=n; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;"

dig로 확인을 하면 아래와 같다.

$ dig _domainkey.[domain.com] txt
..
;; ANSWER SECTION:
_domainkey.[domain.com]. 300 IN TXT "t=y\; o=-\;"

$ dig [select name]._domainkey.[domain.com] txt
..
;; ANSWER SECTION:
_domainkey.[domain.com]. 300 IN TXT "k=rsa; t=y; p=MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALgNMgOmSOtOSD3wcDBKb+y2tM1ZOQGT
gWIYzzY/TivZvGAaQWMWK1XuLscr89pqw9tIXrJYrlN0lLhtiddXc9FZwL0AE3Lt
QQQFUjMgc4JtAHZ13PR7DNYWFGcF+oQh3QIDAQAB;"

또한, 아래 Site에서 정상 등록 여부 확인이 가능하다.
http://domainkeys.sourceforge.net/policycheck.html
http://domainkeys.sourceforge.net/selectorcheck.html

9. Start Postfix with Dovecot, DKIM, DomainKey, MySQL

각 Daemon의 기동은 간단하고, netstat를 통해 각 Port를 확인 할 수 있다.

$ /etc/init.d/dovecot start
$ /etc/init.d/dkimproxy start
$ /etc/init.d/postfix start
$ /etc/init.d/httpd start

$ netstat -an
..
tcp 0 0 127.0.0.1:10025 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10026 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10027 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:10028 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN
tcp 0 0 :::993 :::* LISTEN
tcp 0 0 :::995 :::* LISTEN
tcp 0 0 :::80 :::* LISTEN

각 Port의 대한 정보는 아래와 같다.

DKIM, DomainKey Processing => Local : 10025, 10026, 10027, 10028
DKIM, DomainKey Signed SMTP => 587
Normal SMTP => 25
POP3S => 995
IMAPS => 993
HTTP(WebMail) => 80 (Web Mail 서버가 설치되고, 기동 되었다면)

다음 시간에 위 Mail Server상에 Spam Filtering 설치 해 보도록 하겠습니다.

Linux #6 : Implement Postfix with Dovecot, DKIM, DomainKey, MySQL. #1

나는 이전엔 Q-Mail Platform을 상당히 선호하고 있었는데, Postfix로 전향을 하게 된 계기는 DSN(Delivery Status Notification) 기능의 구현을 위해서 였다. Q-Mail을 통한 구현을 여기저기 찾아 보았는데, 결국 허탕을 치고 모든 E-Mail Platform을 Postfix로 바꾸게 되었다. 일본에 있을 때도 그렇고 쭉 5년 넘게 Q-Mail을 다루었던 경험으로 인해 처음엔 Postfix가 어찌 그리 귀찮고 낯설었는지.. 시간이 지난 지금 Postfix가 이젠 Q-Mail보다 좋은 느낌이다.

1. Installation of Postfix

간단하게 Source RPM으로 설치해도 문제가 없으므로, Lastest Version은 아래에서 구하면 된다.
http://ftp.wl0.org/official/2.7/SRPMS/

rpm -ivh [PostFix SRPM]

* 참고로 필자가 사용한 Version은 postfix-2.3.3-2.1.el5_2.src.rpm, 또한 2.3.3 version을 위한 Patch가 있으므로 postfix-2.3.3-vda.patch.gz와 postfix-sleep.patch도 download 받는다.

# cp postfix-2.3.3-vda.patch.gz /usr/src/redhat/SOURCES
# cd /usr/src/redhat/SOURCES
# gunzip postfix-2.3.3-vda.patch.gz
# cp postfix-sleep.patch /usr/src/redhat/SOURCES
# cd /usr/src/redhat/SPECS/
# cp postfix.spec postfix.spec.old

후 MySQL과 Dovecot을 사용하기 위해 Parameter를 변경 해 줄 필요가 있다.

# cd /usr/local/redhat/SPECS/
# vi postfix.spec
..
%define with_mysql  0  ->  1
%define with_dovecot 0 -> 1
..

또한, Patch를 위해 아래와 같은 정보를 추가 해 준다.
(예제에서의 84, 85, 141, 142는 Line Number, Patch Number인 Patch11, 12는 실제와 다를 수 있다.)

84 Patch11: postfix-2.3.3-vda.patch
85 Patch12: postfix-sleep.patch

141 %patch11 -p1 -b .vda
142 %patch12 -p1 -b .sleep

추가적으로 RPMBUILD 및 Authentication 관련 Libary가 필요 하게 되는데 System 상에 설치되어 있지 않을 수도있으므로 아래 command를 실행 해 준다.

# yum -y install pkgconfig rpm-build db4-devel zlib-devel openldap-devel cyrus-sasl-devel pcre-devel mysql-devel openssl-devel

RPMBUILD를 통해 rpm 파일을 생성 후, 설치를 한다.

# rpmbuild -ba postfix.spec
# cd /usr/src/redhat/RPMS
# rpm -Uhv /usr/src/redhat/RPMS/x86_64/[PostFix RPM] (if x86_64)
# rpm -Uhv /usr/src/redhat/RPMS/i386/[PostFix RPM] (if i386)

YUM을 통해 Postfix가 Updating 되지 않도록 아래와 같이 설정을 한다.

# vi /etc/yum.conf
..
exclude=postfix*
..

Booting시 자동 기동을 위해

# chkconfig postfix on

해주면 Postfix 설치는 일단 끝이난다.

2. Installation of Dovecot

Dovecot은 POP3 및 IMAP Server로 Postfix와 같이 구성할 수 있다. Yum을 사용할 수 있다면 설치는 간단하다.

# yum install dovecot
# chkconfig dovecot on

TLS통한 인증 접근을 구성(POP3S, IMAPS)하고 싶다면 인증 Key를 아래와 같이 생성한다.

# cd /etc/pki/tls/certs
# make [Key_Name].pem
# openssl x509 -in [Key_Name].pem -outform DER -out [Key_Name].der

Additional : 필요한 경우 아래 Library도 설치

# yum -y install cyrus-sasl-md5 cyrus_sasl_sql cyrus-sasl-plain
# yum install gnutls

3. Installation of MySQL DB

MySQL은 Account 관련 정보 / Virtual Domain 관련 정보 / Domain 관련 정보를 관리하기 위함이다.

# version : 5.0.77 (필자가 사용한 Version임)
# ./configure --prefix=/usr/local/mysql --enable-thread-safe-client --with-innodb
# make;make install
# cd /usr/local/mysql
# cp /usr/local/mysql/share/mysql/my-[select].cnf /usr/local/mysql/my.cnf

* 환경에 맞춰 my.cnf file을 선택 설정을 한다.

4. Intallation of Apache with PHP

Apache Web Server는 Web-Mail Service를 제공하거나, Postfix Admin을 사용하고 싶은 경우 설치하면 된다.

# yum install httpd
# chkconfig --level 235 httpd off
** Apache도 환경에 맞게 설정을 한다.

5. Making and checking each configuration files for Postfix and dovecot

Postfix configuration files들은 /etc/postix Directory안에 있다.

Edit /etc/postfix/master.cf
Edit /etc/postfix/main.cf

Dovecot configuration files :
Edit /etc/dovecot.conf
Edit /etc/dovecot-mysql.conf   (MySQL DB의 Account 정보를 획득을 위한 파일)

Postfix with MySQL configuration files :
Edit /etc/postfix/mysql_virtual_alias_maps.cf
Edit /etc/postfix/mysql_virtual_domains_maps.cf
Edit /etc/postfix/mysql_virtual_mailbox_maps.cf

위 3 files은 Postfix의 virtual alias, domains, mailbox 정보를 관리하기 위한 파일이다.

설정과 관련 된 자세한 내용은 Implement Postfix with Dovecot, DKIM, DomainKey, MySQL. #2에서..