Installation:Debian:Postfix

From PMWH2 - PHPMyWebHosting's official wiki
(Redirected from Installation:Postfix)
Jump to: navigation, search
up

Needed Packages

On Debian GNU/Linux you need to install the following packages:

  • postfix (Version 2)
  • postfix-mysql
  • postfix-tls (for Auth-SMTP)
  • postfix-pcre
  • libsasl2
  • libsasl2-modules
  • libsasl2-modules-sql
  • openssl
  • 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 postfix-pcre libsasl2 libsasl2-modules libsasl2-modules-sql openssl

If you want to use amavisd-new, then run

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 local domain]
mydomain = [your local domain]
myhostname = [hostname.your local domain]
mydestination = $myhostname, localhost.$mydomain, $mydomain, $transport_maps
mynetworks = 127.0.0.0/8

# virtual domain and delivery settings
virtual_alias_domains = 
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual_forwardings.cf mysql:/etc/postfix/mysql-virtual_email2email.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual_mailboxes.cf
virtual_mailbox_base = /home/vmail/
# [VMAIL-UID]
virtual_uid_maps = static:1005
# [VMAIL-UID]
virtual_gid_maps = static:1005

# 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_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
# SSL
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/postfix/smtpd.cert
smtpd_tls_key_file = /etc/postfix/smtpd.key

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:

/etc/postfix/mysql-virtual_domains.cf

user = postfix
password = postfix-password
dbname = pmwh
table = postfix-transport
select_field = destination
where_field = domain
hosts = localhost

/etc/postfix/mysql-virtual_forwardings.cf

user = postfix
password = postfix-password
dbname = pmwh
table = postfix-forwardings
select_field = destination
where_field = source
hosts = localhost

/etc/postfix/mysql-virtual_mailboxes.cf

user = postfix
password = postfix-password
dbname = pmwh
table = postfix-users
select_field = maildir
where_field = email
hosts = localhost

/etc/postfix/mysql-virtual_email2email.cf

user = postfix
password = postfix-password
dbname = pmwh
table = postfix-users
select_field = email
where_field = email
hosts = localhost

Make sure to run

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

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)

The second step is to make SASL use the PAM for authentication. 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_hostnames: localhost
sql_user: postfix
sql_passwd: postfix-password
sql_database: pmwh
sql_select: select password from users where email='%u@%r'

Use TLS to encrypt SMTP traffic

An important step is to encrypt the SMTP session. Otherwise the username and password could be transmitted in a very insecure way if the mail client chose to use one of plaintext authentication methods). So I encourage you to encrypt that communication using TLS. TLS is short for Transport Layer Security (RFC2246) and in short terms uses SSL (Secure Socket Layer) which encrypts the mail connection between the road-warrior and the mail server.

First you will need an SSL certificate. If you don't want to pay for one from your favorite trustcenter you can well use a self-signed one. (Personal note: I wonder how paying for something makes it more trusted.) The only drawback: the mail client does not know about your CA (certificate authority) and will spit out a warning to the user. Either tell the users to ignore the warning or let them install the certificate on their computers.

For a certificate that is valid for one year for the hostname smtp.domain.tld you would type this:

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

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]:DE
State or Province Name (full name) [Some-State]:Oldenburg
Locality Name (eg, city) []:Oldenburg
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ladse.de PHPMyWebHosting
Organizational Unit Name (eg, section) []:Master of Disaster
Common Name (eg, YOUR name) []:smtp.domain.tld
Email Address []:postmaster@domain.tld

After a short moment you will get two files: "smtpd.key" (the private key file) and "smtpd.cert" (the certificate). Move these two files into /etc/postfix.

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

chmod o= /etc/postfix/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:

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

Give systemuser "clamav" permissions to scan amavis spool files

bash #> usermod -G amavis clamav

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

/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