Mail Server Setup With Exim, MySQL, Cyrus-Imapd, Horde Webmail On Centos 5.1 - Page 2
Configuration
Configure Apache
- Enable virtual hosting and create default virtualhost, edit /etc/httpd/conf/httpd.conf and add at the end
NameVirtualHost *:80 <VirtualHost *:80> ServerAdmin [email protected] </VirtualHost>
- Create the virtual host for horde webmail add this under the above
<VirtualHost *:80> Servername mail.home.topdog-software.com DocumentRoot /usr/share/horde ErrorLog logs/mail-error_log CustomLog logs/mail-access_log common </VirtualHost>
- Enable horde security settings edit the file /etc/httpd/conf.d/horde.conf and set as below
#Alias /horde /usr/share/horde <Directory /usr/share/horde> 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 </Directory> <Directory /usr/share/horde/config> Order Deny,Allow Deny from all </Directory> <DirectoryMatch "^/usr/share/horde/(.*/)?(config|lib|locale|po|scripts|templates)/(.*)?"> Order Deny,Allow Deny from all </DirectoryMatch>
- Increase PHP memory limit edit /etc/php.ini and change to below
memory_limit = 64M
- 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
Servername mail.home.topdog-software.com:443 DocumentRoot /usr/share/horde
Configure Exim
- Switch the MTA to exim
system-switch-mail (select exim)
Anti-virus / Sanesecurity Checks
- 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
av_scanner = clamd:/var/run/clamav/clamd.sock
RBL's
- Configure the RBL's under acl_check_rcpt:
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
Anti Spam
- 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.
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}{}}
- To reject messages from clients that dont provide a HELO/EHLO add this to acl_check_rcpt:
drop message = REFUSED - no HELO/EHLO greeting log_message = remote host did not present greeting condition = ${if def:sender_helo_name {false}{true}}
- 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)
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
- Stop rogue spam bots from trashing your machine
smtp_accept_max_nonmail = 30 smtp_max_unknown_commands = 1
- Don't advertise pipelining
pipelining_advertise_hosts =
- Enable Spamassassin checks
spamd_address = /var/run/spamassassin/spamd.sock
- Reject all messages with score above 6 at smtp time. (acl_check_data)
accept condition = ${if >={$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 >{$spam_score_int}{60} {1}} message = Your message scored $spam_score SpamAssassin point. Report follows:\n\ $spam_report
Mail routing
- Enable access to Mysql database
hide mysql_servers = localhost/horde/horde/hordepassword
- Modify the local delivery router to deliver to cyrus but verify the email address of user before delivery (in routers section of exim.conf)
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
- Create a transport to deliver to cyrus via lmtp socket
local_delivery: driver = lmtp socket = /var/lib/imap/socket/lmtp batch_max = 50 user = cyrus
SMTP Authentication
- Add the following to the authentication section of /etc/exim/exim.conf
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
Full sample configuration
Download the full configuration file here.
Configure Mysql
- Disable TCP networking edit /etc/my.cnf and the following in the mysqld section
skip-networking
- Set root password
/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h your_host_name password 'new-password' -p
Configure Horde
- Edit the sql file and change the mysql password for the horde user
cp /usr/share/horde/scripts/sql/create.mysql.sql .
vi create.mysql.sqlREPLACE INTO user (host, user, password) VALUES ( 'localhost', 'horde', -- IMPORTANT: Change this password! PASSWORD('hordepassword') );
- Create the user and populate the horde database
mysql -p < create.mysql.sql
- Create the tables for turba (Address book)
mysql -p horde < /usr/share/horde/turba/scripts/sql/turba_objects.mysql.sql
- Create the tables for kronolith (calendering)
mysql -p horde < /usr/share/horde/kronolith/scripts/sql/kronolith.mysql.sql
Horde Configuration
- Create horde base configuration /usr/share/horde/config/conf.php
<?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', '[email protected]'); $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'] = '[email protected]'; $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;
- 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
$_prefs['initial_application'] = array( 'value' => 'imp', 'locked' => true, 'shared' => true, 'type' => 'select', 'desc' => sprintf(_("What application should %s display after login?"), $GLOBALS['registry']->get('name')) );
- 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
$this->applications['horde'] = array( 'fileroot' => dirname(__FILE__) . '/..', 'webroot' => '', 'initial_page' => 'login.php', 'name' => _("Horde"), 'status' => 'active', 'templates' => dirname(__FILE__) . '/../templates', 'provides' => 'horde' );