This documentation is for Dovecot v1.x, see wiki2 for v2.x documentation.

IMAP and POP3 session proxying

NOTE: This page was written quite a long time ago and may not match reality anymore. See here for a newer description of how to use the proxy feature.

Dovecot can act as IMAP and POP3 proxy by forwarding incoming sessions transparently to a administrator-specified mailhost.

Proxy can provide only plaintext authentication to clients, forwarded sessions are non-SSL connections transfering the username and password to the remote server using normal USER + PASS or LOGIN commands.

Another way to do proxying would be to let Dovecot proxy perform the authentication and login to remote server using proxy's password. This should be possible with master password feature, but isn't explained here.

Benefits of IMAP and POP3 session proxying

With IMAP and POP3 session proxying you can scale up your email infrastructure almost infinitely but still having it simple from helpdesk and users point of view. This is accomplished by having multiple mail storage servers but single mail access point to your users. With help of some load balancing appliances you can have multiple Dovecot proxy servers also, add to that multiple replicated SQL servers and your proxy setup is fully fault tolerant.

You can forward sessions to any IMAP/POP3 server, they do not need to be running Dovecot [remark: CAPABILITY list needs some attention, update documentation about that later]. By deploying Dovecot proxy you can bring SSL/TLS and IPv6 features to your existing email infrastructure even if your current IMAP/POP3 server software wouldn't support those.

Performance

Following tests were conducted with Dovecot 1.0-test60.

Non-SSL POP3 session proxying performance of Dell Poweredge 2450, Pentium3 733MHz CPU, 768M RAM, Linux 2.4.28 on Debian Sarge:

"login_process_per_connection = yes" is considered to be more secure, this is because every user has its own proxy process it is not possible to eavesdrop other users sessions in case of some unfortunate bug in login code. Downside of this method is high cost of forking new process for every incoming session. Perdition works like Dovecot with "login_process_per_connection = yes", forking new process for each user.

768M RAM was totally overkill for this workload, 128M would have done the same.

Benchmarking was done with rabid, included in Postal.

Proxying scenarios

There are two possible proxy setups:

Proxying uses three attributes from passdb; proxy with value of Y or N representing whether session should be forwarded or not, host which is a IP-address of a server where session is forwarded and optional destuser which is user's username on destination server.

Proxy only server

On proxy only setup you have one or more Dovecot proxy servers in front of your actual IMAP/POP3 servers. Proxy server is doing only session forwarding, local mail access is disabled. Benefit of this setup is having the session forwarding load away from IMAP/POP3 servers. I also tend to think that this is a bit more secure since mail storage servers do not need to have any direct services open to the Internet.

In this document I assume that Dovecot is installed under /opt/dovecot, by default it is installed under /usr/local when compiling from source. Examples in this document are for MySQL but configs do not differ much with PostgreSQL.

SQL table structure

Create SQL table like

CREATE TABLE proxy (
  user varchar(255) NOT NULL,
  host varchar(16) default NULL,
  destuser varchar(255) default NULL,
  PRIMARY KEY  (user)
);

Insert data to SQL corresponding your users.

Working data could look like this:

mysql> select * from proxy;
+----------+---------------+----------------------+
| user     | host          | destuser             |
+----------+---------------+----------------------+
| john     | 192.168.0.1   |                      |
+----------+---------------+----------------------+
| joe      | 192.168.0.2   | joe@domain.net       |
+----------+---------------+----------------------+

Dovecot configs

Open your preferred editor and save config below as /opt/dovecot/etc/dovecot.conf.

## Dovecot 1.0 configuration file
base_dir = /var/run/dovecot/
protocols = pop3 pop3s imap imaps
disable_plaintext_auth = no
# SSL/TLS settings
# Comment these out if you do not wish to provide SSL secured connections.
ssl_cert_file = /opt/dovecot/etc/mail.domain.net.cert
ssl_key_file = /opt/dovecot/etc/mail.domain.net.key
# Disable SSL/TLS support.
ssl_disable = no
# Login processes
login_dir = /var/run/dovecot/login
login_process_per_connection = no
login_processes_count = 3
# Authentication processes
# If you are not moving mailboxes from host to one on daily basis you can
# use authentication cache pretty safely.
auth_cache_size = 4096
auth_cache_ttl = 7200
# Set limit for MySQL lookup processes
auth_worker_max_count = 30
auth default {
  mechanisms = plain
  # Userdb settings are not used with proxy but there need to be something.
  userdb static {
    args = static uid=5000 gid=5000 home=/dev/null
  }
  passdb sql {
    args = /opt/dovecot/etc/sql.conf
  }
  user = root
  count = 1
}
# eof

Create /opt/dovecot/etc/sql.conf

## SQL passdb configuration
# Database driver: mysql, pgsql
driver = mysql
# Database options
# Only MySQL driver support multiple hosts for now.
connect = host=sqlhost1 host=sqlhost2 dbname=mail user=dovecot password=hush
# Query
password_query = SELECT NULL AS password, host, destuser, 'Y' AS nologin, 'Y' AS nodelay, 'Y' AS proxy, 'Y' AS nopassword FROM proxy WHERE user = '%u'
# eof

Be sure to set 0600 permissions (as root) for sql.conf since it contains password to your SQL!

# chmod 0600 /opt/dovecot/etc/sql.conf

Campus Dovecot proxy

We will proxy user based on the realm they provide with their login.


In newer versions of Dovecot following structure is allowed:

Dovecot

Create /opt/dovecot/etc/sql.conf

## SQL passdb configuration
# Database driver: mysql, pgsql
driver = mysql
# Database options
# Only MySQL driver support multiple hosts for now.
connect = host=sqlhost1 host=sqlhost2 dbname=mail user=dovecot password=hush
# Query
password_query = SELECT NULL AS password, NULL AS destuser, host, 'Y' AS nologin, 'Y' AS nodelay, 'Y' AS nopassword, 'Y' AS proxy FROM proxy_domain WHERE domain = '%d'
# eof

SQL table structure

Create SQL table like

CREATE TABLE proxy_domain (
  domain varchar(255) NOT NULL,
  host varchar(16) default NULL,
  PRIMARY KEY  (domain)
);

Insert data to SQL corresponding your users.

Working data could look like this:

mysql> select * from proxy_domain;
+--------------+---------------+
| domain       | host          |
+--------------+---------------+
| domain1.com  | 192.168.0.1   |
+--------------+---------------+
| domain2.com  | 192.168.0.2   |
+--------------+---------------+


Older versions of Dovecot have to use a workaround:

Dovecot

Create /opt/dovecot/etc/sql.conf

# Database driver
driver = pgsql
# Database options
connect = host=localhost dbname=dovecotdb user=dovecotdba password=dovecotpw
# Query
password_query = SELECT * FROM domain_mapping('%u')
# eof

PostgreSQL

We create a table that will do dynamic mappings between realms and mail servers upon which we will proxy our users.

CREATE SCHEMA dovecot;
CREATE TABLE dovecot.proxy_domain_mappings (
       domain          VARCHAR(32)     NOT NULL,
       mail_server_ip  inet            NOT NULL,
       PRIMARY KEY     (domain)
);

CREATE TYPE dovecot.mapping_t AS (
       password        varchar(8),
       host            varchar(16),
       destuser        varchar(255),
       nologin         varchar(1),
       nodelay         varchar(1),
       proxy           varchar(1)
);

CREATE FUNCTION dovecot.domain_mapping(mail_user varchar(32))
RETURNS SETOF dovecot.mapping_t
AS '
DECLARE
        _mapping   dovecot.mapping_t;
        _destuser  varchar;
        _realm     varchar;
        _password  varchar;
        _nologin   varchar;
        _nodelay   varchar;
        _proxy     varchar;
        _delimiter text;
BEGIN
        _delimiter:= ''@'';
        _password := NULL;
        _nologin  := ''Y'';
        _nodelay  := ''Y'';
        _proxy    := ''Y'';
        SELECT split_part(mail_user,_delimiter,1) INTO _destuser;
        SELECT split_part(mail_user,_delimiter,2) INTO _realm;
        FOR _mapping IN
                SELECT _password, mail_server_ip, _destuser, _nologin, _nodelay, _proxy
                  FROM dovecot.proxy_domain_mappings
                 WHERE domain = lower(_realm)
        LOOP
                RETURN NEXT _mapping;
        END LOOP;
END;
' LANGUAGE PLPGSQL;

Want to do some tests?

dovecotdb=> INSERT INTO dovecot.proxy_domain_mappings VALUES ( 'labo1', '192.168.0.1' );
dovecotdb=> INSERT INTO dovecot.proxy_domain_mappings VALUES ( 'labo2', '192.168.0.2' );
dovecotdb=> SELECT * FROM dovecot.domain_mapping('someuser@labo1');
 password |     host      | destuser | nologin | nodelay | proxy
----------+---------------+----------+---------+---------+-------
          | 192.168.0.1   | someuser | Y       | Y       | Y
(1 row)
dovecotdb=> SELECT * FROM dovecot.domain_mapping('someuser@labo2');
 password |     host      | destuser | nologin | nodelay | proxy
----------+---------------+----------+---------+---------+-------
          | 192.168.0.2   | someuser | Y       | Y       | Y
(1 row)
dovecotdb=> SELECT * FROM dovecot.domain_mapping('someuser@unknownlabo');
 password |     host      | destuser | nologin | nodelay | proxy
----------+---------------+----------+---------+---------+-------
          |               |          |         |         |
(0 rows) 

Start Dovecot proxy

Start proxy by running the Dovecot master process as root.

# /opt/dovecot/sbin/dovecot

IMAP/POP3 server with proxy feature

In this setup you can do session forwarding on your actual IMAP/POP3 servers. When user logs in Dovecot compares local IP-address on user's current connection to user's host attribute in passdb, if those differ user is forwarded to correct mailhost, otherways user is logged to local mailbox.

This model is still a bit unfinished in current code.

SQL table structure

Dovecot configs

Start Dovecot IMAP server

Logging

To be documented...

Technical details

Proxying is done by imap- and pop3-login processes, sharing a lot of code with Dovecot SSL wrapper. Mailbox host is queried through dovecot-auth with single SQL connection per dovecot-auth process.

If you kill or restart Dovecot master process open proxy sessions aren't affected, corresponding login processes will keep running as long as they are handling open sessions.

To flush the authentication cache send HUP signal to dovecot-auth process(es).

HowTo/ImapProxy (last edited 2011-08-18 07:55:24 by chello213047122009)