Installation:Gentoo:Postfix
Needed Packages
On Debian GNU/Linux you need to install the following packages:
- postfix
- postfix-mysql
- postfix-tls (for Auth-SMTP)
- libsasl-digestmd5-des
- libsasl-gssapi-mit or libsasl-gssapi-heimdal
- libsasl-modules-plain
- libpam-mysql
- sasl-bin
- amavisd-new, zoo, lha, unarj, unzip (if you want virus scanning)
Installation
On Debian GNU/Linux use this command to install all at once:
apt-get install postfix postfix-mysql postfix-tls courier-authdaemon courier-authmysql \ courier-base courier-maildrop courier-pop courier-pop-ssl courier-imap courier-imap-ssl \ libsasl-digestmd5-des libsasl-gssapi-mit libsasl-modules-plain libpam-mysql sasl-bin
If you want to use amavisd-new, put this line to your /etc/apt/sources.list:
deb http://people.debian.org/~hmh/woody/ hmh/amavisd-new/ deb http://people.debian.org/~hmh/woody/ hmh/misc/
and do a
apt-get update && apt-get install amavisd-new unzip
Please create a new systemuser named "vmail" to your system.
On Debian GNU/Linux use this command:
adduser --disabled-password --disabled-login --gecos "Mail user" vmail
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=1005(vmail) gid=1005(vmail) Gruppen=1005(vmail) bash #>
Postfix configuration
First, you have to configure postfix to connect to mysql database which is installed via phpmywebhosting.
First of all an important note: Remember that Postfix runs in a chroot environment. Thus it would not be able to access MySQL's socket file at /var/run/mysqld/mysqld.sock. There are two ways to work around this: Mario Duve (et al) propose an addition to the start section of /etc/init.d/postfix like this:
if [ -e /var/spool/postfix/var/run/mysqld/mysqld.sock ]; then rm /var/spool/postfix/var/run/mysqld/mysqld.sock fi mkdir -p /var/spool/postfix/var/run/mysqld chown mysql /var/spool/postfix/var/run/mysqld ln /var/run/mysqld/mysqld.sock /var/spool/postfix/var/run/mysqld/mysqld.sock
In case of power failure postfix won't start working because the socket of mysql is not valid. To prevent this edit /etc/init.d/postfix and add the above lines in the start section under echo -n "Starting mail transport agent: Postfix". Result is:
case "$1" in start) echo -n "Starting mail transport agent: Postfix" if [ -e /var/spool/postfix/var/run/mysqld/mysqld.sock ]; then rm /var/spool/postfix/var/run/mysqld/mysqld.sock fi mkdir -p /var/spool/postfix/var/run/mysqld chown mysql /var/spool/postfix/var/run/mysqld ln /var/run/mysqld/mysqld.sock /var/spool/postfix/var/run/mysqld/mysqld.sock # see if anything is running chrooted. [...]
Also take care, that postfix is started after mysql. Check it with the following command:
bash #> ls /etc/rc$(grep initdefault /etc/inittab | cut -d: -f2).d/ | grep -E "(postfix|mysql)" S20mysql S20postfix bash #>
If it is like above, everything is alright. If not, delete the links in /etc/rc{runlevel}.d/ and create them new.
Or use the real hostname of the MySQL server instead of "localhost". This way database lookups will be done via UDP instead of UNIX sockets. In this case you will need to comment out the line "skip-networking" in the /etc/mysql/my.cnf file to enable the UDP listener.
Debian: /etc/postfix/main.cf
# basic settings command_directory = /usr/sbin daemon_directory = /usr/lib/postfix program_directory = /usr/lib/postfix myorigin = [your domain] mydomain = [your domain] myhostname = [hostname.your domain] mydestination = $myhostname, localhost.$mydomain, $mydomain, $transport_maps mynetworks = [local IP address range] # virtual domain and delivery settings virtual_mailbox_limit = 10000000 virtual_mailbox_base = /home/vmail/ virtual_uid_maps = static:[VMAIL-UID] virtual_gid_maps = static:[VMAIL-UID] virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-maps.cf alias_maps = mysql:/etc/postfix/mysql-aliases.cf transport_maps = mysql:/etc/postfix/mysql-transport.cf virtual_maps = mysql:/etc/postfix/mysql-virtual.cf # 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) local_recipient_maps = $alias_maps $virtual_mailbox_maps unix:passwd.byname # settings for authenticated SMTP smtpd_sasl_auth_enable = yes smtpd_sasl_local_domain = $myhostname smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_relay_domains smtpd_sasl_security_options = noanonymous broken_sasl_auth_clients = yes # some other options smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) # or FreeBSD ;-) setgid_group = postdrop biff = no # appending .domain is the MUA's job. append_dot_mydomain = no relayhost = mailbox_size_limit = 0 recipient_delimiter = + message_size_limit = 10000000
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:
Here is the following set of files in a tar.gz. A little perl script called fill.pl will ask you for the needed values and fill the files with the correct values. To use it, just do
bash #> tar xvfz portfix-mysql.tar.gz bash #> cd postfix bash #> ./fill.pl What is the name of the database admin user? [postfix database name, e.g. vmail] What is his password? [another secret from above] What is the database hostname? localhost [or IP address] bash #> cp mysql-* /etc/postfix/ bash #>
It creates the files following in the next chapter. Just copy them to your /etc/postfix/ directory and restart postfix using
/etc/init.d/postfix restart
Debian: /etc/postfix/mysql-virtual-maps.cf
user = [database admin user] password = [database admin password] dbname = provider table = users select_field = maildir where_field = email additional_conditions = and postfix = 'y' hosts = [database server hostname]
Debian: /etc/postfix/mysql-aliases.cf
user = [database admin user] password = [database admin password] dbname = provider table = alias select_field = destination where_field = alias hosts = [database server hostname]
Debian: /etc/postfix/mysql-transport.cf
user = [database admin user] password = [database admin password] dbname = provider table = transport select_field = destination where_field = domain hosts = [database server hostname]
Debian: /etc/postfix/mysql-virtual.cf
user = [database admin user] password = [database admin password] dbname = provider table = virtual select_field = destination where_field = email hosts = [database server hostname]
Now we configure postfix to understand authenticated SMTP.
Imagine your users fetch their email using POP3. Now they need a way to send mails via your mail server. For security reasons Postfix allows users in the local (=trusted) network to send emails. (You obviously want this security if you don't want to work as an open relay for spammers.) My suggestion is that your users use authenticated SMTP. This means that their email clients provide a username and password to the mail server to make them "trusted". Most email cilents have this feature included.
Setting authenticated SMTP isn't that complicated. The only pitfall is that Debian runs Postfix in a chroot'ed environment by default. ("chroot'ed" means that Debian pretends that the "/var/spool/postfix" directory is pretended to be "/" - so Postfix cannot move out of this secure subdirectory. Anyone who finds a security problem and messes with Postfix can only do harm to that very subdirectory and not screw your whole system)
There may be different ways to use authentication with SMTP. I decided to use PAM (pluggable authentication modules). The authentication configuration is usually stored in "/etc/pam.d". As Postfix runs chroot'ed the configuration is searched for in "/var/spool/postfix/etc/pam.d". Just go there and put the following lines in a file called "smtp" (the backslashes show that all declarations are to be written in a single line):
Debian: /var/spool/postfix/etc/pam.d/smtp
auth required pam_mysql.so user=[database admin user] passwd=[database admin password] host=[database server hostname] \ db=provider table=users usercolumn=email passwdcolumn=password crypt=1 account sufficient pam_mysql.so user=[database admin user] passwd=[database admin password] host=[database server hostname] \ db=provider table=users usercolumn=email passwdcolumn=password crypt=1
For security reasons we change the ownership and permissions of that file. So it only can be read by root and postfix:
bash #> chown root:postfix /var/spool/postfix/etc/pam.d/smtp bash #> chmod 660 /var/spool/postfix/etc/pam.d/smtp bash #>
The second step is to make SASL use the PAM for authentication. This is easy. Just put the following line in
/etc/postfix/sasl/smtpd.conf
pwcheck_method: pam
Third and last step: copy the /lib/security/pam_mysql.so to /var/spool/postfix/lib/security to make it accessible for Postfix (chroot'ed, remember?):
bash #> mkdir -p /var/spool/postfix/lib/security/ bash #> cp /lib/security/pam_mysql.so /var/spool/postfix/lib/security/
(I'm not a PAM guru. If the PAM configuration can be simplified please tell me. I was glad they worked the way they are.)
- 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:
Debian: /etc/amavis/amavisd.conf
$forward_method = 'smtp:127.0.0.1:10025' $inet_socket_port = 10024;
To get clamav, a free virus scanner, run the following command on
bash #> apt-get install clamav clamav-freshclam clamav-testfiles clamav-daemon clamav-base spamassassin
Restart the amavisd:
bash #> /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:
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
Debian: /etc/postfix/master.cf
smtp-amavis unix - - n - 2 smtp -o smtp_data_done_timeout=1200 -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
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.
- Open issues
If you have been successful in one of the following issues then please tell us so we can include the parts here:
- Enforcing quotas during delivery
- how to integrate postgrey with the Debian/GNU installation