Installation:Ubuntu:PostfixMY
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)