Go to content Go to navigation Go to search

9. Roundcube webmail

August 3rd, 2010 by jde

Postfix Tutorial – Step 9

Roundcube webmail

Roundcube is a modern webmail GUI with sieve support.

Install Roundcube webmail:

# cd /usr/ports/mail/roundcube
# make install clean

Options for roundcube 0.4.b,1 

[X] MYSQL     Use MySQL backend
[ ] PGSQL     Use PostgreSQL backend
[ ] SQLITE    Use SQLite backend
[X] SSL       Enable SSL support (imaps or google spellcheck)
[X] LDAP      Enable LDAP support (address book)
[X] PSPELL    Enable PSpell support (internal spellcheck)
[X] NSC       Install network spellchecker
[X] AUTOCOMP  Enable autocomplete in login form

Connect to mysql, create a user and a database for rundcube. Then run the initial sql script:
Remember to replace username and password with something else.

 # mysql -u root -p
Enter password:

mysql> CREATE DATABASE roundcubemail;
mysql> GRANT ALL PRIVILEGES ON roundcubemail.* TO username@localhost IDENTIFIED BY 'password';
mysql> FLUSH PRIVILEGES;
mysql> USE roundcubemail;
mysql> SOURCE /usr/local/www/roundcube/SQL/mysql.initial.sql

Open the Roundcube database configuration file /usr/local/www/roundcube/config/db.inc.php and edit the database connection string:

$rcmail_config['db_dsnw'] = 'mysql://username:password@localhost/roundcubemail';

Open the Roundcube main configuration file /usr/local/www/roundcube/config/main.inc.php and activate the sieve plugin:

$rcmail_config['plugins'] = array('managesieve');

This plugin presents itself in the GUI with a ‘Filter’ tab under “Personal settings”.

The login form includes a ‘Server’ field. You can remove it by setting ‘default_host’:

$rcmail_config['default_host'] = 'mail.example.com';

8. Server-side mail filtering

August 3rd, 2010 by jde

Postfix Tutorial – Step 8

Server-side mail filtering

Many people maintain a set of filtering rules in their email clients. Incoming emails from grandma are automatically moved to the ‘family’ folder, and emails from your ex is moved to ‘trash’. Whatever suits your needs. This is a neat way of keeping things in order… but only until you start reading mail on your smart phone, netbook or use a webmail. With server side filters, no matter where you are or what gadget you use to fetch your mail, the same filters are applied.

Dovecot comes with a Sieve plugin to make this happen.

At the end of /usr/local/etc/dovecot.conf you will find a plugin section. Within that section locate the commented section about Sieve and add this line:

sieve_global_path=/usr/local/virtual/globalsieverc

In the protocol lda section uncomment this line (or add it if it’s not there):

mail_plugins = sieve

The globalsieverc file is a set of global filtering rules which applies to all users until they create their own rules.

Create /usr/local/virtual/globalsieverc with the following content:

require ["fileinto"];
# Move spam to spam folder
if header :contains "X-spam-flag" ["YES"] {
  fileinto "spam";
  stop;
}

Make the file readable by the vmail user:

# chown vmail /usr/local/virtual/globalsieverc

Restart Dovecot:

# /usr/local/etc/rc.d/dovecot restart
Stopping dovecot.
Waiting for PIDS: 56704.
Starting dovecot.

!!NOTE!! The name of the folder is case sensitive and if the folder does not exist, Dovecot will not fail or report it in the log. The folder is just created.

Send a spam mail to one of your accounts. It should be delivered in the spam folder of the account.

# sendmail my@examplemail.com < gtube.txt

Watch the dovecot-deliver.log:

Info: sieve: msgid=<GTUBE1.1010101@example.net>: stored mail into mailbox 'spam'

7. Spam and virus detection

August 1st, 2010 by jde

Postfix Tutorial – Step 7

Spam and virus detection

AMaViS (A Mail Virus Scanner) gives you protection against spam through Spamassassin and virus protection with Clamav (optional):

Let’s install AMaViS:

# cd /usr/ports/security/amavisd-new/
# make install clean

Options for amavisd-new 2.6.4_7,1

[X] BDB           Use BerkeleyDB for nanny/cache/snmp
[ ] SNMP          Install amavisd snmp subagent
[ ] SQLITE        Use SQLite for lookups
[X] MYSQL         Use MySQL for lookups/logging/quarantine
[ ] PGSQL         Use PgSQL for lookups/logging/quarantine
[ ] LDAP          Use LDAP for lookups
[ ] SASL          Use SASL authentication
[X] MILTER        Sendmail milter support
[X] SPAMASSASSIN  Use mail/p5-Mail-SpamAssassin
[ ] P0F           Passive operating system fingerprinting
[ ] ALTERMIME     Use AlterMime for defanging/disclaimers
[X] FILE          Use newer file(1) utility from port
[ ] RAR           RAR support with archivers/rar
[X] UNRAR         RAR support with archivers/unrar
[X] ARJ           ARJ support with archivers/arj
[ ] UNARJ         ARJ support with archivers/unarj
[X] LHA           LHA support with archivers/lha
[X] ARC           ARC support with archivers/arc
[ ] NOMARCH       ARC support with archivers/nomarch
[X] CAB           CAB support with archivers/cabextract
[X] RPM           RPM support with archivers/rpm2cpio
[X] ZOO           ZOO support with archivers/zoo
[ ] UNZOO         ZOO support with archivers/unzoo
[X] LZOP          LZOP support with archivers/lzop
[X] FREEZE        FREEZE support with archivers/freeze
[X] P7ZIP         P7ZIP support with archivers/p7zip
[X] MSWORD        Ms Word support with textproc/ripole
[ ] TNEF          Add external tnef decoder converters/tnef

Some time during the installation, you will also be prompted for SpamAssassin options:

Options for p5-Mail-SpamAssassin 3.3.1

[X] AS_ROOT        Run spamd as root (recommended)
[X] SPAMC          Build spamd/spamc (not for amavisd)
[ ] SACOMPILE      sa-compile
[X] DKIM           DKIM/DomainKeys Identified Mail
[X] SSL            Build with SSL support for spamd/spamc
[X] GNUPG          Install GnuPG (for sa-update)
[X] MYSQL          Add MySQL support
[ ] PGSQL          Add PostreSQL support
[X] RAZOR          Add Vipul's Razor support
[ ] SPF_QUERY      Add SPF query support
[ ] RELAY_COUNTRY  Relay country support
[ ] DCC            Add DCC support (see LICENSE)

Install Clamav:

# cd /usr/ports/clamav/
# make install clean

Options for clamav 0.96.1

[X] ARC           Enable arch archives support
[X] ARJ           Enable arj archives support
[X] LHA           Enable lha archives support
[X] UNZOO         Enable zoo archives support
[X] UNRAR         Enable rar archives support
[X] LLVM          Enable JIT Bytecode compiler
[ ] MILTER        Compile the milter interface
[ ] LDAP          libmilter was built with LDAP
[ ] ICONV         Enable ICONV support
[ ] STDERR        Print logs to stderr instead of stdout
[ ] EXPERIMENTAL  Build experimental code

In /etc/rc.conf:

amavis_milter_enable="YES"
amavisd_enable="YES"
clamav_clamd_enable="YES"
clamav_freshclam_enable="YES"
spamd_enable="YES"

Run sa-update to download configuration files (rules, scores, etc,) for SpamAssassin (Read more…), then start AMaViS and make sure it starts up correctly:

# rehash
# sa-update
# /usr/local/etc/rc.d/amavisd start
Starting amavisd.
# ps -ax | grep amavis
55743  ??  Ss     0:02.77 amavisd (master) (perl)
55744  ??  I      0:00.01 amavisd (virgin child) (perl)
55745  ??  I      0:00.01 amavisd (virgin child) (perl)
# netstat -p tcp -a | grep 10024
tcp4       0      0 localhost.10024        *.*                    LISTEN

Note that the startup command for AMaViS may fail silently, so if you don’t see it listening consult /var/log/maillog.

In /usr/local/etc/postfix/main.cf add these lines:

# Amavis content filtering
content_filter=smtp-amavis:[127.0.0.1]:10024
receive_override_options=no_address_mappings

In /usr/local/etc/postfix/master.cf add these lines:

smtp-amavis unix -       -       n       -       2       smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20
127.0.0.1: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
    -o local_header_rewrite_clients=

Reload Postfix:

# postfix reload
postfix/postfix-script: refreshing the Postfix mail system

Add clamav user to the vscan group in /etc/group:

Find these lines:

vscan:*:110:
clamav:*:106:

Change them to:

vscan:*:110:clamav
clamav:*:106:vscan

Start clamav (be patient, it may take a while before you get the prompt back):

# /usr/local/etc/rc.d/clamav-clamd start
Starting clamav_clamd.
LibClamAV Warning: **************************************************
LibClamAV Warning: ***  The virus database is older than 7 days!  ***
LibClamAV Warning: ***   Please update it as soon as possible.    ***
LibClamAV Warning: **************************************************

You can ignore this warning since clamav-freshclam will take care of that from now on. Let’s start it:

# /usr/local/etc/rc.d/clamav-freshclam start

Open /usr/local/etc/amavisd.conf and locate the @lookup_sql_dsn section. Edit it so that it looks like this:

@lookup_sql_dsn = (
     ['DBI:mysql:database=postfix;host=127.0.0.1;port=3306',
      'postfix',
      'password']);

$sql_select_policy = 'SELECT domain as name FROM domain WHERE CONCAT("@",domain) IN (%k)';

Also locate the @av_scanners section, and make sure clamav is uncommented:

### http://www.clamav.net/
['ClamAV-clamd',
   \&ask_daemon, ["CONTSCAN {}\n", "/var/run/clamav/clamd.sock"],
   qr/\bOK$/m, qr/\bFOUND$/m,
   qr/^.*?: (?!Infected Archive)(.*) FOUND$/m ],

Also tell AMaViS to let spam pass … It will be deliveret to the users inbox and then each user can set their own “Sieve” options.
Whatever you do, do not set $final_spam_destiny to D_BOUNCE. Spam is never sent from the spammers own email address, to you’ll just end up annoying (innocent) people.

$final_spam_destiny = D_PASS;
$spam_quarantine_to = undef;

Restart AMaViS:

# /usr/local/etc/rc.d/amavisd restart
Stopping amavisd.
Waiting for PIDS: 55743 55744 55745, 55743.
Starting amavisd.

Test AMaViS spam detection with this message: spamassassin.apache.org/gtube/gtube.txt
Replace my@examplemail.com with an existing mail account on your server.

# fetch http://spamassassin.apache.org/gtube/gtube.txt
# sendmail my@examplemail.com < gtube.txt

Your maillog should look something like this:

postfix/pickup[59535]: 13CF27CD: uid=0 from=<root>
postfix/cleanup[59586]: 13CF27CD: message-id=<GTUBE1.1010101@example.net>
postfix/qmgr[59173]: 13CF27CD: from=<root@examplemail.com>, size=938, nrcpt=1 (queue active)
postfix/smtpd[59590]: connect from unknown[127.0.0.1]
postfix/smtpd[59590]: 28DC17C8: client=unknown[127.0.0.1]
postfix/cleanup[59586]: 28DC17C8: message-id=<GTUBE1.1010101@example.net>
postfix/qmgr[59173]: 28DC17C8: from=<root@examplemail.com>, size=1673, nrcpt=1 (queue active)
amavis[59204]: (59204-01) Passed SPAM, <root@examplemail.com> -> <my@examplemail.com>, Message-ID: <GTUBE1.1010101@example.net>, mail_id: x1U2T7du28CF, Hits: 1005.069, size: 938, queued_as: 28DC17C8, 42885 ms
postfix/smtp[59588]: 13CF27CD: to=<my@examplemail.com>, relay=127.0.0.1[127.0.0.1]:10024, delay=50, delays=0.62/0.26/11/38, dsn=2.0.0, status=sent (250 2.0.0 from MTA([127.0.0.1]:10025): 250 2.0.0 Ok: queued as 28DC17C8)
postfix/qmgr[59173]: 13CF27CD: removed
postfix/pipe[59592]: 28DC17C8: to=<my@examplemail.com>, relay=dovecot, delay=3, delays=0.17/0.27/0/2.6, dsn=2.0.0, status=sent (delivered via dovecot service)
postfix/qmgr[59173]: 28DC17C8: removed
clamav:*:106:

5. SMTP authentication

August 1st, 2010 by jde

Postfix Tutorial – Step 5

SMTP authentication

You need to effectively prevent spammers from abusing your mail server. SASL (Simple Authentication and Security Layer) is an Internet standard method for adding authentication support to connection-based protocols such as SMTP. Dovecot includes a SASL framework that Postfix can use and therefore SMTP authentication has become very easy to setup.

Open /usr/local/etc/postfix/main.cf and set these values:

smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sender_login_maps = mysql:/usr/local/etc/postfix/smtpd_sender_login_maps.cf
smtpd_sender_restrictions =
   reject_sender_login_mismatch
smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   reject_non_fqdn_hostname,
   reject_non_fqdn_sender,
   reject_non_fqdn_recipient,
   reject_unauth_pipelining,
   reject_invalid_hostname,
   reject_rbl_client sbl-xbl.spamhaus.org,
   reject_rbl_client korea.services.net,
   reject_rhsbl_sender dsn.rfc-ignorant.org

The first three lines enables Postfix to use dovecot SASL authentication. Line 7 (smtpd_recipient_restrictions) includes some other restrictions that will make it hard to deliver spam to local accounts. Later we will also add content checking with Spamassassin. Below you’ll find a short explanation for each of the above lines.:

  • smtpd_sasl_type
    Tell postfix to use dovecot for smtp authentication
  • smtpd_sasl_path
    Path to Dovecot SASL socket. Make sure the path is equal to ‘path’ in the ‘socket listen’->’client’ section of dovecot.conf
  • smtpd_sasl_auth_enable
    Tell postfix to enable SASL authentication
  • smtpd_sender_login_maps
    Look up allowed sender addresses in the database
  • smtpd_sender_restrictions
    Restrictions specific to the sender address received with the MAIL FROM command

    • reject_sender_login_mismatch
      Reject sender if the address in MAIL FROM command is not listed in smtpd_sender_login_maps
  • smtpd_recipient_restrictions
    Rules applied right after Postfix receives the `rcpt to` command:
    • permit_mynetworks
      Permit senders in the local network (mynetworks)
    • permit_sasl_authenticated
      Permit authenticated senders (users with a local mail account)
    • reject_unauth_destination
      Reject mail to unknown accounts. Or said in another way: Permit only mail destined to a user of a domain that is a local or virtual domain on this system (mydestination, virtual_alias_domains or virtual_mailbox_domains).
    • reject_non_fqdn_hostname:
      Reject the request when the HELO or EHLO hostname is not in fully-qualified domain form, as required by the RFC.
    • reject_non_fqdn_sender:
      Reject the request when the MAIL FROM address is not in fully-qualified domain form, as required by the RFC
    • reject_non_fqdn_recipient:
      Reject the request when the RCPT TO address is not in fully-qualified domain form, as required by the RFC
    • reject_invalid_hostname:
      Reject the request when the HELO or EHLO hostname syntax is invalid
    • reject_rbl_client sbl-xbl.spamhaus.org:
      Reject the request when the reversed client network address is listed with any A record under the specified rbl domain.
    • reject_rhsbl_sender dsn.rfc-ignorant.org:
      Reject the request when the MAIL FROM domain is listed with any A record under the specified rbl domain. Use it with care… You will most likely miss mail from Exchange servers and/or other people who misconfigured their mail setup.

Create the file /usr/local/etc/postfix/smtpd_sender_login_maps.cf with the following content:

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT username envelope FROM mailbox WHERE username = '%s' UNION SELECT address envelope FROM alias WHERE goto='%s'

This query creates a list of allowed sender addresses which lets the user send mail from the actual account and any address aliases pointing to that account.

Restart Postfix and let’s test to see if SMTP authentication works:

# postfix reload

# telnet localhost smtp
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.server.com ESMTP Postfix
ehlo example.com
250-mail.server.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth plain am5pQG5lcmRnaXJsLmRrAGpuaUBuZXJkZ2lybC5kawBqbjAzMDM3MQ==
235 2.7.0 Authentication successful
quit
221 2.0.0 Bye
Connection closed by foreign host.

For this test you need to Base64-encode the password. Let’s say the account is julia@example.com and the password is love2bicycle. The encoding is then done like this:

# perl -MMIME::Base64 -e \
'print encode_base64("julia\@example.com\0julia\@example.com\0love2bicycle")';
anVsaWFAZXhhbXBsZS5jb20AanVsaWFAZXhhbXBsZS5jb20AbG92ZTJiaWN5Y2xl

If the test above was successfull, you can test your server against mail-abuse.org:

# telnet relay-test.mail-abuse.org

A series of tests are performed and the output shows the result. At the end – if your server has successfully denied all relay attempts – you should see this message:

Tested host banner: 220 mail.example.com ESMTP Postfix
System appeared to reject relay attempts
Connection closed by foreign host.

6. Secure connections with TLS

August 1st, 2010 by jde

Postfix Tutorial – Step 6

Secure connections with TLS

It is extremely important to communicate over a secture (encrypted) connection. Especially if you plan use your mail accounts on wireless public networks (trains, libraries, restaurants, schools etc). If you don’t you are practically shouting out your password to the world.

On this page you’ll see how to setup Dovecot to offer SSL connections (imaps and pops), and TLS for SMTP connections to Postfix.

First generate a self-signed certificate that will be used for both Dovecot and Postfix:

Prepare directories for the certificates…

# cd /etc/mail/
# mkdir CA
# cd CA
# chmod 700 .
# mkdir certs crl newcerts private
# echo "01" > serial
# touch index.txt
# ln -s ../CA demoCA

Configure yourself as a CA (Certificate Authority).

# openssl req -nodes -new -days 3650 -x509 -keyout private/cakey.pem -out cacert.pem
Generating a 1024 bit RSA private key
.++++++
....++++++
writing new private key to 'private/cakey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DK
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Copenhagen
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MeAndMy Server
Organizational Unit Name (eg, section) []:SSL Certs
Common Name (eg, YOUR name) []:mail.example.org
Email Address []:postmaster@example.org

Create a certificate:

# openssl req -nodes -new -x509 -keyout server.key -out server.ucrt
Generating a 1024 bit RSA private key
...................................................................++++++
................++++++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DK
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Copenhagen
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MeAndMy Server
Organizational Unit Name (eg, section) []:SSL Cert
Common Name (eg, YOUR name) []:mail.example.org
Email Address []:postmaster@example.org

Create the certificate request:

# openssl x509 -x509toreq -in server.ucrt -signkey server.key -out server.csr
Getting request Private Key
Generating certificate request

Sign the request with the CA certificate:

# openssl ca -policy policy_anything -days 3650 -out server.crt -infiles server.csr
Using configuration from /etc/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
   Serial Number: 1 (0x1)
   Validity
       Not Before: Jul 31 21:56:02 2010 GMT
       Not After : Jul 28 21:56:02 2020 GMT
   Subject:
       countryName               = DK
       localityName              = Lille Skensved
       organizationName          = NerdGirl
       organizationalUnitName    = SSL Cert
       commonName                = gudinde.nerdgirl.dk
       emailAddress              = jette@nerdgirl.dk
   X509v3 extensions:
       X509v3 Basic Constraints:
           CA:FALSE
       Netscape Comment:
           OpenSSL Generated Certificate
       X509v3 Subject Key Identifier:
           F9:CA:02:AE:EA:A5:74:A9:FE:16:39:54:E7:DA:4D:B2:BC:CF:F1:89
       X509v3 Authority Key Identifier:
           keyid:64:3F:F5:19:E2:D9:00:D9:AB:C3:5B:5A:49:62:0F:39:1D:79:40:42
Certificate is to be certified until Jul 28 21:56:02 2020 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
chmod o= private/cakey.pem

In /usr/local/etc/dovecot.conf find an edit these lines:

protocols = imap imaps managesieve
ssl = yes
ssl_cert_file = /etc/mail/CA/cacert.pem
ssl_key_file = /etc/mail/CA/private/cakey.pem

Restart Dovecot:

# /usr/local/etc/rc.d/dovecot restart
Stopping dovecot.
Starting dovecot.

In /usr/local/etc/postfix/main.cf add these lines:

smtpd_tls_cert_file= /etc/mail/CA/cacert.pem
smtpd_tls_key_file=/etc/mail/CA/private/cakey.pem
smtpd_tls_security_level = may

The smtpd_tls_security_level is set to ‘may’ which means that Postfix does not force it on clients. Users are offered tls as an optional feature.

# postfix reload
postfix/postfix-script: refreshing the Postfix mail system

If Postfix does not announce the TLS option some mail clients will refuse to use TLS. Therefore it is important to check that STARTTLS shows up after the ehlo greeting:

# telnet localhost smtp
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.nerdgirl.dk ESMTP Postfix
ehlo example.com
250-mail.nerdgirl.dk
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
quit
221 2.0.0 Bye
Connection closed by foreign host.

Edit your mail client preferences and set it up to use TLS. You may have to restart it to make the change take effekt. You will probably be informed that the signature isn’t valid, but that’s because you signed it your self.

4. Dovecot – imap/pop3

July 30th, 2010 by jde

Postfix Tutorial – Step 4

Dovecot – imap/pop3

Dovecot is probably already installed, because we added the Dovecot opton for Postfix. For Dovecot I added the MANAGESIEVE option but still dovecot-managesieve was not installed as a dependency :-| So let’s install the sieve ports…

# cd /usr/ports/mail/dovecot-sieve/
# make install clean
# cd ../dovecot-managesieve/
# make install clean

Add the vmail user:

# adduser
Username: vmail
Full name: vmail
Uid (Leave empty for default): 5000
Login group [vmail]:
Login group is vmail. Invite vmail into other groups? []:
Login class [default]:
Shell (sh csh tcsh nologin) [sh]: nologin
Home directory [/home/vmail]: /usr/local/virtual
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]: yes
Lock out the account after creation? [no]:
Username   : vmail
Password   :
Full Name  : vmail
Uid        : 5000
Class      :
Groups     : vmail
Home       : /usr/local/virtual
Home Mode  :
Shell      : /usr/sbin/nologin
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (vmail) to the user database.
Add another user? (yes/no): no
Goodbye!

Create dovecot’s logfiles:

# mkdir /var/log/dovecot
# touch /var/log/dovecot/dovecot-deliver.log
# touch /var/log/dovecot/dovecot.log
# chown -R vmail:vmail /var/log/dovecot

Open /usr/local/etc/dovecot.conf

And make sure you edit these sections:

protocols = imap imaps managesieve

disable_plaintext_auth = no

log_path = /var/log/dovecot/dovecot.log

ssl = no

mail_location = maildir:/usr/local/virtual/%d/%n/Maildir

protocol lda {
  log_path = /var/log/dovecot/dovecot-deliver.log
  auth_socket_path = /var/run/dovecot/auth-master
  postmaster_address = postmaster@yourdomain.com
  #mail_plugins = sieve

  [other stuff here....]
}

auth default {
  mechanisms = plain login
  passdb sql {
    args = /usr/local/etc/dovecot-sql.conf
  }
  userdb static {
    args = uid=5000 gid=5000 home=/usr/local/virtual/%d/%n allow_all_users=yes
  }

  socket listen {
    master {
      path = /var/run/dovecot/auth-master
      mode = 0600
      user = vmail
      #group =
    }
    client {
      path = /var/run/dovecot/auth-client
      mode = 0660
      user = postfix
      group = postfix
    }
  }
}

auth_verbose = yes
auth_debug = yes
auth_debug_passwords = yes

Fiks permissions on the file:

# chgrp vmail /usr/local/etc/dovecot.conf
# chmod g+r /usr/local/etc/dovecot.conf

Create /usr/local/etc/dovecot-sql.conf with the following content:

driver = mysql
connect = host=127.0.0.1 dbname=postfix user=postfix password=secret_password
default_pass_scheme = MD5-CRYPT
password_query = SELECT username as user, password FROM mailbox WHERE username='%u';

Make sure that both postfix and dovecot are enabled in /etc/rc.conf

posfix_enable="YES"
dovecot_enable="YES"

Start them:

# /usr/local/etc/rc.d/postfix start
# /usr/local/etc/rc.d/dovecot start

3. Postfix

July 30th, 2010 by jde

Postfix Tutorial – Step 3

Postfix

Install postfix:

# cd /usr/ports/mail/postfix
# make install clean

Options for postfix 2.7.1,1 

[X] PCRE       Perl Compatible Regular Expressions
[ ] SASL2      Cyrus SASLv2 (Simple Auth. and Sec. Layer)
[X] DOVECOT    Dovecot SASL authentication method
[ ] SASLKRB5   If your SASL req. Kerberos5 select this option
[ ] SASLKMIT   If your SASL req. MIT Kerberos5 select this option
[X] TLS        Enable SSL and TLS support
[ ] BDB        Berkeley DB (choose version with WITH_BDB_VER)
[X] MYSQL      MySQL maps (choose version with WITH_MYSQL_VER)
[ ] PGSQL      PostgreSQL maps (choose with DEFAULT_PGSQL_VER)
[ ] OPENLDAP   OpenLDAP maps (choose ver. with WITH_OPENLDAP_VER
[ ] CDB        CDB maps lookups
[ ] NIS        NIS maps lookups
[ ] VDA        VDA (Virtual Delivery Agent 32Bit)
[ ] TEST       SMTP/LMTP test server and generator
[ ] INST_BASE  Install into /usr and /etc/postfix

In /etc/rc.conf

postfix_enable="YES"

Sendmail is the standard MTA of various UNIX platforms. Since I am using Postfix instead, let’s disable it:

Open /etc/rc.conf and add:

sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"

Also disable some Sendmail-specific daily maintenance routines in your /etc/periodic.conf file (If you don’t have a periodic.conf file in /etc, you must create it by making a copy of /etc/default/periodic.conf):

daily_clean_hoststat_enable="NO"
daily_status_mail_rejects_enable="NO"
daily_status_include_submit_mailq="NO"
daily_submit_queuerun="NO"

Find any running sendmail processes an kill them. Here’s an example:

# ps -ax | grep sendmail
440 ?? Ss 0:56.33 sendmail: accepting connections (sendmail)
444 ?? Is 0:00.81 sendmail: Queue runner@00:30:00 for /var/spool/clientmqueue (sendmail)
# kill -9 440
# kill -9 444

FreeBSD generates daily mails with system information to the root user. You must redirect these mails to an actual mail account:

# cd /etc/mail/
# vim aliases

Find root: me@my.domain and correct the address to reflect one of the email accounts you’ve just created in the mailbox table.

Next you must run the newaliases command. It creates both /etc/aliases.db and /etc/mail/aliases.db and therefore we will convert the one in /etc to a soft link that points to the one in /etc/mail.

# newaliases
# rm /etc/aliases.db
# ln -s /etc/mail/aliases.db /etc/aliases.db

Configure main.cf

# vim /usr/local/etc/postfix/main.cf

Change myhostname and mydomain, and uncomment the rest of the lines show here:

myhostname = example.domain.tld
mydomain = domain.tld
myorigin = $mydomain

mydestination = $myhostname, localhost.$mydomain, localhost
local_recipient_maps = unix:passwd.byname $alias_maps

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

home_mailbox = Maildir/

#Pipe mail per receipient
default_destination_recipient_limit = 1

#Pass incoming mail to dovecot
virtual_transport=dovecot
dovecot_destination_recipient_limit = 1

# configuration related to MySQL.
virtual_alias_maps = mysql:/usr/local/etc/postfix/mysql_virtual_alias_maps.cf
virtual_gid_maps = static:5000
virtual_mailbox_base = /usr/local/virtual
virtual_mailbox_domains = mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf
virtual_mailbox_maps = mysql:/usr/local/etc/postfix/mysql_virtual_mailbox_maps.cf
virtual_mailbox_limit = 51200000
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000

Virtual maps

The three settings: virtual_alias_maps, virtual_mailbox_domains and virtual_mailbox_maps each refer to a file. Create these files in /usr/local/etc/postfix/ with the following content (remember to replace password with the password for the ‘postfix’ database user):

mysql_virtual_alias_maps.cf

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s'

mysql_virtual_domains_maps.cf:

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT description FROM domain WHERE domain='%s'

mysql_virtual_mailbox_maps.cf

user = postfix
password = password
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s'

You can check your maps like this:

# postmap -q nerdgirl.dk mysql:/usr/local/etc/postfix/mysql_virtual_domains_maps.cf
NerdGirl

Make sure that only ‘root’ and the ‘postfix’ user can read the “.cf” files – after all your database password is stored there:

# cd /usr/local/etc/postfix/
# chgrp postfix mysql_virtual_*.cf
# chmod u=rw,g=r,o= mysql_virtual_*.cf

Configure master.cf

Add these lines in /usr/local/etc/postfix/master.cf

dovecot   unix  -       n       n       -       -       pipe
   flags=DRhu user=vmail:vmail argv=/usr/local/libexec/dovecot/deliver -d ${recipient}

The second line must be indended with spaces.

1. Mail setup considerations

July 30th, 2010 by jde

Postfix Tutorial – Step 1

Mail setup considerations

Before you enter the exciting world of MTA, SMTP, IMAP, POP and all there happy little friends you must consider the fact that running a mail server these days is fairly complicated. Sending and receiving email isn’t that hard, but you’ll realize that…

  • an open relay is a bad thing …
  • emails contain virus and spam…
  • sending passwords in clear text is a security risk…
  • it’s nice to have webmail access…
  • filtering rules are better if they are handled by the server and not the client…

Soon you will find your self buried in a pile of software like Postfix, Amavis, Spamassassin and Dovecot, trying to make them all play nicely together.

Consider yourself warned!

Choosing MTA

An MTA (Mail Transfer Agent)  is a program that transfers mail between computers. The MTA works behind the scenes, while the user usually interacts with another program, the mail user agent (MUA).

There’s a lot of MTA’s to choose from. FreeBSD comes with Sendmail, the standard MTA under most variants of the Unix operating system. Sendmail is too old and too complicated and therefore not recommended. There a plenty of others to choose from (Exim, Postfix, Qmail and so on).

As a newbie it is almost impossible to make a sensible choice. My advice to you is: ask your friends or consult homepages and newsgroups via Google. Use words like “MTA”, “MTS” and “review” in your search. When you have an idea of which MTA you want, check for howto’s and tutorials that will help you get started. If you only find little or nothing, you might have to reconsider.

Virtual users vs. local users

A local user, is a user with a physical account on the server. These users are created with `adduser`.

A virtual user does not exist on the server. These users often reside in a database.

If your mailusers don’t need direct access to the server, for example via ssh, there’s no need to clutter the system with homedirs. Physical users is also always a security risk. Only server administrators should have physical accounts.

Virtual users is a bit more difficult to setup initially, but since they don’t have access to the server, you don’t have to worry about them.

There’s a lot of other advantages when using virtual users, that I’m sure you’ll discover along the way.

Email storage – mbox vs. maildir

The mbox format concatenates individual messages together in a single file. Only one process can access the mbox file in read/write mode, which means everyone else has to wait for an update to complete (file locking).

The maildir type stores each message in a file of its own. No locking is required. Multiple processes can use maildirs at the same time.

Both have advantages and disadvantages, but as I understand the maildir format is the safest and fastest. If you want to read more about this topic, make a “mbox vs maildir” -Google search

A third but not widely used method is to store mail in a database. But reading a file is much faster than reading from a database, which is probably the reason people avoid this.

SMTP authentication and TLS

In the “old” days, users only authenticated themselves when receiving mail via POP3/IMAP. As a result of that, POP3 and IMAP has built in support for authentication. But to effectively prevent spammers from relaying through your mailserver, it is necessary also to authenticate when sending mail and thus ensuring that everyone using your system, is a legal user.

But when users login, the information is transported to the server in clear text. Someone “listening” to the communication could grab the information and exploit the user account. This means that any communication between client and server should be enctrypted. For that purpose you can use TLS (Transport Layer Security).

The final setup

I have decided to go with this setup:

MTA Postfix using maildir, virtual users and support for Dovecot, TLS and MySQL
Virtual users Every mail user is stored in the database.
IMAP Dovecot – A feature rich and flexible IMAP and POP3 server
Mail filter Dovecot Sieve plugin
Virus scanner Clamav – A high performance virus scanner
Spam filter Spamassassin – A powerfull spam killer
Webmail Roundcube – A modern webmail client written in PHP

Note: I have an older tutorial with Courier IMAP instead of Dovecot, which is still available here.

2. Database preparations

July 30th, 2010 by jde

Postfix Tutorial – Step 2

Database preparations

This mail setup is based on virtual users stored in a MySQL database. If MySQL is not installed yet, please do so and return to this page when you’re done.

The database is identical to the one I used with my old setup. It works, but some of the fields are not in use any more.

The following queries will create the postfix database and the database user ‘postfix’.

Instead of the command prompt, you may want to use phpMyAdmin for this.

Replace secret_pass with a password of your choice.

CREATE DATABASE postfix;

CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'secret_pass';
GRANT SELECT ON `postfix` . * TO 'postfix'@'localhost';
FLUSH PRIVILEGES;

USE postfix;

CREATE TABLE alias (
 address varchar(255) NOT NULL default '',
 goto text NOT NULL,
 domain varchar(255) NOT NULL default '',
 created datetime NOT NULL default '0000-00-00 00:00:00',
 modified datetime NOT NULL default '0000-00-00 00:00:00',
 active tinyint(4) NOT NULL default '1',
 PRIMARY KEY (address),
 KEY address (address)
) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Aliases';

CREATE TABLE domain (
 domain varchar(255) NOT NULL default '',
 description varchar(255) NOT NULL default '',
 aliases int(10) NOT NULL default '-1',
 mailboxes int(10) NOT NULL default '-1',
 maxquota int(10) NOT NULL default '-1',
 created datetime NOT NULL default '0000-00-00 00:00:00',
 modified datetime NOT NULL default '0000-00-00 00:00:00',
 active tinyint(4) NOT NULL default '1',
 PRIMARY KEY (domain),
 KEY domain (domain)
) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Domains';

CREATE TABLE mailbox (
 username varchar(255) NOT NULL default '',
 password varchar(255) NOT NULL default '',
 name varchar(255) NOT NULL default '',
 maildir varchar(255) NOT NULL default '',
 quota int(10) NOT NULL default '-1',
 domain varchar(255) NOT NULL default '',
 created datetime NOT NULL default '0000-00-00 00:00:00',
 modified datetime NOT NULL default '0000-00-00 00:00:00',
 active tinyint(4) NOT NULL default '1',
 PRIMARY KEY (username),
 KEY username (username)
) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Mailboxes';

Heres an example of how to use the above tables:

The table ‘domain’, contains the domains hosted on your server. Replace domain.tld with one of your own domains:

INSERT INTO domain (domain,description) VALUES ('domain.tld','Description of your choice');

The next step demonstrates how to create a mailuser belonging to the above domain. Replace user@domain.tld, Full name and secret_pass with values of your choice. First you need to generate an MD5-crypt password (MD5 is too easy to crack, and therefore MD5-crypt is better). Dovecot has a function to generate such a password, but since you have not installed Dovecot yet please go to step three, install Postfix (which will also install Dovecot) and then continue from here:

# rehash
# dovecotpw -s MD5-CRYPT -p secret_pass
{MD5-CRYPT}$1$7KAL0/7C$xpACuJX5DarLgFH.tGV6M/

You are now ready to add the new account in the mailbox table:

INSERT INTO mailbox (username,password,name,maildir)
VALUES ('user@domain.tld','{MD5-CRYPT}$1$7KAL0/7C$xpACuJX5DarLgFH.tGV6M/',
'Full name','user@domain.tld/');

The table architecture is mainly a copy of my old setup, and therefore some of the fields are not used any more. But it works as is. Remove unused table fields.