<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Topdog.za.net</title>
    <link>http://www.topdog.za.net</link>
    <description>A bored sysadmin</description>
    <pubDate>Fri, 26 Feb 2016 10:06:56 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>How to fix Exim SMTP AUTH rewritting the from address</title>
      <link>http://www.topdog.za.net/2012/06/08/how-to-fix-exim-smtp-auth-rewritting-the-from-address</link>
      <pubDate>Fri, 08 Jun 2012 07:55:00 SAST</pubDate>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Email]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2012/06/08/how-to-fix-exim-smtp-auth-rewritting-the-from-address</guid>
      <description>How to fix Exim SMTP AUTH rewritting the from address</description>
      <content:encoded><![CDATA[<p>When using SMTP Authentication with exim and the default configuration
you will find that exim rewrites the sender address to "email@address"@smtp_server_hostname</p>
<pre><code>Return-Path:    &lt;"andrew@topdog.za.net"@xxxx.xxxx.co.za&gt;
...
Sender:     "andrew@topdog.za.net"@xxxx.xxxx.co.za
...
</code></pre>
<p>To fix this you need to modify your acl_check_rcp acl and add sender_retain to
control.</p>
<pre><code>accept  authenticated = *
          control       = submission/sender_retain
</code></pre>
<p>Restart exim and you are good to go.</p>]]></content:encoded>
    </item>
    <item>
      <title>Block Spam from domains on the South Africa ISPA Spam Hall of Shame using DNSBL Part2</title>
      <link>http://www.topdog.za.net/2012/05/11/block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl-part2</link>
      <pubDate>Fri, 11 May 2012 07:30:00 SAST</pubDate>
      <category><![CDATA[Postfix]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Email]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2012/05/11/block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl-part2</guid>
      <description>Block Spam from domains on the South Africa ISPA Spam Hall of Shame using DNSBL Part2</description>
      <content:encoded><![CDATA[<p>I previously <a href="http://www.topdog.za.net/2012/04/22/tip:-block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl/">wrote</a>
about how to block domains named in the ISPA Spam Hall of Shame using DNSBL at
SMTP time, these domains have now resorted to using 3rd party senders to try and get their Junk
through. Because they are using 3rd party senders the envelope from address is no longer the one
that is listed on the hall of shame.</p>
<p>In this post i will describe how you can catch the mail that has slipped through your SMTP DNSBL
checks.</p>
<p>To identify these messages i use <a href="http://spamassassin.apache.org/">Spamassassin's</a> <a href="http://search.cpan.org/dist/Mail-SpamAssassin/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm">URIDNSBL plugin</a>
which extracts the uri's in an email and checks each of them against the DNSBL.</p>
<p>Create a file called ispa.cf in your Spamassassin configuration directory usually
/etc/mail/spamassassin with the following contents</p>
<pre><code># /etc/mail/spamassassin/ispa.cf
urirhsbl        URIBL_BARUWA    ispa.rbl.baruwa.net.   A
body            URIBL_BARUWA    eval:check_uridnsbl('URIBL_BARUWA')
describe        URIBL_BARUWA    Contains a URL listed in the Baruwa blocklist
score           URIBL_BARUWA    7.0
</code></pre>
<p>Restart Spamassassin and email from those domains that by pass the DNSBL checks by using 3rd
party senders should now be tagged as Spam by Spamassassin with a score of 7.0</p>
<p>Feedback is welcome, as Spam fighting is always an on going battle.</p>]]></content:encoded>
    </item>
    <item>
      <title>TIP: Block Spam from domains on the South Africa ISPA Spam Hall of Shame using DNSBL</title>
      <link>http://www.topdog.za.net/2012/04/22/tip:-block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl</link>
      <pubDate>Sun, 22 Apr 2012 09:30:00 SAST</pubDate>
      <category><![CDATA[Postfix]]></category>
      <category><![CDATA[Howto]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Email]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Security]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2012/04/22/tip:-block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl</guid>
      <description>TIP: Block Spam from domains on the South Africa ISPA Spam Hall of Shame using DNSBL</description>
      <content:encoded><![CDATA[<p>The South Africa Internet service providers association <a href="http://ispa.org.za/">(ISPA)</a> maintains a list of known
spammers dubbed the <a href="http://ispa.org.za/spam/hall-of-shame/">Spam Hall of Shame</a>.
The list is contains both domains as well as email addresses, this list is published
on a webpage without downloadable formats.</p>
<p>I extract the data from this web page and publish it in a DNSBL ispa.rbl.baruwa.net,
i use this DNSBL in my <a href="http://www.baruwa.net">SAAS mail security product</a>. So anyone
should be able to use it in a similar way to the other DNSBL's like spamhaus and
spamcop etc.</p>
<h2>Command line checking</h2>
<p>You can check if a domain is on the list using the normal command line utilities</p>
<p>Using host:</p>
<pre><code>host amazingresults.co.za.ispa.rbl.baruwa.net
</code></pre>
<p>Output:</p>
<pre><code>amazingresults.co.za.ispa.rbl.baruwa.net has address 127.0.0.2
</code></pre>
<p>Using dig:</p>
<pre><code>dig amazingresults.co.za.ispa.rbl.baruwa.net
</code></pre>
<p>Output:</p>
<pre><code>;; QUESTION SECTION:
;amazingresults.co.za.ispa.rbl.baruwa.net. IN A

;; ANSWER SECTION:
amazingresults.co.za.ispa.rbl.baruwa.net. 1993 IN A 127.0.0.2
</code></pre>
<p>Checking the TXT output:</p>
<pre><code>host -t txt amazingresults.co.za.ispa.rbl.baruwa.net
</code></pre>
<p>Output:</p>
<pre><code>amazingresults.co.za.ispa.rbl.baruwa.net descriptive text 
"Domain amazingresults.co.za is listed in the ISPA Hall of Shame,
http://ispa.org.za/spam/hall-of-shame/"
</code></pre>
<h2>Usage</h2>
<p>Usage of the DNSBL in various MTA's is described below.</p>
<h3>Exim</h3>
<p>Add the following to your rcpt acl (acl_check_rcpt:).</p>
<pre><code>drop    message       = REJECTED - $dnslist_text
        dnslists      = ispa.rbl.baruwa.net/$sender_address_domain
</code></pre>
<h3>Postfix</h3>
<p>Add to smtpd_recipient_restrictions after permit_mynetworks in your
main.cf file</p>
<pre><code>reject_rhsbl_client ispa.rbl.baruwa.net,
reject_rhsbl_sender ispa.rbl.baruwa.net,
</code></pre>
<h3>Sendmail</h3>
<p>Add to your mc file and rebuild the cf</p>
<pre><code>FEATURE(rhsbl,`ispa.rbl.baruwa.net',`"550 Mail from domain " $`'&amp;{RHS} " refused.
Domain is listed in the ISPA Hall of Shame -  http://ispa.org.za/spam/hall-of-shame/"')
</code></pre>
<h2>How the data is extracted</h2>
<p>The data is extracted using an <a href="http://www.topdog.za.net/2012/04/22/python-modules-you-should-know:-scrapy/">automated custom web</a> crawler written using <a href="http://scrapy.org/">Scrapy</a> in Python.
The crawler extracts both the domains and the email addresses, the domains are processed and added to the DNSBL,
the emails addresses get processed and added to the email blacklists on our <a href="http://www.baruwa.net">SAAS platform</a>.</p>
<h2>Update</h2>
<p>Some of these domains have resorted to using third party senders, which means the smtp
envelope is no longer the one listed on the hall of shame, i have written a <a href="http://www.topdog.za.net/2012/05/11/block-spam-from-domains-on-the-south-africa-ispa-spam-hall-of-shame-using-dnsbl-part2/">followup post</a>
which describes how you can identify and flag as spam these messages that bypass the
SMTP time DNSBL checks.</p>]]></content:encoded>
    </item>
    <item>
      <title>TIP: Use a random IP address from an pool of addresses with Exim</title>
      <link>http://www.topdog.za.net/2012/04/21/tip:-use-a-random-ip-address-from-an-pool-of-addresses-with-exim</link>
      <pubDate>Sat, 21 Apr 2012 08:21:00 SAST</pubDate>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2012/04/21/tip:-use-a-random-ip-address-from-an-pool-of-addresses-with-exim</guid>
      <description>TIP: Use a random IP address from an pool of addresses with Exim</description>
      <content:encoded><![CDATA[<p>Create a lookup file /etc/exim/ips.txt with</p>
<pre><code>1: xxx.xxx.xxx.1
2: xxx.xxx.xxx.2
3: xxx.xxx.xxx.3
4: xxx.xxx.xxx.4
</code></pre>
<p>Set the transport to:</p>
<pre><code>remote_smtp:
  driver = smtp
  interface = "${lookup {${randint:5}} lsearch {/etc/exim/ips.txt}}"
</code></pre>
<p>randint will return a random number between 1-4 which is then looked up
in the file and used if you have more ip's just add to the list and
increment the randint value to number ips + 1</p>]]></content:encoded>
    </item>
    <item>
      <title>Exim commands you should know</title>
      <link>http://www.topdog.za.net/2012/04/15/exim-commands-you-should-know</link>
      <pubDate>Sun, 15 Apr 2012 11:56:00 SAST</pubDate>
      <category><![CDATA[Tips]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2012/04/15/exim-commands-you-should-know</guid>
      <description>Exim commands you should know</description>
      <content:encoded><![CDATA[<p>Print out the exim configuration options</p>
<pre><code>exim -bP
</code></pre>
<p>Print the contents of the queue</p>
<pre><code>exim -bp
</code></pre>
<p>Print the number of items in the queue</p>
<pre><code>exim -bpc
</code></pre>
<p>Test addresses</p>
<pre><code>exim -bt addresss
</code></pre>
<p>Print exim version and test configuration</p>
<pre><code>exim -bV
</code></pre>
<p>Verify addresses</p>
<pre><code>exim -bv address
</code></pre>
<p>Deliver a message</p>
<pre><code>exim -M message-id
</code></pre>
<p>Add addresses to a message</p>
<pre><code>exim -Mar message-id address address
</code></pre>
<p>Freeze messages to prevent delivery</p>
<pre><code>exim -Mf message-id
</code></pre>
<p>Force delivery of a message</p>
<pre><code>exim -Mg message-id
</code></pre>
<p>Remove a message from the queue</p>
<pre><code>exim -Mrm message-id
</code></pre>
<p>Unfreeze a message</p>
<pre><code>exim -Mt message-id
</code></pre>
<p>Display a message</p>
<pre><code>exim -Mvc message-id
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Mail server setup with Exim, MySQL, Cyrus-Imapd, Horde webmail on Centos 5.1</title>
      <link>http://www.topdog.za.net/2009/03/04/mail-server-setup-with-exim--mysql--cyrus-imapd--horde-webmail-on-centos-5.1</link>
      <pubDate>Wed, 04 Mar 2009 12:37:00 SAST</pubDate>
      <category><![CDATA[Horde]]></category>
      <category><![CDATA[Centos]]></category>
      <category><![CDATA[Howto]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Cyrus]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Email]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2009/03/04/mail-server-setup-with-exim--mysql--cyrus-imapd--horde-webmail-on-centos-5.1</guid>
      <description>Mail server setup with Exim, MySQL, Cyrus-Imapd, Horde webmail on Centos 5.1</description>
      <content:encoded><![CDATA[<h2>Introduction</h2>
<p>This how to describes the installation and configuration of a mail system on
Centos 5.1 with selinux enabled for enhanced security. This system will be
able to service HTTP, HTTPS, SMTP, TLS, SMTP-AUTH, IMAP, POP3 clients and is
virtual enabled allowing more that one domain to be served from the system.</p>
<p>The webmail client imp will provide a feature rich interface with a webmail
component, an address book, calendaring, and ability to reset passwords all
with a highly configurable preference system to enable users to modify their
look and feel as well as the operation of the interface.</p>
<p>The IMAP/POP3 system is the high performance cyrus-imapd system that runs as a
sealed unit (mail users are not system users) and utilizes a high end/
performance back end for mail storage. The other cyrus-imapd features include,
mail indexing for quick search operations using squat, a notification daemon
that can be configured to notify via sms or email, sieve filtering system
(auto response, mail filtering, notifications, filing), and built in quota
system. This system will use pam_mysql via the SASL (saslauthd) mechanism to
authenticate users against the Mysql database back end shared by all the
components.</p>
<p>The exim system will be configured to enable users relay mail using TLS
secured SMTP-AUTH, using the same database backend that is shared by all the
components. Address verification will take place using SQL queries to the
mysql backend before any mail is accepted for delivery to the cyrus-imapd mail
store. Anti-virus checks are integrated into this system with the use of
clamav via a Unix domain socket. Spam checks are also run at smtp time via a
socket connection to the spamd spamassasin system messages scoring over 6 are
automatically rejected with out being spooled to the system.</p>
<p>The mysql database will store the user authentication information encrypted
using md5-hex as well as other information for the other webmail components.</p>
<p>This system is designed for high performance and security, cutting down on
open ports and prefering to use unix domain sockets and running selinux in
enforcing mode.</p>
<p>User account management takes place via the horde web interface allowing the
admin easy access to add and remove accounts or to manage passwords, it is
also possible to interact directly with the database table and make
alterations there.</p>
<h2>OS Installation notes</h2>
<p>For the purpose of keeping this howto precise i will not take you through the
actually installation of the Centos 5.1 system i will assume that you have a
bare bones install, a kickstart to help you get a bare bones install is can be
downloaded <a href="http://www.topdog-software.com/files/barebones.ks">here</a></p>
<p>For this tutorial i will be using the static IP address 192.168.1.4 and the
hostname mail.home.topdog-software.com with a domain of home.topdog-
software.com, please feel free to make alterations to suite your environment.
The working directory will be /usr/local/src all packages to be downloaded
should be downloaded and extracted there.</p>
<h2>Software installation</h2>
<h3>Install prerequisites</h3>
<p>Update the system.</p>
<pre><code>yum update
</code></pre>
<p>Configure rpmforge repo</p>
<pre><code>rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
</code></pre>
<p>Disable the repo (such that base packages not overwritten) edit /etc/yum.d/rpmforge.repo and set the following option</p>
<pre><code>enabled = 0
</code></pre>
<h3>Install Apache</h3>
<pre><code>yum install httpd php php-mysql php-xml php-imap php-mbstring php-mcrypt \
php-pecl-Fileinfo php-pear-DB php-pear-File php-pear-Log php-pear-Mail-Mime \
php-pear-Auth-SASL php-pear-Date php-pear-HTTP-Request php-pear-Mail php-pear-Net-Sieve \
php-pear-Net-Socket php-pear-Net-SMTP openssl mod_ssl -y
</code></pre>
<h3>Install Exim</h3>
<pre><code>yum install exim system-switch-mail -y
</code></pre>
<h3>Install Mysql</h3>
<pre><code>yum install mysql mysql-server -y
</code></pre>
<h3>Install Horde</h3>
<pre><code>yum install horde imp-h3 ingo-h3 turba-h3 kronolith-h3 -y
wget ftp://ftp.horde.org/pub/passwd/passwd-h3-3.0.1.tar.gz
tar xzvf passwd-h3-3.0.1.tar.gz -C /usr/share/horde
mv /usr/share/horde/passwd-h3-3.0.1 /usr/share/horde/passwd
</code></pre>
<h3>Install cyrus-imapd</h3>
<p>I will use the <a href="http://www.invoca.ch/pub/packages/cyrus-imapd/">Invoca systems source rpm</a> as it is more recent and support many features that the Centos
build does not provide.</p>
<pre><code>yum install db4-utils -y
rpm -Uvh http://www.topdog-software.com/oss/cyrus-imapd/cyrus-imapd-perl-2.3.11-3.i386.rpm
rpm -Uvh http://www.topdog-software.com/oss/cyrus-imapd/cyrus-imapd-utils-2.3.11-3.i386.rpm
rpm -Uvh http://www.topdog-software.com/oss/cyrus-imapd/cyrus-imapd-2.3.11-3.i386.rpm
</code></pre>
<h3>Install Pam_mysql</h3>
<pre><code>rpm -Uvh http://www.topdog-software.com/oss/pam_mysql/pam_mysql-0.7RC1-1.i386.rpm
</code></pre>
<h3>Install ClamAV</h3>
<pre><code>yum --enablerepo=rpmforge install clamav clamav-db clamd -y
</code></pre>
<h3>Install Spamassassin</h3>
<pre><code>yum install spamassassin -y
</code></pre>
<h2>Configuration</h2>
<h3>Configure Apache</h3>
<p>Enable virtual hosting and create default virtualhost, edit /etc/httpd/conf/httpd.conf and add at the end</p>
<pre><code>NameVirtualHost *:80
&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@home.topdog-software.com
&lt;/VirtualHost&gt;
</code></pre>
<p>Create the virtual host for horde webmail add this under the above</p>
<pre><code>&lt;VirtualHost *:80&gt;
        Servername mail.home.topdog-software.com
        DocumentRoot /usr/share/horde
        ErrorLog logs/mail-error_log
        CustomLog logs/mail-access_log common
&lt;/VirtualHost&gt;
</code></pre>
<p>Enable horde security settings edit the file /etc/httpd/conf.d/horde.conf and set as below</p>
<pre><code>#Alias /horde /usr/share/horde
&lt;Directory /usr/share/horde&gt;

    Options +FollowSymLinks
    php_admin_flag safe_mode off
    php_admin_flag magic_quotes_runtime off
    php_flag session.use_trans_sid off
    php_flag session.auto_start off
    php_admin_flag file_uploads on
    #php_admin_flag allow_url_fopen on

    php_value post_max_size 20M
    php_value upload_max_filesize 10M

    php_admin_value open_basedir "/usr/share/horde:/usr/share/horde/config:/usr/share/pear:/tmp"
    php_admin_flag register_globals off
&lt;/Directory&gt;

&lt;Directory /usr/share/horde/config&gt;
    Order Deny,Allow
    Deny from all
&lt;/Directory&gt;

&lt;DirectoryMatch "^/usr/share/horde/(.*/)?(config|lib|locale|po|scripts|templates)/(.*)?"&gt;
    Order Deny,Allow
    Deny from all
&lt;/DirectoryMatch&gt;
</code></pre>
<p>Increase PHP memory limit edit /etc/php.ini and change to below</p>
<pre><code>memory_limit = 64M
</code></pre>
<p>Enable horde under SSL edit /etc/httpd/conf.d/ssl.conf and add the following to the default virtualhost between the <VirtualHost _default_:443><VirtualHost> tags</p>
<pre><code>Servername mail.home.topdog-software.com:443
DocumentRoot /usr/share/horde
</code></pre>
<h3>Configure Exim</h3>
<p>Switch the MTA to exim</p>
<pre><code> system-switch-mail (select exim)
</code></pre>
<h4>Anti-virus / Sanesecurity Checks</h4>
<p>Configure Exim (/etc/exim/exim.conf) to use clamav to scan incoming mail and reject virus infected email and image and pdf spam at smtp time.</p>
<pre><code>av_scanner = clamd:/var/run/clamav/clamd.sock
</code></pre>
<h4>RBL's</h4>
<p>Configure the RBL's under acl_check_rcpt: </p>
<pre><code>drop    message       = REJECTED because $sender_host_address is in a black list spamhaus.org
           dnslists      = zen.spamhaus.org

drop    message       = REJECTED because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
           dnslists      = bl.spamcop.net

drop    message       = REJECTED because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
           dnslists      = dnsbl.sorbs.net
</code></pre>
<h4>Anti Spam</h4>
<p>If you want to reject messages from servers with no reverse dns add this under acl_check_rcpt:, it does have a exception list to which you can add domains where the acl should not be applied and trys to deliver a test message to sending address to verify if the sender is valid.</p>
<pre><code>drop  message   = REJECTED - We don't accept messages from hosts without reverse DNS
        log_message = No reverse DNS
        domains = ! lsearch;/etc/exim/checks_exempt_hosts
        !verify = reverse_host_lookup
        !verify = sender/callout=2m,defer_ok
        !condition =  ${if eq{$sender_verify_failure}{}}
</code></pre>
<p>To reject messages from clients that dont provide a HELO/EHLO add this to acl_check_rcpt:</p>
<pre><code>drop  message  = REFUSED - no HELO/EHLO greeting
        log_message = remote host did not present greeting
        condition = ${if def:sender_helo_name {false}{true}}
</code></pre>
<p>You can rate limit the connections to your server as well add this to acl_check_connect: to do so (read the exim docs on the parameters if you want to fine tune it for your site)</p>
<pre><code>deny ratelimit = 250 / 15m / strict
       message = You can only send $sender_rate per $sender_rate_period
       log_message = RATE: $sender_rate/$sender_rate_period (max $sender_rate_limit)

accept
</code></pre>
<p>Stop rogue spam bots from trashing your machine</p>
<pre><code>smtp_accept_max_nonmail = 30
smtp_max_unknown_commands = 1
</code></pre>
<p>Don't advertise pipelining</p>
<pre><code>pipelining_advertise_hosts =
</code></pre>
<p>Enable Spamassassin checks</p>
<pre><code>spamd_address = /var/run/spamassassin/spamd.sock
</code></pre>
<p>Reject all messages with score above 6 at smtp time. (acl_check_data)</p>
<pre><code>accept  condition  = ${if &gt;={$message_size}{100000} {1}}
        add_header = X-Spam-Note: SpamAssassin run bypassed due to message size

  warn    spam       = nobody/defer_ok
        add_header = X-Spam-Flag: YES

  accept  condition  = ${if !def:spam_score_int {1}}
        add_header = X-Spam-Note: SpamAssassin invocation failed

  warn    add_header = X-Spam-Score: $spam_score ($spam_bar)\n\
#       X-Spam-Report: $spam_report

  drop    condition = ${if &gt;{$spam_score_int}{60} {1}}
        message   = Your message scored $spam_score SpamAssassin point. Report follows:\n\
        $spam_report
</code></pre>
<h4>Mail routing</h4>
<p>Enable access to Mysql database</p>
<pre><code>hide mysql_servers = localhost/horde/horde/hordepassword
</code></pre>
<p>Modify the local delivery router to deliver to cyrus but verify the email address of user before delivery (in routers section of exim.conf)</p>
<pre><code>localuser:
  driver = accept
  local_parts = ${lookup mysql {SELECT REPLACE(user_uid,'${quote_mysql:@$domain}','') \
         as user FROM horde_users WHERE user_uid='${quote_mysql:$local_part@$domain}'}{$value}}
  transport = local_delivery
  cannot_route_message = Unknown user
</code></pre>
<p>Create a transport to deliver to cyrus via lmtp socket</p>
<pre><code>local_delivery:
  driver = lmtp
  socket = /var/lib/imap/socket/lmtp
  batch_max = 50
  user = cyrus
</code></pre>
<h4>SMTP Authentication</h4>
<p>Add the following to the authentication section of /etc/exim/exim.conf</p>
<pre><code>plain:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :
  server_set_id = $2
  server_condition = ${if saslauthd{{$2}{$3}{pop}}{1}{0}}
  server_advertise_condition = true

login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = ${if saslauthd{{$1}{$2}{pop}}{1}{0}}
  server_set_id = $1
  server_advertise_condition = true
</code></pre>
<h4>Full sample configuration</h4>
<p>Download the full configuration file <a href="http://www.topdog-
software.com/files/exim.conf.gz">here</a></p>
<h3>Configure Mysql</h3>
<p>Disable TCP networking edit /etc/my.cnf and the following in the mysqld section</p>
<pre><code>skip-networking
</code></pre>
<p>Set root password</p>
<pre><code>/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h impi password 'new-password' -p
</code></pre>
<h3>Configure Horde</h3>
<p>Edit the sql file and change the mysql password for the horde user</p>
<pre><code>cp /usr/share/horde/scripts/sql/create.mysql.sql .
vi create.mysql.sql

REPLACE INTO user (host, user, password)
    VALUES (
        'localhost',
        'horde',
-- IMPORTANT: Change this password!
        PASSWORD('hordepassword')
);
</code></pre>
<p>Create the user and populate the horde database</p>
<pre><code>mysql -p &lt; create.mysql.sql
</code></pre>
<p>Create the tables for turba (Address book)</p>
<pre><code>mysql -p horde &lt; /usr/share/horde/turba/scripts/sql/turba_objects.mysql.sql
</code></pre>
<p>Create the tables for kronolith (calendering)</p>
<pre><code>mysql -p horde &lt; /usr/share/horde/kronolith/scripts/sql/kronolith.mysql.sql
</code></pre>
<h4>Horde configuration</h4>
<p>Create horde base configuration /usr/share/horde/config/conf.php</p>
<pre><code>&lt;?php
$conf['debug_level'] = E_ALL;
$conf['max_exec_time'] = 0;
$conf['compress_pages'] = true;
$conf['umask'] = 077;
$conf['use_ssl'] = 2;
$conf['server']['name'] = $_SERVER['SERVER_NAME'];
$conf['server']['port'] = $_SERVER['SERVER_PORT'];
$conf['session']['name'] = 'Horde';
$conf['session']['use_only_cookies'] = true;
$conf['session']['cache_limiter'] = 'nocache';
$conf['session']['timeout'] = 0;
$conf['cookie']['domain'] = $_SERVER['SERVER_NAME'];
$conf['cookie']['path'] = '/';
$conf['sql']['username'] = 'horde';
$conf['sql']['password'] = 'hordepassword';
$conf['sql']['socket'] = '/var/lib/mysql/mysql.sock';
$conf['sql']['protocol'] = 'unix';
$conf['sql']['database'] = 'horde';
$conf['sql']['charset'] = 'iso-8859-1';
$conf['sql']['phptype'] = 'mysqli';
$conf['auth']['admins'] = array('Administrator', 'andrew@home.topdog-software.com');
$conf['auth']['checkip'] = true;
$conf['auth']['checkbrowser'] = true;
$conf['auth']['alternate_login'] = false;
$conf['auth']['redirect_on_logout'] = false;
$conf['auth']['params']['driverconfig'] = 'horde';
$conf['auth']['params']['table'] = 'horde_users';
$conf['auth']['params']['username_field'] = 'user_uid';
$conf['auth']['params']['password_field'] = 'user_pass';
$conf['auth']['params']['encryption'] = 'md5-hex';
$conf['auth']['params']['show_encryption'] = false;
$conf['auth']['driver'] = 'sql';
$conf['signup']['allow'] = false;
$conf['log']['priority'] = PEAR_LOG_NOTICE;
$conf['log']['ident'] = 'HORDE';
$conf['log']['params'] = array();
$conf['log']['name'] = '/tmp/horde.log';
$conf['log']['params']['append'] = true;
$conf['log']['type'] = 'file';
$conf['log']['enabled'] = true;
$conf['log_accesskeys'] = false;
$conf['prefs']['params']['driverconfig'] = 'horde';
$conf['prefs']['driver'] = 'sql';
$conf['datatree']['params']['driverconfig'] = 'horde';
$conf['datatree']['driver'] = 'sql';
$conf['group']['driver'] = 'datatree';
$conf['cache']['default_lifetime'] = 1800;
$conf['cache']['params']['dir'] = Horde::getTempDir();
$conf['cache']['params']['gc'] = 86400;
$conf['cache']['driver'] = 'file';
$conf['token']['driver'] = 'none';
$conf['mailer']['params']['auth'] = '0';
$conf['mailer']['type'] = 'smtp';
$conf['vfs']['params']['driverconfig'] = 'horde';
$conf['vfs']['type'] = 'sql';
$conf['sessionhandler']['params']['persistent'] = false;
$conf['sessionhandler']['params']['rowlocking'] = true;
$conf['sessionhandler']['params']['socket'] = '/var/lib/mysql/mysql.sock';
$conf['sessionhandler']['params']['protocol'] = 'unix';
$conf['sessionhandler']['params']['hostspec'] = 'localhost';
$conf['sessionhandler']['params']['username'] = 'horde';
$conf['sessionhandler']['params']['password'] = 'hordepassword';
$conf['sessionhandler']['params']['database'] = 'horde';
$conf['sessionhandler']['type'] = 'mysql';
$conf['problems']['email'] = 'webmaster@home.topdog-software.com';
$conf['problems']['maildomain'] = 'home.topdog-software.com';
$conf['problems']['tickets'] = false;
$conf['menu']['apps'] = array();
$conf['menu']['always'] = true;
$conf['menu']['links']['help'] = 'authenticated';
$conf['menu']['links']['help_about'] = true;
$conf['menu']['links']['options'] = 'authenticated';
$conf['menu']['links']['problem'] = 'never';
$conf['menu']['links']['login'] = 'all';
$conf['menu']['links']['logout'] = 'authenticated';
$conf['hooks']['permsdenied'] = false;
$conf['hooks']['username'] = false;
$conf['hooks']['preauthenticate'] = false;
$conf['hooks']['postauthenticate'] = false;
$conf['hooks']['authldap'] = false;
$conf['portal']['fixed_blocks'] = array();
$conf['accounts']['driver'] = 'null';
$conf['imsp']['enabled'] = false;
$conf['kolab']['enabled'] = false;
</code></pre>
<p>Set horde preferences to make web mail the default application on logging in. Edit the file /usr/share/horde/config/prefs.php and modify $_prefs['initial_application'] to look as below</p>
<pre><code>$_prefs['initial_application'] = array(
    'value' =&gt; 'imp',
    'locked' =&gt; true,
    'shared' =&gt; true,
    'type' =&gt; 'select',
    'desc' =&gt; sprintf(_("What application should %s display after login?"), $GLOBALS['registry']-&gt;get('name'))
);
</code></pre>
<p>Make horde work from within the default root of the web servers, edit /usr/share/horde/config/registry.php and modify $this→applications['horde'] as below</p>
<pre><code>$this-&gt;applications['horde'] = array(
    'fileroot' =&gt; dirname(__FILE__) . '/..',
    'webroot' =&gt; '',
    'initial_page' =&gt; 'login.php',
    'name' =&gt; _("Horde"),
    'status' =&gt; 'active',
    'templates' =&gt; dirname(__FILE__) . '/../templates',
    'provides' =&gt; 'horde'
);
</code></pre>
<h4>IMP configuration</h4>
<p>Create imp base configuration /usr/share/horde/imp/config/conf.php</p>
<pre><code>&lt;?php
$conf['utils']['spellchecker'] = '/usr/bin/aspell';
$conf['utils']['gnupg'] = '/usr/bin/gpg';
$conf['utils']['gnupg_keyserver'] = array('pgp.mit.edu');
$conf['utils']['gnupg_timeout'] = '10';
$conf['utils']['openssl_cafile'] = '/etc/pki/tls/certs';
$conf['utils']['openssl_binary'] = '/usr/bin/openssl';
$conf['menu']['apps'] = array('ingo', 'kronolith', 'passwd', 'turba');
$conf['user']['select_sentmail_folder'] = false;
$conf['user']['allow_resume_all_in_drafts'] = true;
$conf['user']['allow_folders'] = true;
$conf['user']['allow_resume_all'] = false;
$conf['user']['allow_view_source'] = true;
$conf['user']['alternate_login'] = false;
$conf['user']['redirect_on_logout'] = false;
$conf['server']['change_server'] = false;
$conf['server']['change_port'] = false;
$conf['server']['change_protocol'] = false;
$conf['server']['change_smtphost'] = false;
$conf['server']['change_smtpport'] = false;
$conf['server']['server_list'] = 'none';
$conf['server']['sort_limit'] = '0';
$conf['server']['cache_folders'] = false;
$conf['server']['cache_msgbody'] = true;
$conf['mailbox']['show_attachments'] = false;
$conf['mailbox']['show_preview'] = false;
$conf['mailbox']['show_xpriority'] = false;
$conf['fetchmail']['show_account_colors'] = false;
$conf['fetchmail']['size_limit'] = '4000000';
$conf['msgsettings']['filtering']['words'] = './config/filter.txt';
$conf['msgsettings']['filtering']['replacement'] = '****';
$conf['spam']['reporting'] = false;
$conf['notspam']['reporting'] = false;
$conf['msg']['prepend_header'] = true;
$conf['msg']['append_trailer'] = true;
$conf['compose']['allow_cc'] = true;
$conf['compose']['allow_bcc'] = true;
$conf['compose']['allow_receipts'] = true;
$conf['compose']['special_characters'] = true;
$conf['compose']['use_vfs'] = false;
$conf['compose']['link_attachments'] = false;
$conf['compose']['add_maildomain_to_unexpandable'] = false;
$conf['compose']['attach_size_limit'] = '0';
$conf['compose']['attach_count_limit'] = '0';
$conf['hooks']['vinfo'] = false;
$conf['hooks']['signature'] = false;
$conf['hooks']['trailer'] = false;
$conf['hooks']['fetchmail_filter'] = false;
$conf['hooks']['mbox_redirect'] = false;
$conf['hooks']['mbox_icon'] = false;
$conf['hooks']['spam_bounce'] = false;
$conf['maillog']['use_maillog'] = true;
$conf['tasklist']['use_tasklist'] = true;
$conf['notepad']['use_notepad'] = true;
</code></pre>
<p>Create IMP servers configuration /usr/share/horde/imp/config/servers.php (remove all others) with content below</p>
<pre><code>&lt;?php

$servers['cyrus'] = array(
    'name' =&gt; 'localserver',
    'server' =&gt; 'localhost',
    'hordeauth' =&gt; 'full',
    'protocol' =&gt; 'imap/notls',
    'port' =&gt; 143,
    'maildomain' =&gt; '',
    'smtphost' =&gt; 'localhost',
    'smtpport' =&gt; 25,
    'realm' =&gt; '',
    'preferred' =&gt; '',
    'admin' =&gt; array(
        'params' =&gt; array(
            'login' =&gt; 'cyrus',
            'password' =&gt; '',
            'userhierarchy' =&gt; 'user.',
            'protocol' =&gt; 'imap/notls',
            'hostspec' =&gt; 'localhost',
            'port' =&gt; 143
        )
    ),
    'quota' =&gt; array(
        'driver' =&gt; 'cyrus',
        'params' =&gt; array(),
    ),
    'acl' =&gt; array(
        'driver' =&gt; 'rfc2086',
    ),
);
</code></pre>
<p>Prevent compose window from being a popup, edit /usr/share/horde/imp/config/prefs.php and change the variable $_prefs['compose_window'] to look like below</p>
<pre><code>$_prefs['compose_popup'] = array(
    'value' =&gt; 0,
    'locked' =&gt; true,
    'shared' =&gt; true,
    'type' =&gt; 'checkbox',
    'desc' =&gt; _("Compose messages in a separate window?"));
</code></pre>
<h4>Kronolith configuration</h4>
<p>Create kronolith base configuration /usr/share/horde/kronolith/config/conf.php</p>
<pre><code>&lt;?php
$conf['calendar']['params']['table'] = 'kronolith_events';
$conf['calendar']['params']['driverconfig'] = 'horde';
$conf['calendar']['driver'] = 'sql';
$conf['storage']['params']['table'] = 'kronolith_storage';
$conf['storage']['params']['driverconfig'] = 'horde';
$conf['storage']['driver'] = 'sql';
$conf['metadata']['keywords'] = false;
$conf['reminder']['server_name'] = 'home.topdog-software.com';
$conf['reminder']['from_addr'] = 'postmaster@home.topdog-software.com';
$conf['autoshare']['shareperms'] = 'none';
$conf['menu']['print'] = true;
$conf['menu']['import_export'] = true;
$conf['menu']['apps'] = array('imp', 'ingo', 'kronolith', 'turba');
</code></pre>
<h4>Turba configuration</h4>
<p>Configure the turba base configuration /usr/share/horde/turba/config/conf.php</p>
<pre><code>&lt;?php
$conf['menu']['import_export'] = true;
$conf['menu']['apps'] = array('imp', 'ingo', 'kronolith', 'turba');
$conf['client']['addressbook'] = 'localsql';
$conf['comments']['allow'] = true;
$conf['documents']['type'] = 'horde';
</code></pre>
<h4>Ingo configuration</h4>
<p>Configure the ingo base configuration /usr/share/horde/ingo/config/conf.php</p>
<pre><code>&lt;?php
$conf['menu']['apps'] = array('imp', 'kronolith', 'turba');
$conf['storage']['driver'] = 'prefs';
$conf['storage']['maxblacklist'] = 0;
$conf['storage']['maxwhitelist'] = 0;
$conf['rules']['userheader'] = true;
$conf['rules']['usefolderapi'] = true
</code></pre>
<p>Configure the ingo backend to use timsieved in /usr/share/horde/ingo/config/backends.php (remove all other backends)</p>
<pre><code>&lt;?php
$backends['sieve'] = array(
    'driver' =&gt; 'timsieved',
    'preferred' =&gt; 'localhost',
    'hordeauth' =&gt; 'full',
    'params' =&gt; array(
        'hostspec' =&gt; 'localhost',
        'logintype' =&gt; 'PLAIN',
        'usetls' =&gt; true,
        'port' =&gt; 2000,
        'scriptname' =&gt; 'ingo',
    ),
    'script' =&gt; 'sieve',
    'scriptparams' =&gt; array()
);
</code></pre>
<h4>Passwd configuration</h4>
<p>Configure the passwd base configuration /usr/share/horde/passwd/config/conf.php</p>
<pre><code>&lt;?php
$conf['menu']['apps'] = array('imp', 'ingo', 'kronolith', 'turba');
$conf['backend']['backend_list'] = 'hidden';
$conf['user']['change'] = true;
$conf['user']['refused'] = array('root', 'bin', 'daemon', 'adm', 'lp', 'shutdown',
'halt', 'uucp', 'ftp', 'anonymous', 'nobody', 'httpd', 'operator',
'guest', 'diginext', 'bind', 'cyrus', 'courier', 'games', 'kmem',
'mailnull', 'man', 'mysql', 'news', 'postfix', 'sshd', 'tty', 'www');
$conf['password']['strengthtests'] = false;
$conf['hooks']['full_name'] = true;
$conf['hooks']['default_username'] = false;
$conf['hooks']['username'] = false;
$conf['hooks']['userdn'] = false;
</code></pre>
<p>Configure the passwd back end to use the horde mysql database in /usr/share/horde/passwd/config/backends.php (remove all others)</p>
<pre><code>&lt;?php
$backends['hordesql'] = array (
    'name' =&gt; 'Horde Authentication',
    'preferred' =&gt; '',
    'password policy' =&gt; array(
        'minLength' =&gt; 5,
        'maxLength' =&gt; 8,
        'maxSpace' =&gt; 0,
        'minUpper' =&gt; 1,
        'minLower' =&gt; 1,
        'minNumeric' =&gt; 1,
        'minSymbols' =&gt; 1
    ),
    'driver' =&gt; 'sql',
    'params' =&gt; array_merge($conf['sql'],
                            array('table' =&gt; 'horde_users',
                                  'user_col' =&gt; 'user_uid',
                                  'pass_col' =&gt; 'user_pass',
                                  'show_encryption' =&gt; false)),
);
</code></pre>
<h4>Secure Horde installation</h4>
<p>Secure the horde installation</p>
<pre><code> chown apache:root -R /usr/share/horde/config
 chown apache:root -R /usr/share/horde/*/config
 chmod -R go-rwx /usr/share/horde/config
 chmod -R go-rwx /usr/share/horde/*/config
 chown -R root:root /usr/share/horde/scripts
 chown -R root:root /usr/share/horde/*/scripts
 chmod -R go-rwx /usr/share/horde/scripts
 chmod -R go-rwx /usr/share/horde/*/scripts
 chmod a-rwx /usr/share/horde/test.php
 chmod a-rwx /usr/share/horde/*/test.php
 find /usr/share/horde/ -iname readme -exec rm -f {} \;
 find /usr/share/horde/ -iname todo -exec rm -vf {} \;
 find /usr/share/horde/ -iname license -exec rm -vf {} \;
 find /usr/share/horde/ -iname copying -exec rm -vf {} \;
 find /usr/share/horde/ -iname docs -exec rm -vrf {} \;
</code></pre>
<h3>Configure Cyrus-imapd</h3>
<p>The cyrus-imapd system will have virtual hosting enabled, sieve scripts,
quota's set to 10MB, auto creation (&amp; auto subscription) of the mailbox with
these folders (INBOX,sent-mail,drafts,spam,trash). Authentication of users
will take place aganist the Mysql database via SASL using the saslauthd
daemon.</p>
<p>Create the configuration /etc/imapd.conf with the following content</p>
<pre><code>configdirectory: /var/lib/imap
servername: TDS-IMAP/POP3
partition-default: /var/spool/imap
virtdomains: on
defaultdomain: localhost.localdomain
admins: andrew@home.topdog-software.com
postmaster: support@home.topdog-software.com
quotawarn: 85
lmtp_over_quota_perm_failure: 1
lmtp_strict_quota: 1
autocreatequota: 10240
createonpost: 1
autocreateinboxfolders: sent-mail|drafts|spam|trash
autosubscribeinboxfolders: sent-mail|drafts|spam|trash
autocreate_sieve_script: /etc/default_sieve
autocreate_sieve_compiledscript: /etc/default_sieve_script.bc
sievedir: /var/lib/imap/sieve
md5_dir: /var/lib/imap/md5
#sievenotifier: sms
#sendsms: /usr/bin/mysmsprog
sendmail: /usr/sbin/sendmail
hashimapspool: true
sasl_pwcheck_method: saslauthd
sasl_mech_list: PLAIN
allowplainwithouttls: 0
tls_cert_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
tls_key_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
tls_ca_file: /etc/pki/tls/certs/ca-bundle.crt
loglevel: info
</code></pre>
<p>Create the configuration /etc/cyrus.conf with the following content</p>
<pre><code>START {
  # do not delete this entry!
  recover       cmd="ctl_cyrusdb -r"

  # this is only necessary if using idled for IMAP IDLE
  idled         cmd="idled"
  # replication
  # syncclient       cmd="/usr/lib/cyrus-imapd/sync_client -r"
}

# UNIX sockets start with a slash and are put into /var/lib/imap/sockets
SERVICES {
  # add or remove based on preferences
  imap          cmd="imapd" listen="imap" prefork=1 proto=tcp maxchild=100 maxfds=1000 provide_uuid=1
#  imaps                cmd="imapd -s" listen="imaps" prefork=1
  pop3          cmd="pop3d" listen="pop3" prefork=1 proto=tcp maxchild=100 maxfds=1000 provide_uuid=1
#  pop3s                cmd="pop3d -s" listen="pop3s" prefork=1
  sieve         cmd="timsieved" listen="localhost:sieve" prefork=0 proto=tcp maxfds=1000 provide_uuid=1

  # these are only necessary if receiving/exporting usenet via NNTP
#  nntp         cmd="nntpd" listen="nntp" prefork=3
#  nntps                cmd="nntpd -s" listen="nntps" prefork=1

  #fud
  # fud           cmd="fud" listen="fud" prefork=1 proto="udp"
  # at least one LMTP is required for delivery
#  lmtp         cmd="lmtpd" listen="lmtp" prefork=0
  lmtpunix      cmd="lmtpd" listen="/var/lib/imap/socket/lmtp" prefork=1 maxfds=1000 provide_uuid=1

  # this is only necessary if using notifications
  notify        cmd="notifyd" listen="/var/lib/imap/socket/notify" proto="udp" prefork=1
  # replication
}

EVENTS {
  # this is required
  checkpoint    cmd="ctl_cyrusdb -c" period=30 maxfds=1000

  # this is only necessary if using duplicate delivery suppression,
  # Sieve or NNTP
  delprune      cmd="cyr_expire -E 3" at=0400

  # this is only necessary if caching TLS sessions
  #tlsprune     cmd="tls_prune" at=0400
  squat         cmd="squatter"  period=30
}
</code></pre>
<h3>Configure Pam_mysql</h3>
<p>Pam_mysql will be used to authenticate the following cyrus-imapd services
aganist the mysql database, IMAP,POP,SIEVE,LMTP,CSYNC.</p>
<h4>Pam_mysql configuration</h4>
<p>Enable pam_mysql for the services make the changes below.</p>
<p>/etc/pam.d/imap</p>
<pre><code>auth       optional     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
account    required     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
</code></pre>
<p>/etc/pam.d/pop</p>
<pre><code>auth       optional     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
account    required     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
</code></pre>
<p>/etc/pam.d/sieve</p>
<pre><code>auth       optional     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
account    required     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
</code></pre>
<p>/etc/pam.d/lmtp</p>
<pre><code>auth       optional     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
account    required     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
</code></pre>
<p>/etc/pam.d/csync</p>
<pre><code>auth       optional     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
account    required     pam_mysql.so user=horde passwd=hordepassword \
host=/var/lib/mysql/mysql.sock db=horde table=horde_users usercolumn=user_uid passwdcolumn=user_pass crypt=3
</code></pre>
<h4>Saslauthd configuration</h4>
<p>Edit /etc/sysconfig/saslauthd and modify to below</p>
<pre><code>SOCKETDIR=/var/run/saslauthd

# Mechanism to use when checking passwords.  Run "saslauthd -v" to get a list
# of which mechanism your installation was compiled to use.
MECH=pam

# Additional flags to pass to saslauthd on the command line.  See saslauthd(8)
# for the list of accepted flags.
FLAGS="-r -n 0 -c"
</code></pre>
<h3>Configure ClamAV</h3>
<p>Add the clamav user to the exim group.</p>
<pre><code>usermod -G exim clamav
</code></pre>
<p>Change the location of the socket and disable TCP. Make changes to /etc/clamd.conf</p>
<pre><code>LocalSocket /var/run/clamav/clamd.socket
#TCPSocket 3310
#TCPAddr 127.0.0.1
</code></pre>
<p>Install sane security signatures</p>
<pre><code>wget http://www.sanesecurity.co.uk/clamav/update_sanesecurity.txt -O /usr/local/bin/update_sanesecurity.sh
chmod +x /usr/local/bin/update_sanesecurity.sh
ln -s /usr/local/bin/update_sanesecurity.sh /etc/cron.hourly/
/usr/local/bin/update_sanesecurity.sh
</code></pre>
<p>Enable local selinux module for clamav, create file clamdlocal.te and add the following</p>
<pre><code>module clamdlocal 1.0;

require {
        type proc_t;
        type var_t;
        type sysctl_kernel_t;
        type var_spool_t;
        type clamd_t;
        class dir { write search read remove_name add_name };
        class file { write getattr read lock create unlink };
}

#============= clamd_t ==============
allow clamd_t proc_t:file { read getattr };
allow clamd_t sysctl_kernel_t:dir search;
allow clamd_t sysctl_kernel_t:file read;
allow clamd_t var_spool_t:dir read;
allow clamd_t var_spool_t:file { read getattr };
allow clamd_t var_t:dir { write read add_name remove_name };
allow clamd_t var_t:file { write getattr read lock create unlink };
</code></pre>
<p>Compile and load the module</p>
<pre><code>checkmodule -M -m -o clamdlocal.mod clamdlocal.te
semodule_package -o clamdlocal.pp -m clamdlocal.mod
semodule -i clamdlocal.pp
</code></pre>
<h3>Configure Spamassassin</h3>
<p>Modify the startup options edit /etc/sysconfig/spamassassin and modify as below</p>
<pre><code>SPAMDOPTIONS=" -l -d -c -m5 -H -m 10 --socketpath=/var/run/spamassassin/spamd.sock --socketowner=exim"
</code></pre>
<p>Enable local spamd module for spamassassin, create file spamdlocal.te and add the following</p>
<pre><code>module spamdlocal 1.0;

require {
        type spamd_t;
        type spamd_var_run_t;
        class capability { fowner chown kill };
        class sock_file { write create unlink getattr setattr };
}

#============= spamd_t ==============
allow spamd_t self:capability { fowner chown kill };
allow spamd_t spamd_var_run_t:sock_file { write create unlink getattr setattr };
</code></pre>
<p>Compile and install the module</p>
<pre><code>checkmodule -M -m -o spamdlocal.mod spamdlocal.te
semodule_package -o spamdlocal.pp -m spamdlocal.mod
semodule -i spamdlocal.pp
</code></pre>
<h2>Final touches</h2>
<h3>Disable services</h3>
<p>Disable unwanted services, use this <a href="http://www.topdog-
software.com/files/disable_service.sh.gz">script</a></p>
<h3>Enable services</h3>
<pre><code>chkconfig --level 234 exim on
chkconfig --level 234 mysqld on
chkconfig --level 234 spamassassin on
chkconfig --level 234 clamd on
chkconfig --level 234 httpd on
chkconfig --level 234 saslauthd on
chkconfig --level 234 cyrus-imapd on

service mysqld restart
service saslauthd restart
service spamassassin restart
service clamd restart
service exim restart
service cyrus-imapd restart
service httpd restart
</code></pre>
<h3>Create admin user</h3>
<p>Create a file admin.sql and add the following (modify the password to suite you)</p>
<pre><code>USE horde;

REPLACE INTO horde_users (user_uid,user_pass)
    VALUES (
        'andrew@home.topdog-software.com',
-- Change this
        md5('verystrongpassword'),
);
</code></pre>
<p>Add user to database</p>
<pre><code>mysql -p horde &lt; admin.sql
</code></pre>
<h3>Firewall</h3>
<p>Add these rules in your configuration file /etc/sysconfig/iptables</p>
<pre><code>*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m multiport -j ACCEPT --dports 80,443,25,110,143
-A INPUT -p icmp -m icmp -m limit --icmp-type 8 --limit 5/min -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -s 192.168.1.4 -j ACCEPT
COMMIT
</code></pre>
<h3>Login</h3>
<p>Phew ! you are done. Open your browser and go to
<a href="https://192.168.1.4/">https://192.168.1.4/</a> and login with the details above,
you can the create other users under administration → users. You can test all
the other features as well.</p>
<h2>References</h2>
<ul>
<li><a href="http://www.horde.org">http://www.horde.org</a></li>
<li><a href="http://wiki.horde.org/CentOS5InstallationNotes">http://wiki.horde.org/CentOS5InstallationNotes</a></li>
<li><a href="http://sanesecurity.co.uk/clamav/">http://sanesecurity.co.uk/clamav/</a></li>
<li><a href="http://www.exim.org/">http://www.exim.org/</a></li>
<li><a href="http://cyrusimap.web.cmu.edu/imapd/install.html">http://cyrusimap.web.cmu.edu/imapd/install.html</a></li>
<li><a href="http://pam-mysql.sourceforge.net/">http://pam-mysql.sourceforge.net/</a></li>
<li><a href="http://dev.mysql.com/">http://dev.mysql.com/</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>CENTOS 5 virtual hosting howto</title>
      <link>http://www.topdog.za.net/2008/02/03/centos-5-virtual-hosting-howto</link>
      <pubDate>Sun, 03 Feb 2008 18:58:00 SAST</pubDate>
      <category><![CDATA[Horde]]></category>
      <category><![CDATA[Centos]]></category>
      <category><![CDATA[Howto]]></category>
      <category><![CDATA[Exim]]></category>
      <category><![CDATA[Cyrus]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Email]]></category>
      <guid isPermaLink="true">http://www.topdog.za.net/2008/02/03/centos-5-virtual-hosting-howto</guid>
      <description>CENTOS 5 virtual hosting howto</description>
      <content:encoded><![CDATA[<h2>Introduction</h2>
<p>This tutorial shows how to set up a CentOS 5.x server to offer all services
needed by virtual web hosters. These include web hosting,smtp server with
(SMTP-AUTH and
TLS,SPF,DKIM,Domainkeys),DNS,FTP,MySQL,POP3/IMAP,Firewall,Webalizer for stats.</p>
<p>I will use the following software:</p>
<ul>
<li>Database Server: MySQL 5.0.22</li>
<li>Mail Server: Postfix 2.3.3</li>
<li>DNS Server: BIND9 9.3.3</li>
<li>Web Server: Apache 2.2.3 / PHP 5.1.6</li>
<li>FTP Server: Vsftpd 2.0.5</li>
<li>POP3/IMAP server: Dovecot 1.0</li>
<li>Webalizer: for site statistics 2.01_10</li>
<li>Virtualmin: Control panel</li>
</ul>
<h2>OS installation</h2>
<h3>Requirements</h3>
<p>To install the system you will need</p>
<ul>
<li>Centos 5.1 Install media</li>
<li>A good internet connection</li>
</ul>
<h3>Install the Base system</h3>
<ul>
<li>Boot from the DVD or CD media and at the boot prompt type linux text</li>
<li>Skip the media test</li>
<li>Select your language</li>
<li>Select keyboard layout</li>
<li>Configure your network, i will be using dhcp if you do not have dhcp you can use static entires</li>
<li>Select Yes to initialize drive</li>
<li>Select custom layout for partitioning type</li>
<li>Create partitions</li>
<li>Configure networking</li>
<li>Set the timezone</li>
<li>Set the root password</li>
<li>Select server group and select customize software selection</li>
<li>
<p>Package groups select as follows: </p>
<ul>
<li>DNS name server</li>
<li>bind-chroot</li>
</ul>
</li>
<li>
<p>Editors</p>
<ul>
<li>vim-enhanced</li>
</ul>
</li>
<li>FTP server</li>
<li>
<p>Mail server</p>
<ul>
<li>dovecot</li>
<li>spamassassin</li>
<li>postfix</li>
</ul>
</li>
<li>
<p>Mysql Database</p>
<ul>
<li>mysql-server</li>
</ul>
</li>
<li>
<p>Web server</p>
<ul>
<li>mod_ssl</li>
<li>webalizer</li>
<li>php</li>
<li>php-pear</li>
<li>http-suexec</li>
<li>php-mysql</li>
</ul>
</li>
</ul>
<h3>Services to disable</h3>
<p>To enhance security and free system resources on the system we need to disable
any services that are not required. You can run <a href="http://www
.topdog-software.com/files/disable_service.sh.gz">this script</a> to do this for you.</p>
<ul>
<li>acpid</li>
<li>anacron</li>
<li>apmd</li>
<li>autofs</li>
<li>bluetooth</li>
<li>cups</li>
<li>firstboot</li>
<li>gpm</li>
<li>haldaemon</li>
<li>messagebus</li>
<li>mdmonitor</li>
<li>hidd</li>
<li>ip6tables</li>
<li>kudzu</li>
<li>lvm2-monitor</li>
<li>netfs</li>
<li>nfslock</li>
<li>pcscd</li>
<li>portmap</li>
<li>rpcgssd</li>
<li>rpcidmad</li>
<li>sendmail</li>
<li>smartd</li>
<li>yum-updatesd</li>
</ul>
<h3>Basics</h3>
<p>We need to fix a few issues to prepare the system for configuration</p>
<p>Install updates</p>
<pre><code> # yum upgrade
</code></pre>
<p>Switch the mta to postfix</p>
<pre><code> # alternatives --config mta
 There are 2 programs which provide 'mta'.
   Selection    Command
 -----------------------------------------------
    1           /usr/sbin/sendmail.postfix
 *+ 2           /usr/sbin/sendmail.sendmail
 Enter to keep the current selection[+], or type selection number: 1
</code></pre>
<p>Install caching-nameserver config</p>
<pre><code> # yum install caching-nameserver
</code></pre>
<p>Install Build tools</p>
<pre><code> # yum install gcc cpp gcc-c++ automake automake14 automake15 automake16 automake17 openssl-devel subversion ncurses-devel -y
</code></pre>
<h3>Configure network alias</h3>
<pre><code> # cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0:1
</code></pre>
<p>Modify the file /etc/sysconfig/network-scripts/ifcfg-eth0:1 to look like this</p>
<pre><code>DEVICE=eth0:1
BOOTPROTO=static
BROADCAST=192.168.1.255
IPADDR=192.168.1.6
NETMASK=255.255.255.0
NETWORK=192.168.1.0
ONBOOT=yes
</code></pre>
<h3>Install webmin / virtualmin</h3>
<p>Import webmin pgp key</p>
<pre><code> # wget http://www.webmin.com/jcameron-key.asc
 # rpm --import jcameron-key.asc
</code></pre>
<p>Download the rpm</p>
<pre><code> # wget http://prdownloads.sourceforge.net/webadmin/webmin-1.390-1.noarch.rpm
</code></pre>
<p>Verify the rpm (should say OK or else download again)</p>
<pre><code> # rpm --checksig webmin-1.390-1.noarch.rpm
</code></pre>
<p>Install the rpm</p>
<pre><code> # rpm -Uvh webmin-1.390-1.noarch.rpm
</code></pre>
<h3>Initial webmin config</h3>
<p>We need to secure webmin by editing /etc/webmin/miniserv.conf and make the
following changes</p>
<p>Using SSL only</p>
<pre><code>ssl=1
</code></pre>
<p>Change the port to 443 and bind to the second nic only</p>
<pre><code>port=443
bind=192.168.1.6
</code></pre>
<p>Disable UDP broadcasts</p>
<pre><code>#listen=10000
</code></pre>
<p>Change host lockout on login failures to 3</p>
<pre><code>blockhost_failures=3
</code></pre>
<p>Increase host lockout timeout to 120</p>
<pre><code>blockhost_time=120
</code></pre>
<p>Change user lockout on login failures to 3</p>
<pre><code>blockuser_failures=3
</code></pre>
<p>Change user lockout timeout to 120</p>
<pre><code>blockuser_time=120
</code></pre>
<p>Change the realm to something else</p>
<pre><code>realm=cpanel
</code></pre>
<p>Log logins to utmp</p>
<pre><code>utmp=1
</code></pre>
<p>Install the <a href="http://www.stress-free.co.nz/webmin-theme/">webmin Tiger theme</a></p>
<ul>
<li>Login to webmin via <a href="https://192.168.1.5:10000">https://192.168.1.5:10000</a> using root and your password</li>
<li>Go to webmin → Configuration → webmin themes</li>
<li>Select From ftp or http URL and enter <a href="http://www.stress-free.co.nz/files/theme-stressfree.tar.gz">http://www.stress-free.co.nz/files/theme-stressfree.tar.gz</a></li>
<li>Click install theme</li>
<li>Click “return to list themes”</li>
<li>Select StressFree as the Current theme then click change</li>
</ul>
<p>Install php-pear module</p>
<ul>
<li>Go to webmin → webmin configuration → webmin modules</li>
<li>Select Third party module from and enter <a href="http://www.webmin.com/download/modules/php-pear.wbm.gz">http://www.webmin.com/download/modules/php-pear.wbm.gz</a></li>
<li>Click install module</li>
</ul>
<p>Install virtualmin</p>
<ul>
<li>Go to webmin → webmin configuration → webmin modules</li>
<li>Select install from ftp or http URL and enter <a href="http://download.webmin.com/download/virtualmin/virtual-server-3.51.gpl.wbm.gz">http://download.webmin.com/download/virtualmin/virtual-server-3.51.gpl.wbm.gz</a></li>
<li>Click install module</li>
</ul>
<p>Remove unwanted modules Go to webmin → webmin configuration → delete and
select the following</p>
<ul>
<li>ADSL client</li>
<li>Bacula backup system</li>
<li>CD Burner</li>
<li>CVS Server</li>
<li>Cluster change passwords</li>
<li>Cluster copy files</li>
<li>Cluster cron jobs</li>
<li>Cluster shell commands</li>
<li>Cluster software packages</li>
<li>Cluster usermin servers</li>
<li>Cluster users and groups</li>
<li>Cluster webmin servers</li>
<li>Command shell</li>
<li>Configuration engine</li>
<li>Custom commands</li>
<li>DHCP server</li>
<li>Fetchmail mail retrieval</li>
<li>File manager</li>
<li>Frox ftp proxy</li>
<li>HTTP Tunnel</li>
<li>Heartbeat monitor</li>
<li>IPsec VPN</li>
<li>Jabber IM server</li>
<li>LDAP server</li>
<li>Logical volume management</li>
<li>Majordomo list manager</li>
<li>NFS exports</li>
<li>NIS client and server</li>
<li>OpenSLP server</li>
<li>PPP dialin server</li>
<li>PPP dialup client</li>
<li>PPTP vpn server</li>
<li>PPTP vpn client</li>
<li>Postgresql database server</li>
<li>Printer admin</li>
<li>ProFTPD server</li>
<li>QMAIL mail server</li>
<li>SMART drive status</li>
<li>SSH / Telnet login</li>
<li>SSL tunnels</li>
<li>SAMBA windows file sharing</li>
<li>Scheduled commands</li>
<li>Sendmail mail server</li>
<li>Shoreline firewall</li>
<li>Squid analysis report generator</li>
<li>Squid proxy server</li>
<li>Voicemail server</li>
<li>WU-FTP server</li>
<li>Idmapd server</li>
</ul>
<p>Restart webmin</p>
<pre><code> # service webmin restart
</code></pre>
<h3>Configure rpmforge repo</h3>
<pre><code> # rpm -Uhv http://packages.sw.be/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
</code></pre>
<p><strong>NOTE: If you are using a different architecture check on <a href="https://rpmrepo.org/RPMforge/Using">https://rpmrepo.org/RPMforge/Using</a> for the correct rpm</strong></p>
<p>Disable the repo (such that base packages not overwritten) edit /etc/yum.d/rpmforge.repo and set the following option</p>
<pre><code>enabled = 0
</code></pre>
<h3>Install extra required packages</h3>
<p>Install clamav</p>
<pre><code> # yum --enablerepo=rpmforge install clamav clamav-db clamav-milter clamd -y
 # wget http://www.topdog-software.com/files/clamav-milter.patch
 # patch /etc/init.d/clamav-milter &lt; clamav-milter.patch
 # chkconfig --del clamd
 # freshclam
</code></pre>
<p>Install sanesecurity signatures</p>
<pre><code> # wget http://www.sanesecurity.co.uk/clamav/update_sanesecurity.txt -O /usr/local/bin/update_sanesecurity.sh
 # chmod +x /usr/local/bin/update_sanesecurity.sh
 # ln -s /usr/local/bin/update_sanesecurity.sh /etc/cron.hourly/
 # /usr/local/bin/update_sanesecurity.sh
</code></pre>
<p>Install PHP eaccelerator</p>
<pre><code> # yum --enablerepo=rpmforge install php-eaccelerator
</code></pre>
<p>Install newer spamassassin package from rpmforge</p>
<pre><code> # yum --enablerepo=rpmforge upgrade spamassassin
</code></pre>
<p>Install spamass-milter</p>
<pre><code> # yum --enablerepo=rpmforge install spamass-milter
</code></pre>
<p>Install perl modules1) required by spamassassin</p>
<pre><code> # perl -MCPAN -e 'install Mail::SPF'
 # perl -MCPAN -e 'install Mail::SPF::Query' 
 # perl -MCPAN -e 'install Net::Ident'
 # perl -MCPAN -e 'install IP::Country::Fast'
 # perl -MCPAN -e 'install Mail::DomainKeys'
 # perl -MCPAN -e 'install Mail::DKIM'
</code></pre>
<p>Install fuzzyOCR</p>
<pre><code> # yum --enablerepo=rpmforge install netpbm-progs ocrad gocr gifsicle giflib-utils giflib -y
 # svn co https://svn.own-hero.net/fuzzyocr/trunk/devel/
 # cd devel/
 # perl -MCPAN -e 'install String::Approx'
 # perl -MCPAN -e 'install Time::HiRes'
 # perl -MCPAN -e 'install Log::Agent'
 # cp -rv {FuzzyOcr.cf,FuzzyOcr.scansets,FuzzyOcr.preps,FuzzyOcr.pm,FuzzyOcr.words,FuzzyOcr/} /etc/mail/spamassassin
 # chcon -R system_u:object_r:etc_mail_t /etc/mail/spamassassin/{FuzzyOcr.cf,FuzzyOcr.scansets,FuzzyOcr.preps,FuzzyOcr.pm,FuzzyOcr.words,FuzzyOcr/}
 # wget http://www.gbnetwork.co.uk/mailscanner/FuzzyOcr.words -O /etc/mail/spamassassin/FuzzyOcr.words
</code></pre>
<p>Install Razor</p>
<pre><code> # yum --enablerepo=rpmforge install razor-agents -y
</code></pre>
<p>Install roundcube</p>
<pre><code> # yum install php-imap
 # rpm -Uvh http://www.topdog-software.com/oss/roundcube/roundcube-0.1-rc2.noarch.rpm
</code></pre>
<p>Install imapproxy</p>
<pre><code> # wget http://imapproxy.org/downloads/up-imapproxy-1.2.6.tar.gz
 # rpmbuild -tb up-imapproxy-1.2.6.tar.gz
 # rpm -Uvh /usr/src/redhat/RPMS/i386/up-imapproxy-1.2.6-1.i386.rpm
</code></pre>
<p>Activate services</p>
<pre><code> # chkconfig --level 345 httpd on
 # chkconfig --level 345 postfix on
 # chkconfig --level 345 spamassassin on
 # chkconfig --level 345 spamass-milter on
 # chkconfig --level 345 clamav-milter on
 # chkconfig --level 345 mysqld on
 # chkconfig --level 345 named on
 # chkconfig --level 345 vsftpd on
 # chkconfig --level 345 dovecot on
 # chkconfig --level 345 imapproxy on
</code></pre>
<h2>Configuration</h2>
<h3>Postfix</h3>
<p>We will be setting up postfix with the following features</p>
<ul>
<li>Virtual hosting</li>
<li>UCE prevention</li>
<li>Anti virus</li>
<li>SMTP authentication</li>
<li>TLS</li>
<li>RBLs</li>
<li>SPF</li>
<li>Attack mitigation</li>
</ul>
<p>The adding of accounts and domains with be configured through virtualmin
although it can be done manually as well. The setup is designed to be resource
friendly so should be able to run on machines that are not over spec'ed so
enabling the resources to be put to better use. To make it resource friendly
we are not using external databases to store virtual user information like
most other how-to's do as well as using milters for spam and virus checking as
opposed to running amavisd-new.</p>
<h4>The basics</h4>
<p>To begin with we will configure the basics such as the hostname, mail origin,
networks, hash maps spool directory. All these configuration options should be
added to /etc/postfix/main.cf unless stated. Sample configuration files are
available for download at the end of this page.</p>
<pre><code>command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mydomain = example.com
myorigin = $mydomain
mynetworks = 127.0.0.0/8
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
canonical_maps = hash:/etc/postfix/canonical
sender_canonical_maps = hash:/etc/postfix/canonical
recipient_canonical_maps = hash:/etc/postfix/canonical
virtual_alias_maps = hash:/etc/postfix/virtual
mail_spool_directory = /var/spool/mail
</code></pre>
<h4>Maildir</h4>
<p>We will use the much improved maildir format as opposed to the default mbox
format</p>
<pre><code>home_mailbox = Maildir/
</code></pre>
<h4>SASL</h4>
<p>To perform SMTP authentication we will be using SASL, however we will not use
the Cyrus SASL as that requires us to run the saslauthd daemon, we will
instead use dovecot sasl since we will be running dovecot for IMAP and POP3
thus killing 2 birds with one stone.</p>
<pre><code>smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
</code></pre>
<h4>TLS</h4>
<p>We need TLS to ensure that the plain text passwords are not transmitted over
the wire during SMTP authentication, servers that support TLS are also able to
communicate with this server over a secured connection.</p>
<p>Instructions on creating your server certificate signed by cacert.org are can
be found <a href="/create_cacert_postfix_certificate">here</a></p>
<p>Set TLS random source</p>
<pre><code>tls_random_source = dev:/dev/urandom
</code></pre>
<p>Enable server TLS</p>
<pre><code>smtpd_use_tls = yes
smtpd_tls_key_file = /etc/pki/postfix/key.pem
smtpd_tls_cert_file = /etc/pki/postfix/server.pem
smtpd_tls_CAfile = /etc/pki/postfix/root.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_session_cache_database = btree:/var/spool/postfix/smtpd_tls_cache
</code></pre>
<p>Enable client TLS</p>
<pre><code>smtp_use_tls = yes
smtp_tls_session_cache_database = btree:/var/spool/postfix/smtp_tls_cache
smtp_tls_note_starttls_offer = yes
</code></pre>
<h4>Spam prevention</h4>
<p>Require a valid EHLO / HELO</p>
<pre><code>smtpd_helo_required = yes
</code></pre>
<p>Prevent email address harvesting attacks</p>
<pre><code>disable_vrfy_command = yes
</code></pre>
<p>Change reject codes to permanent (By default postfix issues 4xx error codes which implies temporary failure we need 5xx for permanent errors)</p>
<pre><code>unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550
unknown_local_recipient_reject_code = 550
</code></pre>
<p>Setup sender address verification</p>
<pre><code>address_verify_map = btree:/var/spool/postfix/verify
smtpd_sender_restrictions = hash:/etc/postfix/sender_access
</code></pre>
<p>Create /etc/postfix/sender_access and add</p>
<pre><code>#sample /etc/postfix/sender_access contains frequently spoofed domains
aol.com     reject_unverified_sender
hotmail.com reject_unverified_sender
yahoo.com reject_unverified_sender
gmail.com reject_unverified_sender
bigfoot.com reject_unverified_sender
</code></pre>
<p>Mitigate attacks from zombies and broken clients</p>
<pre><code>smtpd_error_sleep_time = 5s
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 20
</code></pre>
<p>Only allow pipelining from authenticated clients</p>
<pre><code>smtpd_data_restrictions = reject_unauth_pipelining
</code></pre>
<p>Install postfix-policyd-spf-perl and enable SPF support</p>
<pre><code> # wget http://www.openspf.org/blobs/postfix-policyd-spf-perl-2.005.tar.gz
 # tar xzvf postfix-policyd-spf-perl-2.005.tar.gz
 # cd postfix-policyd-spf-perl-2.005
 # cp postfix-policyd-spf-perl /etc/postfix/
</code></pre>
<p>Add this to /etc/postfix/master.cf</p>
<pre><code>spfpolicy unix  -       n       n       -       -       spawn user=nobody argv=/usr/bin/perl /etc/postfix/postfix-policyd-spf-perl
</code></pre>
<p>Add DKIM support</p>
<p>Instructions on adding DKIM support can be found <a href="/postfix_dkim_milter">here</a></p>
<p>Add domainkeys support</p>
<p>Instructions on adding domainkeys support can be found
  <a href="/postfix_domainkeys_milter">here</a></p>
<p>Getting it all to work depends on the smtpd_recipient_restrictions option so we set it below</p>
<pre><code>smtpd_recipient_restrictions =
        permit_mynetworks
        permit_sasl_authenticated
        reject_unauth_destination
        check_recipient_access hash:/etc/postfix/access
        reject_unknown_recipient_domain
        reject_unknown_sender_domain
        reject_unverified_recipient
        reject_non_fqdn_recipient
        reject_non_fqdn_sender
        reject_invalid_hostname
        reject_rbl_client list.dsbl.org
        reject_rbl_client zen.spamhaus.org
        reject_rbl_client l1.spews.dnsbl.sorbs.net
        reject_rbl_client combined.njabl.org
        reject_rbl_client bl.spamcop.net
        reject_rhsbl_sender dsn.rfc-ignorant.org
        reject_rhsbl_sender bogusmx.rfc-ignorant.org
        reject_rhsbl_sender rhsbl.sorbs.net
        reject_rhsbl_client dsn.rfc-ignorant.org
        reject_rhsbl_client bogusmx.rfc-ignorant.org
        reject_rhsbl_client rhsbl.sorbs.net
        check_policy_service unix:private/spfpolicy
</code></pre>
<h4>Milters [spamassassin &amp; clamav]</h4>
<p>For your spam classification using spamassassin and virus scanning using
clamav we will be using postfix's milter interface instead of using the
resource intensive amavisd-new daemon. This is a very efficient way of doing
it as we don't even have to run clamd the clamav milter does the scanning
itself.</p>
<pre><code>smtpd_milters = unix:/var/clamav/clmilter.socket unix:/var/run/spamass.sock
non_smtpd_milters = unix:/var/clamav/clmilter.socket unix:/var/run/spamass.sock
</code></pre>
<h4>Create db files</h4>
<pre><code> # postmap /etc/postfix/canonical
 # postmap /etc/postfix/access
 # postmap /etc/postfix/virtual
 # postmap /etc/postfix/sender_access
</code></pre>
<h4>Sample configuration files</h4>
<ul>
<li><a href="http://www.topdog-software.com/files/main.cf.gz">main.cf</a></li>
<li><a href="http://www.topdog-software.com/files/master.cf.gz">master.cf</a></li>
<li><a href="http://www.topdog-software.com/files/canonical.gz">canonical</a></li>
<li><a href="http://www.topdog-software.com/files/virtual.gz">virtual</a></li>
</ul>
<h3>Dovecot</h3>
<p>This will setup dovecot as our IMAP/POP3 server.</p>
<h4>Basic configuration</h4>
<p>We will setup dovecot for IMAP and POP3 and disable SSL.</p>
<pre><code>protocols = imap pop3
listen = *
ssl_listen = *
ssl_disable = yes
</code></pre>
<h4>Maildir</h4>
<p>We will use the maildir format as opposed to the default mbox format.</p>
<pre><code>mail_location = maildir:~/Maildir
</code></pre>
<h4>Authentication &amp; SASL</h4>
<p>Configure dovecot to use LOGIN and PLAIN as the authentication mechanisims as
many MS clients are unable to use encrypted authentication mechanisms. We also
setup the SASL socket to enable postfix to authenticate SMTP connections using
dovecot.</p>
<pre><code>auth default {
  mechanisms = plain login
  passdb pam {
  }
  userdb passwd {
  }

  socket listen {
    client {
        path = /var/spool/postfix/private/auth
        mode = 0660
        user = postfix
        group = postfix
    }
  }
}
</code></pre>
<h4>Client Issues</h4>
<p>Some MS imap clients in the outlook family have issues with both thier IMAP
and POP3 implementations so we need to accommodate them by setting up these
work arounds</p>
<pre><code>protocol imap {
 imap_client_workarounds = outlook-idle delay-newmail
}

protocol pop3 {
 pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
</code></pre>
<h4>Run IMAP behind proxy</h4>
<p>The imap server is configured to run on port 10143 such that port 143 is
handled by the imap proxy server that will improve performance for your
webmail by caching connections to the imap server. The listen option under
protocol sets this up.</p>
<pre><code>protocol imap {
 imap_client_workarounds = outlook-idle delay-newmail
 listen = 127.0.0.1:10143
}
</code></pre>
<h4>Sample files</h4>
<ul>
<li><a href="http://www.topdog-software.com/files/dovecot.conf.gz">dovecot.conf</a></li>
</ul>
<h3>Imapproxy</h3>
<p><em>imapproxy was written to compensate for webmail clients that are unable to
maintain persistent connections to an IMAP server. Most webmail clients need
to log in to an IMAP server for nearly every single transaction. This
behaviour can cause tragic performance problems on the IMAP server. imapproxy
tries to deal with this problem by leaving server connections open for a short
time after a webmail client logs out. When the webmail client connects again,
imapproxy will determine if there's a cached connection available and reuse it
if possible.</em> - according to the imapproxy website.</p>
<h4>Configuration</h4>
<p>Make the following changes in the file /etc/imapproxy.conf</p>
<pre><code>server_hostname 127.0.0.1
cache_size 3072
listen_port 143
server_port 10143
cache_expiration_time 900
proc_username nobody
proc_groupname nobody
stat_filename /var/run/pimpstats
protocol_log_filename /var/log/imapproxy_protocol.log
syslog_facility LOG_MAIL
send_tcp_keepalives no
enable_select_cache yes
foreground_mode no
force_tls no
enable_admin_commands no
</code></pre>
<h4>Sample files</h4>
<ul>
<li><a href="http://www.topdog-software.com/files/imapproxy.conf.gz">imapproxy.conf</a></li>
</ul>
<h3>Bind</h3>
<p>Bind will be setup chrooted to improve security we will also use views to
prevent abuse of the dns server.</p>
<h4>Basic configuration</h4>
<p>The basic configuration disables by default, recursive queries and zone
transfers. We also obscure the version of BIND we are running such that we are
not hit by zero day vulnerabilities from script kiddies.</p>
<pre><code>options {
        directory "/var/named";
        pid-file "/var/run/named/named.pid";
        listen-on {
                127.0.0.1;
                192.168.1.5;
                };
        version "just guess";
        allow-recursion { "localhost"; };
        allow-transfer { "none"; };
};
</code></pre>
<h4>Logging</h4>
<p>The logging is customized to remove the annoying “lame-server” and update
errors that appear in the logs</p>
<pre><code>logging {
        category update { null; };
        category update-security { null;        };
        category lame-servers{ null; };
};
</code></pre>
<h4>Chroot</h4>
<p>Ensure that this is set in the file /etc/sysconfig/named (its usually set by
the bind-chroot package)</p>
<pre><code>ROOTDIR=/var/named/chroot
</code></pre>
<h4>Point server</h4>
<p>Let the machine use this server for dns resolution edit /etc/resolv.conf and
prepend</p>
<pre><code>nameserver 127.0.0.1
</code></pre>
<h4>Sample files</h4>
<ul>
<li><a href="http://www.topdog-software.com/files/named.conf.gz">named.conf</a></li>
<li><a href="http://www.topdog-software.com/files/named.gz">/etc/sysconfig/named</a></li>
</ul>
<h3>Vsftp</h3>
<p>We will use vsftpd as our ftp server. This has a better track record as
opposed to the proftpd &amp; wuftpd servers.</p>
<h4>Basic setting</h4>
<p>Our basic setup disables anonymous users, and enables local system users to
connect to the ftp server</p>
<pre><code>anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
anon_upload_enable=NO
anon_mkdir_write_enable=NO
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_file=/var/log/vsftpd.log
xferlog_std_format=YES
ftpd_banner=Welcome to example.com server
pam_service_name=vsftpd
tcp_wrappers=YES
</code></pre>
<h4>Chroot</h4>
<p>All users will be chrooted to their home directories (except usernames in the
/etc/vsftpd/chroot_list file) meaning the cannot break out and see other users
files.</p>
<pre><code>chroot_list_enable=YES
chroot_local_user=YES
chroot_list_file=/etc/vsftpd/chroot_list
</code></pre>
<h4>Banned users</h4>
<p>Users added to the file /etc/vsftpd/user_list will not be allowed to login</p>
<pre><code>userlist_enable=YES
</code></pre>
<h4>Sample files</h4>
<ul>
<li><a href="http://www.topdog-software.com/files/vsftpd.conf.gz">vsftpd.conf</a></li>
<li><a href="http://www.topdog-software.com/files/user_list.gz">user_list</a></li>
<li><a href="http://www.topdog-software.com/files/chroot_list.gz">chroot_list</a></li>
</ul>
<h3>Clamav milter</h3>
<p>Edit /etc/sysconfig/clamav-milter </p>
<pre><code>  CLAMAV_FLAGS="
          --config-file=/etc/clamd.conf
          --force-scan
          --local
          --max-children=5
          --sendmail-cf=
          --outgoing
          --quiet
  "
  SOCKET_ADDRESS="local:/var/clamav/clmilter.socket"
</code></pre>
<p>Patch the init file to fix socket permissions</p>
<pre><code>   # wget http://www.topdog-software.com/files/clamav-milter.patch
   # patch /etc/init.d/clamav-milter &lt; clamav-milter.patch
</code></pre>
<h3>Mysql</h3>
<h4>Basic config</h4>
<p>listen only to the localhost, edit /etc/my.cnf under the mysqld section</p>
<pre><code>bind-address = 127.0.0.1
</code></pre>
<h4>Set root password</h4>
<pre><code> # mysqladmin -u root password NEWPASSWORD
</code></pre>
<h4>Start mysql</h4>
<pre><code> # service mysqld start
</code></pre>
<h3>Spamassassin</h3>
<h4>Basic config</h4>
<pre><code>required_hits 5
report_safe 0
rewrite_header Subject [SPAM]
</code></pre>
<h4>Create mysql database</h4>
<p>Create the database</p>
<pre><code># mysqladmin -p create bayes
</code></pre>
<p>Populate the database</p>
<pre><code> # mysql -p bayes &lt; /usr/share/doc/spamassassin-$(rpm --qf %{VERSION} -q spamassassin)/sql/bayes_mysql.sql
</code></pre>
<p>Create the user</p>
<pre><code> # mysql -p
 mysql&gt; GRANT ALL ON bayes.* TO bayes@localhost IDENTIFIED BY 'password';
</code></pre>
<h4>Configure to use db</h4>
<p>Edit the file /etc/mail/spamassassin/local.cf and add</p>
<pre><code>bayes_store_module  Mail::SpamAssassin::BayesStore::MySQL
bayes_sql_dsn       DBI:mysql:bayes:localhost
bayes_sql_override_username bayes
bayes_sql_username  bayes
bayes_sql_password  password
</code></pre>
<h4>Configure FuzzyOCR</h4>
<p>We will be storing the image hashes in a mysql database to improve on
performance such that images that we have already scanned do not get scanned
again as OCR is a resource intense activity.</p>
<h4>Create mysql Database</h4>
<p>The sql script creates the database and tables and adds a user fuzzyocr with the password fuzzyocr</p>
<pre><code># mysql -p &lt; /usr/local/src/devel/FuzzyOcr.mysql
</code></pre>
<p>Change the password</p>
<pre><code> # mysqladmin -u fuzzyocr -p fuzzyocr password
</code></pre>
<h4>Basic settings</h4>
<p>Edit /etc/mail/spamassassin/FuzzyOCR.cf and set the basic options</p>
<pre><code>focr_path_bin /usr/bin:/usr/local/bin
focr_minimal_scanset 1
focr_autosort_scanset 1
focr_enable_image_hashing 3
focr_logfile /tmp/FuzzyOcr.log
</code></pre>
<h4>Make FuzzyOCR use the database</h4>
<p>Edit the file /etc/mail/spamassassin/FuzzyOcr.cf and add</p>
<pre><code>focr_mysql_db FuzzyOcr
focr_mysql_hash Hash
focr_mysql_safe Safe
focr_mysql_user fuzzyocr
focr_mysql_pass password
focr_mysql_host localhost
focr_mysql_port 3306
focr_mysql_socket /var/lib/mysql/mysql.sock
</code></pre>
<h4>SARE rule updates</h4>
<p>Import the GPG key used to sign the rules</p>
<pre><code> # mkdir /etc/mail/spamassassin/sa-update-keys/
 # chmod 700 /etc/mail/spamassassin/sa-update-keys/
 # wget http://daryl.dostech.ca/sa-update/sare/GPG.KEY
 # sa-update --import GPG.KEY
</code></pre>
<p>Create the channels file /etc/mail/spamassassin/sare-sa-update-channels.txt</p>
<pre><code>updates.spamassassin.org
72_sare_redirect_post3.0.0.cf.sare.sa-update.dostech.net
70_sare_evilnum0.cf.sare.sa-update.dostech.net
70_sare_bayes_poison_nxm.cf.sare.sa-update.dostech.net
70_sare_html0.cf.sare.sa-update.dostech.net
70_sare_html_eng.cf.sare.sa-update.dostech.net
70_sare_header0.cf.sare.sa-update.dostech.net
70_sare_header_eng.cf.sare.sa-update.dostech.net
70_sare_specific.cf.sare.sa-update.dostech.net
70_sare_adult.cf.sare.sa-update.dostech.net
72_sare_bml_post25x.cf.sare.sa-update.dostech.net
99_sare_fraud_post25x.cf.sare.sa-update.dostech.net
70_sare_spoof.cf.sare.sa-update.dostech.net
70_sare_random.cf.sare.sa-update.dostech.net
70_sare_oem.cf.sare.sa-update.dostech.net
70_sare_genlsubj0.cf.sare.sa-update.dostech.net
70_sare_genlsubj_eng.cf.sare.sa-update.dostech.net
70_sare_unsub.cf.sare.sa-update.dostech.net
70_sare_uri0.cf.sare.sa-update.dostech.net
70_sare_obfu0.cf.sare.sa-update.dostech.net
70_sare_stocks.cf.sare.sa-update.dostech.net
</code></pre>
<p>Create an update script /usr/local/bin/update-sa</p>
<pre><code>#!/bin/bash
#
#
sa-update -D --channelfile /etc/mail/spamassassin/sare-sa-update-channels.txt --gpgkey 856AA88A &amp;&gt;/var/log/sa-updates.log
</code></pre>
<p>Make it executable and add to cron</p>
<pre><code> # chmod +x /usr/local/bin/update-sa
 # ln -s /usr/local/bin/update-sa /etc/cron.daily/
 # ln -s /usr/local/bin/update-sa /etc/cron.hourly/
</code></pre>
<h3>Spamassassin milter</h3>
<p>Edit /etc/sysconfig/spamass-milter</p>
<pre><code>SOCKET=/var/run/spamass.sock
EXTRA_FLAGS="-m -r 8"
</code></pre>
<h4>Patch</h4>
<p>We need to <a href="http://www.topdog-software.com/files/spamass-milter.patch">patch</a>
the init file to fix the permissions of the socket created such that postfix
is able to use the socket.</p>
<pre><code> # wget http://www.topdog-software.com/files/spamass-milter.patch
 # patch /etc/rc.d/init.d/spamass-milter &lt; spamass-milter.patch
</code></pre>
<h3>Apache</h3>
<h4>Disable modules</h4>
<p>We will disable some modules that we are not using thus freeing up memory and
also improving security.</p>
<p>Edit /etc/httpd/conf/httpd.conf and comment out the modules as below.</p>
<pre><code>#LoadModule ldap_module modules/mod_ldap.so
#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
#LoadModule dav_module modules/mod_dav.so
#LoadModule status_module modules/mod_status.so
#LoadModule dav_fs_module modules/mod_dav_fs.so
#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule cache_module modules/mod_cache.so
#LoadModule disk_cache_module modules/mod_disk_cache.so
#LoadModule file_cache_module modules/mod_file_cache.so
#LoadModule mem_cache_module modules/mod_mem_cache.so
</code></pre>
<p>Edit /etc/httpd/conf.d/proxy_ajp.conf and comment out as below</p>
<pre><code>#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
</code></pre>
<h4>Listen to one ip for https</h4>
<p>Apache has to be configured to listed to one address for port 443 as webmin
will be using the same port. Edit /etc/httpd/conf.d/ssl</p>
<pre><code>Listen 192,168.1.6:443
</code></pre>
<h4>Enable gzip compression</h4>
<p>We setup gzip compression via the mod_deflate module to improve web server
performance and to cut down on bandwidth usage by compressing responses to the
client.</p>
<pre><code>SetOutputFilter DEFLATE
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
Header append Vary User-Agent env=!dont-vary
</code></pre>
<p>Setup logging for the deflate module</p>
<pre><code>DeflateFilterNote deflate_ratio
LogFormat "%v %h %l %u %t \"%r\" %&gt;s %b mod_deflate: %{deflate_ratio}n pct." vhost_with_deflate_info
CustomLog logs/deflate_access_log vhost_with_deflate_info
</code></pre>
<h4>Increase PHP max memory</h4>
<p>Edit the file /etc/php.ini and set the following</p>
<pre><code>memory_limit = 64M
</code></pre>
<h4>Enable virtual hosting</h4>
<pre><code>NameVirtualHost *:80
</code></pre>
<h4>Create default virtual host</h4>
<p>This needs to be the first virtual host, it will be the default on the server
the equivalent of the server with out virtual hosting.</p>
<pre><code>&lt;VirtualHost *:80&gt;
        Servername localhost.localdomain
        Serveradmin root@localhost.localdomain
&lt;/Virtualhost&gt;
</code></pre>
<h3>Roundcube webmail</h3>
<h4>Create database</h4>
<p>Create the database and add the roundcube user.</p>
<pre><code> # mysqladmin -p create roundcube
 # mysql -p
 # mysql&gt; GRANT ALL ON roundcube.* TO roundcube@localhost IDENTIFIED BY 'password';
</code></pre>
<p>Initialize the database</p>
<pre><code> # mysql -u roundcube -p roundcube &lt; /usr/share/doc/roundcube-0.1/SQL/mysql5.initial.sql
</code></pre>
<h4>Basic config</h4>
<p>Configure database DSN in /var/www/roundcube/config/db.inc.php</p>
<pre><code>$rcmail_config['db_dsnw'] = 'mysql://roundcube:password@localhost/roundcube';
</code></pre>
<p>Configure roundcube in /var/www/roundcube/config/main.inc.php</p>
<pre><code>$rcmail_config['default_host'] = 'localhost';
$rcmail_config['default_port'] = 143;
$rcmail_config['virtuser_file'] = '/etc/postfix/virtual';
$rcmail_config['smtp_server'] = 'localhost';
$rcmail_config['smtp_port'] = 25;
$rcmail_config['smtp_helo_host'] = 'localhost';
</code></pre>
<h4>Setup catch all virtualhost</h4>
<p>As we will be providing webmail for all domains that are created on the system
we need to setup a catch all virtualhost that can display roundcube when ever
a user accesses <a href="http://webmail.domainname">http://webmail.domainname</a></p>
<pre><code>&lt;VirtualHost *:80&gt;
ServerName webmail.example.com
ServerAlias webmail.*
DocumentRoot /var/www/roundcube
&lt;Directory /var/www/roundcube&gt;
Options -Indexes IncludesNOEXEC FollowSymLinks
allow from all
&lt;/Directory&gt;
&lt;/VirtualHost&gt;
</code></pre>
<h3>Iptables</h3>
<p>This is a basic firewall it may not suit your needs, firewalling is an art so
i recommend to read into it to improve on this basic one.</p>
<h4>Basic config</h4>
<p>Add these rules in your configuration file /etc/sysconfig/iptables</p>
<pre><code>*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m multiport -j ACCEPT --dports 80,443,25,110,143,53
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p icmp -m icmp -m limit --icmp-type 8 --limit 5/min -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -s 127.0.0.1 -j ACCEPT
-A OUTPUT -s 192.168.1.5 -j ACCEPT
-A OUTPUT -s 192.168.1.6 -j ACCEPT
COMMIT
</code></pre>
<h4>Activate config</h4>
<pre><code> # service iptables restart
</code></pre>
<h3>Virtualmin</h3>
<p>Virtualmin is a powerful and flexible hosting control panel that integrates
with webmin. We will be using it to provide the virtual hosting functions such
as creation of domains, accounts and maintaining configurations on the system.</p>
<h4>Start services</h4>
<p>You need to start up services that are required to be able to configure
virtualmin. Start the following services</p>
<pre><code> # service named start
 # service spamassassin start
 # service spamass-milter start
 # service clamav-milter start
 # service postfix start
 # service dovecot start
 # service imapproxy start
 # service httpd start
</code></pre>
<h4>Initial settings</h4>
<h5>Mysql</h5>
<p>Webmin needs to be able to communicate with mysql since we have set a password
for mysql we need to set that up in webmin, go to servers → mysql and enter
this information</p>
<h4>Configure Features</h4>
<p>You need to enable the features and plugins that we want to use. On login this
is the screen that you will see.</p>
<p>Enable the following features and save</p>
<ul>
<li>Home directory</li>
<li>Administration user</li>
<li>Mail for domain</li>
<li>BIND DNS domain</li>
<li>Apache website</li>
<li>Webalizer reporting</li>
<li>Log file rotation</li>
<li>Mysql database</li>
<li>Webmin user</li>
</ul>
<h4>Configure server templates</h4>
<p>Server template are used to customize the services and to create packages for
different hosting account types.</p>
<h4>Apache template</h4>
<p>You can make changes to the way apache virtual hosts are created by editing
this template, The defaults however will do for purposes of this howto.</p>
<h4>Domain owner template</h4>
<p>This template is used to configure various server limits such as number of
mailboxes,aliases,databases,virtual servers and other options like bandwidth
limits, admin abilities. For this howto we will use the default values.</p>
<h4>Home directory template</h4>
<p>This template allows you to set a skel directory to hold setting for new users
for this howto we will use the defaults</p>
<h4>Administration user</h4>
<p>This template lets you set the quota for the virtual server and the admin user
for this howto we will use the default quota 1GB.</p>
<h4>Mail for domain template</h4>
<p>This template sets various mail related options, we will modify the email
message sent on server creation to have to content below</p>
<pre><code>The following virtual server has been set up successfully :

Domain name:             ${DOM}
Hosting server:          ${HOSTNAME}
${IF-VIRT}
Virtual IP address:      ${IP}
${ENDIF-VIRT}
Administration login:    ${USER}
Administration password: ${PASS}
${IF-WEBMIN}
Administration URL:      ${WEBMIN_PROTO}://www.${DOM}:${WEBMIN_PORT}/
${ENDIF-WEBMIN}

${IF-WEB}
Website:                 http://www.${DOM}/
${IF-WEBALIZER}
Webalizer log reporting: Enabled
${ELSE-WEBALIZER}
Webalizer log reporting: Disabled
${ENDIF-WEBALIZER}

${ENDIF-WEB}
${IF-MAIL}
Email domain:            ${DOM}
SMTP server:             mail.${DOM}
POP3 server:             mail.${DOM}
Webmail:                 webmail.${DOM}

${ENDIF-MAIL}
${IF-DNS}
DNS domain:              ${DOM}
Nameserver:              ${HOSTNAME}

${ENDIF-DNS}
${IF-MYSQL}
MySQL database:          ${DB}
MySQL login:             ${MYSQL_USER}
MySQL password:          ${PASS}

${ENDIF-MYSQL}
${IF-POSTGRES}
PostgreSQL database:     ${DB}
PostgreSQL login:        ${USER}
PostgreSQL password:     ${PASS}

${ENDIF-POSTGRES}
</code></pre>
<p>We will leave the other options as the defaults.</p>
<h4>BIND DNS domain template</h4>
<p>This template is used to customize the zones that will be created by
virtualmin. The changes to be made are adding a spf record, add the following
records to auto generated text box (replace ns1.home.topdog-software.com. with
your slave server)</p>
<pre><code>@     IN NS ns1.home.topdog-software.com. ;slave
admin IN A 192.168.1.6 ;virtualmin
webmail IN A 192.168.1.5 ;webmail
</code></pre>
<p>In the directives text box add the following with the ip address of your slave
server such that the slave is allowed to do zone transfers.</p>
<pre><code>allow-transfer { 192.168.1.2; };
</code></pre>
<h4>Mysql Database template</h4>
<p>Contains options on creation of databases by virtualmin, for the howto we will
use the defaults.</p>
<h4>Webmin login template</h4>
<p>Contains option on creation of new users by virtualmin, for the howto we will
use the defaults</p>
<h4>Create virtual server</h4>
<p>Finally we have a working virtual server system, lets create our first virtual
server. Go to servers → virtualmin virtual servers and click add new virtual
server, owned by new user.</p>
<p>Fill in the require fields and click create.</p>
<p>Add a mail user to the domain. click on the domain name, then click edit mail
and FTP users, then add user and fill in the information.</p>
<h2>Testing</h2>
<h3>Postfix</h3>
<h4>Test smtp</h4>
<pre><code>telnet 192.168.1.5 25
Connected to localhost.
Escape character is '^]'.
220 tds mail cluster
helo me
250 hosting1
mail from:address@yahoo.com
250 2.1.0 Ok
rcpt: andrew@example.com
250 2.1.0 Ok
DATA
354 End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;
From:address@yahoo.com
To:andrew@example.com
Subject:This is a test
Hi
This is a test
.
250 2.0.0 Ok: queued as 4ACCC7C5A6

telnet 192.168.1.5 25
Trying 192.168.1.5...
Connected to localhost.
Escape character is '^]'.
220 tds mail cluster
ehlo me
250-hosting1
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
</code></pre>
<h4>Test dkim</h4>
<p>Send a mail to autorespond+dkim@dk.elandsys.com</p>
<h4>Test domainkeys</h4>
<p>Send a mail to autorespond+dk@dk.elandsys.com</p>
<h3>Dovecot</h3>
<h4>Test pop3</h4>
<pre><code>telnet 192.168.1.5 110
+OK Dovecot ready.
user andrew.example
+OK
pass password
+OK Logged in.
quit
+OK Logging out.
</code></pre>
<h4>Test imap</h4>
<pre><code>telnet 192.168.1.5 143
* OK Dovecot ready.
01 login andrew.example password
01 OK User logged in
01 list "" "*"
* LIST (\HasNoChildren) "." "Trash"
* LIST (\HasNoChildren) "." "Drafts"
* LIST (\HasNoChildren) "." "Junk"
* LIST (\HasNoChildren) "." "Sent"
* LIST (\HasNoChildren) "." "INBOX"
01 OK List completed.
01 logout
* BYE LOGOUT received
01 OK Completed
</code></pre>
<h3>Bind</h3>
<pre><code>dig example.com @127.0.0.1
</code></pre>
<h3>Clamav-milter</h3>
<p>We are using the test virus from <a href="http://www.eicar.org">www.eicar.org</a></p>
<pre><code>telnet 192.168.1.5 25
Connected to localhost.
Escape character is '^]'.
220 tds mail cluster
helo me
250 hosting1
mail from:address@yahoo.com
250 2.1.0 Ok
rcpt: andrew@example.com
250 2.1.0 Ok
DATA
354 End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
.
550 5.7.1 virus Eicar-Test-Signature detected by ClamAV - http://www.clamav.net
quit
221 2.0.0 Bye
</code></pre>
<p>Take a lot at your /var/log/maillog you should see something like this</p>
<pre><code>73BC87C4E4: milter-reject: END-OF-MESSAGE from localhost[127.0.0.1]:
5.7.1 virus Eicar-Test-Signature detected by ClamAV - http://www.clamav.net; 
from=&lt;address@yahoo.com&gt; to=&lt;andrew@example.com&gt; proto=SMTP helo=&lt;me&gt;
</code></pre>
<h3>Spamass-milter</h3>
<p>We are using the test message from
<a href="http://spamassassin.apache.org/gtube/">http://spamassassin.apache.org/gtube/</a></p>
<pre><code>telnet 192.168.1.5 25
Connected to localhost.
Escape character is '^]'.
220 tds mail cluster
helo me
250 hosting1
mail from:address@yahoo.com
250 2.1.0 Ok
rcpt: andrew@example.com
250 2.1.0 Ok
DATA
354 End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;
XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X
.
550 5.7.1 Blocked by SpamAssassin
quit
221 2.0.0 Bye
</code></pre>
<p>You will see this in your log files</p>
<pre><code>spamd: result: Y 1002 - AWL,GTUBE,MISSING_SUBJECT,TVD_SPACE_RATIO,UNPARSEABLE_RELAY scantime=0.5,size=723,user=root,uid=99,required_score=5.0,
</code></pre>
<h2>Comments</h2>
<p>Got any comments/bugs drop me a mail my contact info is on the home page.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
