close x

How to MailServer on Ubuntu+Amazon EC2+Scripts to generate mail users

We are going to build a mail server in Amazon ecosystem…

First we need to launch the instance with Ubuntu 10.04, maybe you can find this ami-cf4d67bb in europe, and this ami-c997c68c in USA west or this ami-2d4aa444 in USA East.

Once the AMI is launched we connect by ssh:

ssh -i KEY_PAIR ubuntu@ip_server

1.- Update the sources:

aptitude update & aptitude safe-upgrade

2.- Install Mysql server, and select internet site when you’ll be asked.

aptitude install mysql-client mysql-server

3.- Install Postfix and SASL

aptitude install postfix postfix-mysql libsasl2-modules libsasl2-modules-sql libgsasl7 libauthen-sasl-cyrus-perl sasl2-bin libpam-mysql

4.- Install ClamAV

aptitude install clamav-base libclamav6 clamav-daemon clamav-freshclam

5.- Install Amavis, SpamAssassin and postgrey

aptitude install amavisd-new spamassassin spamc postgrey

6.- Install phpMyadmin

aptitude install phpmyadmin

7.- Install Shorewall

aptitude install shorewall-common shorewall-perl shorewall-doc

8.- Install courier, we say no to the directory creation.

aptitude install courier-base courier-authdaemon courier-authlib-mysql courier-imap courier-imap-ssl courier-ssl

SHOREWALL PENDIENT

9.- Configure MTA

Set the server name

nano /etc/mailname

Open the postfix conf file, and change the next values “domain.com” is the name of our domain:

nano /etc/postfix/main.cf

myorigin = domain.com

Then decide what the greeting text will be. Enough info so it is useful, but not divelge everything to potential hackers.

smtpd_banner = $myhostname ESMTP $mail_name

We are going to send mails from our server…maybe later we’ll try by Gmail, so…

relayhost =

Next is network details. You will accept connection from anywhere, and you only trust this machine

inet_interfaces = all

mynetworks_style = host

As we will be using virtual domains, these need to be empty.

local_recipient_maps =

mydestination =

Then will set a few numbers.

# how long if undelivered before sending warning update to sender

delay_warning_time = 4h

# will it be a permanent error or temporary

unknown_local_recipient_reject_code = 450

# how long to keep message on queue before return as failed.

maximal_queue_lifetime = 3d

# max and min time in seconds between retries if connection failed

minimal_backoff_time = 1000s

maximal_backoff_time = 8000s

# how long to wait when servers connect before receiving rest of data

smtp_helo_timeout = 60s

# how many address can be used in one message.

# effective stopper to mass spammers, accidental copy in whole address list

# but may restrict intentional mail shots.

smtpd_recipient_limit = 16

# how many error before back off.

smtpd_soft_error_limit = 3

# how many max errors before blocking it.

smtpd_hard_error_limit = 12

Now we can specify some restrictions. Be carefull that each setting is on one line only.

# Requirements for the HELO statement

smtpd_helo_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit

# Requirements for the sender details

smtpd_sender_restrictions = permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit

# Requirements for the connecting server

smtpd_client_restrictions = reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl, reject_rbl_client dnsbl.njabl.org

# Requirement for the recipient address

smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, permit

smtpd_data_restrictions = reject_unauth_pipelining

Further restrictions:

# require proper helo at connections

smtpd_helo_required = yes

# waste spammers time before rejecting them

smtpd_delay_reject = yes

disable_vrfy_command = yes

Next we need to set some maps and lookups for the virtual domains.

# not sure of the difference of the next two # but they are needed for local aliasing

alias_maps = hash:/etc/postfix/aliases

alias_database = hash:/etc/postfix/aliases

# this specifies where the virtual mailbox folders will be located

virtual_mailbox_base = /var/spool/mail/virtual

# this is for the mailbox location for each user

virtual_mailbox_maps = mysql:/etc/postfix/mysql_mailbox.cf

# and this is for aliases

virtual_alias_maps = mysql:/etc/postfix/mysql_alias.cf

# and this is for domain lookups

virtual_mailbox_domains = mysql:/etc/postfix/mysql_domains.cf

# this is how to connect to the domains (all virtual, but the option is there)

# not used yet

# transport_maps = mysql:/etc/postfix/mysql_transport.cf

You can use a lookup for the uid and gid of the owner of mail files. But I tend to have one owner(virtual), so instead add this:

virtual_uid_maps = static:5000

virtual_gid_maps = static:5000

Let’s set up a alias file

cp /etc/aliases /etc/postfix/aliases

Add some aliases if needed

postalias /etc/postfix/aliases

Next you need to set up the folder where the virtual mail will be stored. This may have already been done by the apt-get. And also create the user whom will own the folders.

# to add if there is not a virtual user

mkdir /var/spool/mail/virtual

groupadd –system virtual -g 5000

useradd –system virtual -u 5000 -g 5000

chown -R virtual:virtual /var/spool/mail/virtual

Now we are going to connect MySQL with Postfix…

nano /etc/postfix/mysql_mailbox.cf

user=mail password=mailPASSWORD dbname=maildb table=users select_field=maildir where_field=id hosts=www.notesfromchechu.com additional_conditions = and enabled = 1

user=mail

password=PASSWORD

dbname=maildb

table=users

select_field=maildir

where_field=id

hosts=www.notesfromchechu.com

additional_conditions = and enabled = 1

Create how to find the e-mail alias:

nano /etc/postfix/mysql_alias.cf

user=mail

password=PASSWORD

dbname=maildb

table=aliases

select_field=destination

where_field=mail

hosts=www.notesfromchechu.com

additional_conditions = and enabled = 1

Create how to find the domains:

nano /etc/postfix/mysql_domains.cf

user=mail

password=PASSWORD

dbname=maildb

table=domains

select_field=domain

where_field=domain

hosts=www.notesfromchechu.com

additional_conditions = and enabled = 1

MySQL

Once logged into our MySQL server:

# then we create the mail database

create database maildb;

# then we create a new user: “mail”

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON maildb.* TO ‘mail’@'localhost’ IDENTIFIED by ‘mailPASSWORD’;

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON maildb.* TO ‘mail’@'%’ IDENTIFIED by ‘mailPASSWORD’;

exit;

mysql -u mail -p maildb

CREATE TABLE `aliases` ( `pkid` smallint(3) NOT NULL auto_increment, `mail` varchar(120) NOT NULL default ”, `destination` varchar(120) NOT NULL default ”, `enabled` tinyint(1) NOT NULL default ’1′, PRIMARY KEY (`pkid`), UNIQUE KEY `mail` (`mail`) ) ;

CREATE TABLE `domains` ( `pkid` smallint(6) NOT NULL auto_increment, `domain` varchar(120) NOT NULL default ”, `transport` varchar(120) NOT NULL default ‘virtual:’, `enabled` tinyint(1) NOT NULL default ’1′, PRIMARY KEY (`pkid`) ) ;

CREATE TABLE `users` ( `id` varchar(128) NOT NULL default ”, `name` varchar(128) NOT NULL default ”, `uid` smallint(5) unsigned NOT NULL default ’5000′, `gid` smallint(5) unsigned NOT NULL default ’5000′, `home` varchar(255) NOT NULL default ‘/var/spool/mail/virtual’, `maildir` varchar(255) NOT NULL default ‘blah/’, `enabled` tinyint(3) unsigned NOT NULL default ’1′, `change_password` tinyint(3) unsigned NOT NULL default ’1′, `clear` varchar(128) NOT NULL default ‘ChangeMe’, `crypt` varchar(128) NOT NULL default ‘sdtrusfX0Jj66′, `quota` varchar(255) NOT NULL default ”, `procmailrc` varchar(128) NOT NULL default ”, `spamassassinrc` varchar(128) NOT NULL default ”, PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`) ) ;

Let’s configure MySQL

nano /etc/mysql/my.cnf

bind-address = www.notesfromchechu.com

general_log_file = /var/log/mysql/mysql.log

general_log = 1

/etc/init.d/mysql restart

POP/IMAP

nano /etc/courier/authdaemonrc

authmodulelist=”authmysql”

logging.DEBUG_LOGIN=2

nano /etc/courier/authmysqlrc

MYSQL_USERNAME mail

MYSQL_PASSWORD PASSWORD

MYSQL_DATABASE maildb

MYSQL_USER_TABLE users

MYSQL_CRYPT_PWFIELD crypt

# MYSQL_CLEAR_PWFIELD clear

MYSQL_MAILDIR_FIELD concat(home,’/',maildir)

MYSQL_WHERE_CLAUSE enabled=1

Basic settings are done…let’s going to test it:

reboot server

telnet localhost 25

EHLO name_of_our_server

MAIL FROM:

RCPT TO:

data

we’ll write somethig and will finish with and enter and ‘.’

we can see logs here /var/log/mail.log

Let’s go for more

Amavis check mails for viruses and spam, Amavis’s conf files are in:

cd /etc/amavis/conf.d

nano 15-content_filter_mode

Comment out both virus and spam scans. (Default).

# #@bypass_virus_checks_maps = (

# \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

# @bypass_spam_checks_maps = (

# \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

nano 50-user

In the middle insert:

@local_domains_acl = qw(.);

$log_level = 2;

$syslog_priority = ‘debug’;

# $sa_tag_level_deflt = 2.0; # add spam info headers if at, or above that level

# $sa_tag2_level_deflt = 6.31;# add ‘spam detected’ headers at that level

$sa_kill_level_deflt = 8.0; # triggers spam evasive actions

# $sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent

$final_spam_destiny = D_PASS;

# $final_spam_destiny = D_REJECT;# default

# $final_spam_destiny = D_BOUNCE; # debian default

# $final_spam_destiny = D_DISCARD; # ubuntu default, recommended as sender is usually faked

We have now setup amavis to scan and pass along incomming email. Next we will setup postfix to talk to amavis.

vi /etc/postfix/master.cf

Append these lines to the end of the file (make sure they are not already present). (Note the -o lines have spaces in front of them).

amavis unix – - – - 2 smtp

-o smtp_data_done_timeout=1200

-o smtp_send_xforward_command=yes

-o disable_dns_lookups=yes

-o max_use=20

www.notesfromchechu.com:10025 inet n – - – - smtpd

-o content_filter=

-o local_recipient_maps=

-o relay_recipient_maps=

-o smtpd_restriction_classes=

-o smtpd_delay_reject=no

-o smtpd_client_restrictions=permit_mynetworks,reject

-o smtpd_helo_restrictions=

-o smtpd_sender_restrictions=

-o smtpd_recipient_restrictions=permit_mynetworks,reject

-o smtpd_data_restrictions=reject_unauth_pipelining

-o smtpd_end_of_data_restrictions=

-o mynetworks=127.0.0.0/8

-o smtpd_error_sleep_time=0

-o smtpd_soft_error_limit=1001

-o smtpd_hard_error_limit=1000

-o smtpd_client_connection_count_limit=0

-o smtpd_client_connection_rate_limit=0

-o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

Also add the following two lines immediately below the “pickup” transport service:

-o content_filter=

-o receive_override_options=no_header_body_checks

and then added to main.cf

nano /etc/postfix/main.cf

content_filter = amavis:[www.notesfromchechu.com]:10024

Add user to group:

adduser clamav amavis

This should be it to get amavis working. If emails are picked up by amavis and passed back to postfix then it looks okay. Only when finished testing do you proced to uncomment the anti virus and anti spam lines insudo

nano 15-content_filter_mode

@bypass_virus_checks_maps = (

\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (

\%bypass_spam_checks,\@bypass_spam_checks_acl, \$bypass_spam_checks_re);

nano /etc/amavis/conf.d/50-user

@local_domains_acl = qw(.);

$log_level = 1;

$syslog_priority = ‘info’;

# $sa_tag_level_deflt = 2.0;# add spam info headers if at, or above that level

# $sa_tag2_level_deflt = 6.31; # add ‘spam detected’ headers at that level

$sa_kill_level_deflt = 8.0; # triggers spam evasive actions # $sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent

# $final_spam_destiny = D_PASS; # $final_spam_destiny = D_REJECT; # default

# $final_spam_destiny = D_BOUNCE; # debian default $final_spam_destiny = D_DISCARD; # ubuntu default, recommended as sender is usually faked

Activate SpamAssasin

nano /etc/default/spamassassin

ENABLED=1

nano /etc/spamassassin/local.cf

use_bayes 1bayes_auto_learn 1

By default freshclam, the daemon that updates the virus definition database, is run 24 times a day. That seems a little excessive, so I tend to set that to once a day.

Choose daemon and which server is closest to you.

dpkg-reconfigure clamav-freshclam

The Postgrey conf is ok, but we need to tell postfix to use it:

nano /etc/postfix/main.cf

smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, check_policy_service inet:www.notesfromchechu.com:10023, permit

nano /etc/default/postgrey

POSTGREY_OPTS=”–inet=10023 –max-age=365″

Now we’ll insert some data to test the system…

We enter into phpmysql, and execute the next sql commands:

INSERT INTO domains (domain) VALUES (‘domain.com’);

Some alias:

INSERT INTO aliases (mail,destination) VALUES (‘prueba1@domain.com’,'prueba@domain.com’), (‘prueba2@domain.com’,'prueba@domain.com’);

And the user:

INSERT INTO users (id,name,maildir,crypt) VALUES (‘prueba@domain.com’,'prueba’,'prueba/’, encrypt(‘prueba’) );

SECURITY

SASL

aptitude install sasl2-bin libpam-mysql libsasl2-modules libsasl2-modules-sql

adduser postfix sasl

mkdir -p /var/spool/postfix/var/run/saslauthd

nano /etc/postfix/main.cf

# SASL

smtpd_sasl_auth_enable = yes # If your potential clients use Outlook Express or other older clients

# this needs to be set to yes

broken_sasl_auth_clients = no

smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain =

Modify these existing configurations:

# Add permit_sasl_authenticated to you existing smtpd_sender_restrictions

smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks,

warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain,

reject_unauth_pipelining, permit

# Add permit_sasl_authenticated to you existing smtpd_recipient_restrictions

smtpd_recipient_restrictions = reject_unauth_pipelining, permit_mynetworks,

permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain,

reject_unauth_destination, check_policy_service inet:www.notesfromchechu.com:10023, permit

We change the way Sasl is running:

nano /etc/default/saslauthd

START=yes

OPTIONS=”-r -c -m /var/spool/postfix/var/run/saslauthd”

Tell postfix how to interact with SASL:

nano /etc/postfix/sasl/smtpd.conf

pwcheck_method: saslauthd

mech_list: plain login cram-md5 digest-md5

log_level: 7

allow_plaintext: true

auxprop_plugin: mysql

sql_engine: mysql

sql_hostnames: www.notesfromchechu.com

sql_user: mail

sql_passw: PASSWORD

sql_database: maildb

sql_select: select crypt from users where id=’%u@%r’ and enabled = 1

nano /etc/pam.d/smtp

auth required pam_mysql.so user=mail passwd=PASSWORD host=www.notesfromchechu.com db=maildb table=users usercolumn=id passwdcolumn=crypt crypt=1

account sufficient pam_mysql.so user=mail passwd=PASSWORD host=www.notesfromchechu.com db=maildb table=users usercolumn=id passwdcolumn=crypt crypt=1

/etc/init.d/saslauthd restart

/etc/init.d/postfix restart

Now we’ll set the encryption

First we need to create the certificate:

cd /etc/postfix

openssl req -new -outform PEM -out postfix.cert -newkey rsa:2048 -nodes -keyout postfix.key -keyform PEM -days 999 -x509

nano /etc/postfix/main.cf

# TLS parameters

# smtp_use_tls = no

smtp_tls_security_level = may

# smtpd_use_tls=yes

smtpd_tls_security_level = may

# smtpd_tls_auth_only = no

smtp_tls_note_starttls_offer = yes

smtpd_tls_loglevel = 1

smtpd_tls_received_header = yes

smtpd_tls_session_cache_timeout = 3600s

tls_random_source = dev:/dev/urandom

smtpd_tls_cert_file = /etc/postfix/postfix.cert

smtpd_tls_key_file = /etc/postfix/postfix.key

# smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

# smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

nano /etc/postfix/master.cf

submission inet n – n – - smtpd

-o smtpd_sasl_auth_enable=yes

# if you do not want to restrict it encryption only, comment out next line

-o smtpd_tls_auth_only=yes

# -o smtpd_tls_security_level=encrypt

# -o header_checks=

# -o body_checks=<

-o smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject -o smtpd_sasl_security_options=noanonymous,noplaintext

-o smtpd_sasl_tls_security_options=noanonymous

# -o milter_macro_daemon_name=ORIGINATING<

smtps inet n – - – - smtpd

-o smtpd_tls_wrappermode=yes

-o smtpd_sasl_auth_enable=yes

-o smtpd_tls_auth_only=yes

-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_sasl_security_options=noanonymous,noplaintext

-o smtpd_sasl_tls_security_options=noanonymous

# -o milter_macro_daemon_name=ORIGINATING

cd /etc/courier

openssl req -x509 -newkey rsa:1024 -keyout imapd.pem -out imapd.pem -nodes -days 999

nano /etc/courier/imapd-ssl

Ok the mail server conf its done…now we are going to enable the webmail…

WEBMAIL

aptitude install roundcube roundcube-mysql

This will create a symblink in /etc/apache2/conf.d/ to /etc/roundcube/apache.conf. Edit this file.

nano /etc/roundcube/apache.conf

Depending on your setup you may want to move those Alias commands at the top to your virtual hosts configuration, or for this example enable them here for all hosts.

# Uncomment them to use it or adapt them to your configuration

Alias /roundcube/program/js/tiny_mce/ /usr/share/tinymce/www/

Alias /roundcube /var/lib/roundcube

Next edit the configuration file

nano /etc/roundcube/main.inc.php

$rcmail_config['default_host'] = ‘ssl://localhost:993′;

$rcmail_config['smtp_server'] = ‘ssl://localhost’;

$rcmail_config['smtp_port'] = 465;

$rcmail_config['smtp_helo_host'] = ‘mailserver.domain.com”;

$rcmail_config['create_default_folders'] = TRUE;

$rcmail_config['sendmail_delay'] = 1;

Reload Apache

/etc/init.d/apache2 reload

Cloud Computing Linux0 comments

Leave a Reply