Installation:Ubuntu:PostfixMY

From PMWH2 - PHPMyWebHosting's official wiki
Jump to: navigation, search
up

Needed Packages

On Ubuntu 7.10 Server you need to install the following packages:

  • postfix (Version 2)
  • postfix-mysql
  • postfix-pcre
  • postfix-policyd (if you want anti-spam control)
  • libsasl2-2
  • libsasl2-modules
  • libsasl2-modules-sql
  • openssl
  • amavisd-new, zoo, lha, unarj, zip, unzip (if you want virus scanning)

Installation

On Ubuntu 7.10 Server use this command to install all at once:

bash #> sudo apt-get install postfix postfix-mysql postfix-pcre libsasl2-2 libsasl2-modules libsasl2-modules-sql openssl

If you want to use amavisd-new, then run

bash #> sudo apt-get install amavisd-new zip unzip zoo lha unrar

If you want to use postfix-policyd, then run

bash #> sudo apt-get install postfix-policyd

Please create a new systemuser named "vmail" to your system.

On Ubuntu 7.10 Server use this command:

bash #> sudo adduser --disabled-password --disabled-login --gecos "Mail user" vmail --uid 5000 --gid 5000

After the creation, type this to get uid and gid of the vmail user, we will need those values in Postfix' main.cf.

bash #> id vmail
uid=5000(vmail) gid=5000(vmail) Gruppen=5000(vmail)
bash #>

Postfix configuration

First, you have to configure postfix to connect to mysql database which is installed via phpmywebhosting. Take care, that postfix is started after mysql. Check it with the following command:

bash #> ls /etc/rc2.d/ | grep -E "(postfix|mysql)"
S19mysql
S20postfix
bash #>

If it is like above, everything is alright. If not, delete the links in /etc/rc2.d/ and create them new.

Ubuntu: configure /etc/postfix/main.cf From a terminal prompt:

bash #> sudo dpkg-reconfigure postfix

Insert the following details when asked (replacing example.com with your domain name if you have one):

* Internet Site
* example.com
* postmaster
* localhost
* No
* 127.0.0.0/8
* 0
* +
* all

than

bash #> sudo postconf -e 'inet_interfaces = [IP your MX points to]'
bash #> sudo postconf -e 'virtual_alias_domains ='
bash #> sudo postconf -e 'virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_forwardings.cf mysql:/etc/postfix/mysql-virtual_email2email.cf'
bash #> sudo postconf -e 'virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_domains.cf'
bash #> sudo postconf -e 'virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailboxes.cf'
bash #> sudo postconf -e 'transport_maps = mysql:/etc/postfix/mysql-virtual-transport.cf mysql:/etc/postfix/mysql-backup-transport.cf'
bash #> sudo postconf -e 'virtual_mailbox_base = [your mailbox base]'
bash #> sudo postconf -e 'virtual_uid_maps = static:5000        # [VMAIL-UID]'
bash #> sudo postconf -e 'virtual_gid_maps = static:5000        # [VMAIL-GID]'

# define which email is accepted for delivery only
# alias_maps means: addresses in the MySQL aliase table
# virtual_mailbox_maps: addresses in the MySQL virtual table
# unix:passwd.byname: addresses of local users in /etc/passwd (optional)
bash #> sudo postconf -e 'local_recipient_maps = $alias_maps $virtual_mailbox_maps unix:passwd.byname'

# settings for authenticated SMTP
bash #> sudo postconf -e 'smtpd_sasl_auth_enable = yes'
bash #> sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_relay_domains'
bash #> sudo postconf -e 'smtpd_sasl_security_options = noanonymous'
bash #> sudo postconf -e 'broken_sasl_auth_clients = yes'

bash #> sudo postconf -e 'message_size_limit = 10000000'

Additional for quota support (only with courier maildrop)

bash #> sudo postconf -e 'virtual_transport = maildrop'
bash #> sudo postconf -e 'virtual_mailbox_limit = 51200000'
bash #> sudo postconf -e 'virtual_create_maildirsize = yes'
bash #> sudo postconf -e 'virtual_mailbox_extended = yes'
bash #> sudo postconf -e 'virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf'
bash #> sudo postconf -e 'virtual_mailbox_limit_override = yes'
bash #> sudo postconf -e 'virtual_maildir_limit_message = Sorry, the users maildir has overdrawn his diskspace quota, please try again later.'
bash #> sudo postconf -e 'virtual_overquota_bounce = yes'

# courier maildrop (uncomment for maildrop use) 
bash #> sudo postconf -e 'maildrop_destination_concurrency_limit = 1'
bash #> sudo postconf -e 'maildrop_destination_recipient_limit   = 1'

postfix-policyd

bash #> sudo postconf -e 'smtpd_restriction_classes = policy-weight'
bash #> sudo postconf -e 'policy-weight = check_policy_service inet:127.0.0.1:10031'

smtpd_recipient_restrictions

bash #> sudo postconf -e 'smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unknown_sender_domain,reject_unknown_recipient_domain,reject_unauth_destination,reject_unauth_pipelining,reject_invalid_hostname,reject_non_fqdn_hostname,check_recipient_access mysql:/etc/postfix/mysql-smtpd_restriction_class.cf,permit'

As you can see we will not be querying the MySQL database according to definitions in /etc/postfix/mysql-aliases.cf.

For this to work you need to create these files first. They define how Postfix accesses the database and how you named the fields. Just copy and paste them:

Note that in the files we create below, we specify 127.0.0.1 for the hosts field instead of localhost. This is because Postfix is run in a chroot environment, and if you specify localhost Postfix will try to connct to the MySQL deamon using a unix socket in the directory /var/run/mysql, to which it will not have access. Using 127.0.0.1 forces Postfix to connect using a TCP/IP socket, which will work in the chroot environment.

/etc/postfix/mysql-virtual_domains.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_transport
select_field = destination
where_field = domain

/etc/postfix/mysql-virtual_forwardings.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_forwardings
select_field = destination
where_field = source

/etc/postfix/mysql-virtual_mailboxes.cf

user = postfix_user
password = postfx_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_users
select_field = maildir
where_field = email

/etc/postfix/mysql-virtual_email2email.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_users
select_field = email
where_field = email

/etc/postfix/mysql-virtual-transport.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_transport
select_field =  destination
where_field = domain
additional_conditions = and `master_destination` like '%%:[your MX IpAddress]:%%'

/etc/postfix/mysql-backup-transport.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_transport
select_field =  master_destination
where_field = domain
additional_conditions = and `master_destination` not like '%%:[your MX IpAddress]:%%'

/etc/postfix/mysql_virtual_mailbox_limit_maps.cf (for use with courier maildrop)

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = postfix_users
select_field = quota
where_field = email

/etc/postfix/mysql-smtpd_restriction_class.cf

user = postfix_user
password = postfix_password
dbname = pmwh2
hosts =  127.0.0.1
table = pmwh2_domains
select_field = smtpd_restriction_class
where_field = domain

Make sure to run

bash #> sudo chmod o= /etc/postfix/mysql-*
bash #> sudo chgrp postfix /etc/postfix/mysql-*

Now we configure postfix to understand authenticated SMTP. This is easy. Just put the following lines in

/etc/postfix/sasl/smtpd.conf

pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: plain login cram-md5 digest-md5
sql_engine: mysql
sql_user: postfix_user
sql_passwd: postfix_password
sql_database: pmwh2
sql_hostnames: 127.0.0.1
sql_select: select password from users where email='%u@%r'

Generate certificates to be used for TLS encryption and/or certificate Authentication: You will then be asked a few question about the fields of the certificate. It does not matter what you enter. Just fill the fields. One exception though - the "Common Name" must be the hostname of your mail server. Example session:

Country Name (2 letter code) [AU]:AT
State or Province Name (full name) [Some-State]:LowerAustria
Locality Name (eg, city) []:Hoeflein
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.com PHPMyWebHosting
Organizational Unit Name (eg, section) []:Master of Disaster
Common Name (eg, YOUR name) []:smtp.example.com
Email Address []:postmaster@example.com

Run from Console

bash #> sudo openssl genrsa -des3 -rand /etc/hosts -out smtpd.key 1024
bash #> sudo chmod 600 smtpd.key
bash #> sudo openssl req -new -key smtpd.key -out smtpd.csr
bash #> sudo openssl x509 -req -days 3650 -in smtpd.csr -signkey smtpd.key -out smtpd.crt
bash #> sudo openssl rsa -in smtpd.key -out smtpd.key.unencrypted
bash #> sudo mv -f smtpd.key.unencrypted smtpd.key
bash #> sudo openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650
bash #> sudo mv smtpd.key /etc/ssl/private/
bash #> sudo mv smtpd.crt /etc/ssl/certs/
bash #> sudo mv cakey.pem /etc/ssl/private/
bash #> sudo mv cacert.pem /etc/ssl/certs/

Configure Postfix to do TLS encryption for both incoming and outgoing mail:

bash #> sudo postconf -e 'smtpd_tls_auth_only = no'
bash #> sudo postconf -e 'smtp_use_tls = yes'
bash #> sudo postconf -e 'smtpd_use_tls = yes'
bash #> sudo postconf -e 'smtp_tls_note_starttls_offer = yes'
bash #> sudo postconf -e 'smtpd_tls_key_file = /etc/ssl/private/smtpd.key'
bash #> sudo postconf -e 'smtpd_tls_cert_file = /etc/ssl/certs/smtpd.crt'
bash #> sudo postconf -e 'smtpd_tls_CAfile = /etc/ssl/certs/cacert.pem'
bash #> sudo postconf -e 'smtpd_tls_loglevel = 1'
bash #> sudo postconf -e 'smtpd_tls_received_header = yes'
bash #> sudo postconf -e 'smtpd_tls_session_cache_timeout = 3600s'
bash #> sudo postconf -e 'tls_random_source = dev:/dev/urandom'

Make sure at least the key file is not readable for the whole wide world:

bash #> sudo chmod o= /etc/ssl/private/smtpd.key

A quick test

Run postfix reload to restart Postfix. Run

telnet localhost 25

and enter

EHLO anywhere.org

You should find a line reading

250-STARTTLS

Bingo - TLS is running.

Virus filtering

Now that you operate your own professional email server you may offer your users a little more service: scanning incoming emails for viruses. Good news: it is perfectly easy to install. Bad news: it will most likely mean you have to spend money because good antivirus software does not come for free (yet).

Let's get to work. First make sure you installed the amavisd-new package. Amavis is a piece of software that gets all emails forwarded, scans them using an external virus scanner and re-injects them into your mail system. It is important to note that Amavis does not include a virus scanner - it is just an interface between Postfix and your favorite virus scanner. So make sure you have a virus scanner already installed and keep it up-to-date.

Now please take a look at the /etc/amavis/amavisd.conf (FreeBSD 5.3: /usr/local/etc/amavisdconf) file. All configuration you find here are well explained and should be easy to edit. Make sure that you configure at least one virus scanner in the first part of the file and have the following options set:

Ubuntu: /etc/amavis/conf.d/50-user

@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);

@lookup_sql_dsn = ( ['DBI:mysql:database=pmwh2;host=localhost;port=3306', 'pmwh2_user', 'pmwh2_password'] );

$sql_select_policy = 'SELECT *,amavis_users.id FROM amavis_users,amavis_policy
  WHERE (amavis_users.policy_id=amavis_policy.id) AND (amavis_users.email IN (%k)) ORDER BY amavis_users.priority DESC';
$sql_select_white_black_list = 'SELECT wb FROM amavis_wblist,amavis_mailaddr
  WHERE (amavis_wblist.rid=?) AND (amavis_wblist.sid=amavis_mailaddr.id) AND (amavis_mailaddr.email IN (%k)) ORDER BY
  amavis_mailaddr.priority DESC';

@storage_sql_dsn = ( ['DBI:mysql:database=amavis_storage;host=localhost;port=3306', 'amavis', 'amavis'] );

$virus_quarantine_method='sql:';
$spam_quarantine_method='sql:';
$banned_files_quarantine_method='sql:';
$bad_header_quarantine_method='sql:';

To get clamav, a free virus scanner, run the following command on

bash #> sudo apt-get install clamav clamav-freshclam clamav-testfiles clamav-daemon clamav-base spamassassin

Give systemuser "clamav" permissions to scan amavis spool files

bash #> sudo usermod -G amavis clamav

Restart the amavisd:

bash #> sudo /etc/init.d/amavis restart

amavisd-new has a lot, lot more options to use other scanners. Most of them are "free" for uncommercial use, but closed source. So make up your mind if you want them or not. If you decide to install another, you just have to uncomment the designated part in amavisd.conf - in most cases.

The last thing to do is tell Postfix that you want to have all your emails scanned. First edit /etc/postfix/main.cf and add the following line:

bash #> sudo postconf -e 'content_filter = smtp-amavis:[127.0.0.1]:10024'

Now you have told Postfix that you want to use the "content_filter = smtp-amavis:[127.0.0.1]:10024" transport method on all emails. You may also consider setting "soft_bounce = yes" temporarily to make sure emails do not get bounced when something goes wrong. Emails will stay in your mail queue if you set this to true.

Finally tell Postfix what you mean by "content_filter = smtp-amavis:[127.0.0.1]:10024". Add this section to the

/etc/postfix/master.cf

smtp-amavis unix -      -       n     -       2  smtp
   -o smtp_data_done_timeout=1200
   -o smtp_send_xforward_command=yes
   -o disable_dns_lookups=yes

127.0.0.1:10025 inet    n       -       n       -       -       smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -o smtpd_client_restrictions=
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks=127.0.0.0/8
  -o strict_rfc821_envelopes=yes
  -o smtpd_error_sleep_time=0
  -o smtpd_soft_error_limit=1001
  -o smtpd_hard_error_limit=1000

Restart Postfix (postfix reload) and you are set. You may want to watch the log file (tail -f /var/log/mail.log) and send a test mail. You should find a line like "X-Virus-Scanned: by AMaViS snapshot-20020222" in the email header. To make sure that your system handles infected emails correctly you may want to attach 'eicar.com'. Eicar is not a virus but a well-known (to virus scanners) signature to test if your virus recognition works. When you send this "infected" email to yourself you will receive an alert from Amavis with subject "VIRUS IN YOUR MAIL".

A last word to explain how Amavis works. Postfix receives your mail and pipes the email as defined in your "vscan" transport method into the amavis tool. Amavis will then use the configured virus scanner to scan all attachments. If the attachments are archives it will even use the archive tools to unpack them. After scanning the files it will contact Postfix on localhost's port 10025 and re-inject the email into the delivery process. But this time it sets the "content_filter" option to nothing and thus bypasses the content scanning this time. You will also see this behaviour in your /var/log/mail.log file. First you will see a "relay=vscan" and then a "relay=local".

Amavisd can also be quite intense. Don't shoot me, but after all it's "just" Perl. ;-) Keep in mind.

In case you are not authorized, make sure you tail the auth.log (probably to be found in /var/log) and also use "postfix check" to see if you have any issues open. So for example, if your permissions are screwed up and postfix can not find something, it will most likely tell you.

Configuration of Postfix mySQL is done. next step (Courier-Maildrop) or next step (without Courier-Maildrop)