the perdition and nginx imap proxies

29
The Perdition and NGINX IMAP Proxies UKUUG Spring 2010 Conference Manchester, UK March 2010 Jan-Piet Mens mens.de

Upload: jpmens

Post on 14-Jan-2015

20.687 views

Category:

Technology


18 download

DESCRIPTION

 

TRANSCRIPT

Page 1: The Perdition and NGINX IMAP Proxies

The Perdition and NGINX IMAP Proxies

UKUUG Spring 2010 Conference Manchester, UK

March 2010

Jan-Piet Mens mens.de

Page 2: The Perdition and NGINX IMAP Proxies

Overview

IMAP servers: one, two, .... lots How an IMAP proxy works Perdition NGINX Summary.

Page 3: The Perdition and NGINX IMAP Proxies

Single server

User configures IMAP server name in MUA MUA connects to IMAP server Expansion means Larger server

Multiple servers Distribute accounts

IMAP

serverclient

Page 4: The Perdition and NGINX IMAP Proxies

Multiple servers

More than one server? Users "know" server names Non-transparent to users User "freddy" server1?

User "paula" server3?

Use DNS CNAMES to associate users to servers

client

IMAPserver

a-f.example.net

IMAPserver

g-m.example.net

IMAPserver

n-z.example.net

Page 5: The Perdition and NGINX IMAP Proxies

How a proxy works

Client connects to proxy (in) Proxy retrieves username 01 login [email protected] secret

Proxy looks up username in "map" Optional: authentication

Optional: translate username

Map returns address of back-end IMAP server Proxy hands off connection to IMAP server (out) and

authenticates with target server

lookup

client

IMAP

server

IMAP

server

IMAP

server

IMAP

proxy

map

Page 6: The Perdition and NGINX IMAP Proxies

Pros and Cons

Advantages Transparent to users: imap.example.net

Replace/maintain back-end servers at will

Migrate users from server1 to serverN

Synthetic usernames on IMAP servers

Different ways of lookup up users (DB, LDAP, etc.)

Consolidate heterogenous brands of IMAP servers

Integrate monitoring to provide access to available IMAP servers only

Central logging

Disadvantages Additional code

Possible single point of failure

Load-balance / heartbeat

Page 7: The Perdition and NGINX IMAP Proxies

IMAP Capabilities

Different servers have different capabilities http://www.iana.org/assignments/imap4-capabilities

Clients typically query them before login List capabilities of your IMAP server $ openssl s_client -connect imap.gmail.com:993 * OK ready for requests 01 capability * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA

XLIST CHILDREN XYZZY

01 OK Thats all she wrote!

Adapt proxy’s CAPABILITY to common denominator

client

IMAPproxy

LotusDomino

Dovecot Cyrus

CAPABILITY

Page 8: The Perdition and NGINX IMAP Proxies

Testing IMAP connections

Telnet / SSL $ telnet imap.example.net imap $ openssl s_client -connect imap.example.net:993

Watch your IMAP connection with IMAP Proxy Server http://www.aboutmyip.com/AboutMyXApp/ImapProxy.jsp $ java -jar IMAPProxy.jar

Page 9: The Perdition and NGINX IMAP Proxies

IMAP Proxies

Perdition NGINX (Engine X)

Others Courier IMAP/POP3 proxy

Cyrus Murder

Dovecot proxy

Page 10: The Perdition and NGINX IMAP Proxies

Perdition

Created by Simon Horman POP3 and IMAP4 One process per connection Can bridge between SSL/TLS and plain back-ends Perdition can authenticate user locally if compiled with

PAM support

Supported lookups: CDB, GDBM, BDB, MySQL, PostgresSQL, LDAP, NIS, regex

Custom C function

Username replacement No support for CRAM-MD5

Page 11: The Perdition and NGINX IMAP Proxies

Perdition configuration

/etc/perdition/perdition.conf bind_address 192.168.1.120 connection_logging log_facility mail log_passwd fail imap_capability IMAP4REV1 UIDPLUS IDLE map_library /lib/libperditionXXX.so map_library_opt "this or that" username_from_database ssl_mode tls_listen,ssl_listen ssl_ca_chain_file /etc/perdition/chain.pem ssl_cert_file /etc/perdition/imap.crt ssl_key_file /etc/perdition/imap.key ssl_cert_verify_depth 0 ssl_listen_ciphers "ALL:!ADH:!NULL:+HIGH: ...

Page 12: The Perdition and NGINX IMAP Proxies

Perdition map: GDBM

Options map_library libperditiondb_gdbm.so.0 map_library_opt /etc/my_popmap.gdbm.db

Data $ cat popmap sue:localhost jane:[email protected]:143 [email protected]:[email protected]

$ makegdbm popmap.gdbm.db < popmap

Page 13: The Perdition and NGINX IMAP Proxies

Perdition map: POSIX regexp

Options map_library libperditiondb_posix_regex.so.0 map_library_opt /etc/popmap.re

Data First match wins

$ cat popmap.re ^john: [email protected]:143 ^[a-m]: server2.example.net (.*)@(.*): $1_$2@localhost

Page 14: The Perdition and NGINX IMAP Proxies

Perdition map: MySQL, PostgresSQL

Options map_library libperditiondb_mysql.so.0 map_library_opt dbhost:dbport:dbname:dbtable:dbuser:\ dbpwd:dbservercol:dbusercol:dbportcol

Data SELECT * FROM users; +------+------------------+------+ | user | servername | port | +------+------------------+------+ | sue | localhost | NULL | | jane | [email protected] | 143 | +------+------------------+------+

Page 15: The Perdition and NGINX IMAP Proxies

Perdition map: LDAP

Options map_library libperditiondb_ldap.so.0 map_library_opt 3:ldap://localhost/o=example.net?\ username,mailhost,port?one?(uid=%s)

Data Attributes returned from search

new username (optional), server, port (optional) perdition.schema has a structural objectclass

dn: uid=jane, o=example.net objectClass: uidObject objectClass: perditionPopmap uid: jane username: s009 mailhost: example.org port: 143

Can use mailHost from inetLocalMailRecipient

Page 16: The Perdition and NGINX IMAP Proxies

Perdition map: custom C

Options map_library libperditiondb_XXYY.so.0 map_library_opt "this or that"

Data Look up user in map

int dbserver_get(const char *key, \ const char *options_str, char **str_return, \ int *len_return)

Initialize / Terminate

int dbserver_init(char *options_str) int dbserver_fini(void)

Make

gcc -shared $(L).c -L/usr/lib -o $(L).so

Page 17: The Perdition and NGINX IMAP Proxies

Perdition map: custom C (2)

Example int dbserver_get(const char *key, const char *opts, char **sret, int *lret) { int status = -2; // not found

if (key && *key && !strcmp(key, "jp")) { char *server = "192.168.1.20"; // [user@]host[:port] *lret = strlen(server) + 1; if ((*sret = calloc(1, *lret)) == NULL) status = -3; // other error else { status = 0; // OK strcpy(*sret, server); } } return (status); }

Page 18: The Perdition and NGINX IMAP Proxies

Case study: Perdition with Lotus Domino

Domino cluster contains n hosts User has mail on >= 2 hosts Custom Perdition database map Retrieves username

Finds user’s back-end IMAP servers (cldbdir.nsf)

Attempts TCP connect

Fails over to backup server

Returns first live server to Perdition

Perdition connects to that IMAP server

LDAP

socket()

client Perdition

Domino Domino Domino

Page 19: The Perdition and NGINX IMAP Proxies

NGINX (Engine X)

Fast HTTP server and reverse proxy, and IMAP/POP3 and SMTP proxy created by Igor Sysoev for rambler.ru

Fixed process pool and non-blocking code Powers WordPress, Github, Ohloh, SourceForge, ... Doesn’t require special database or LDAP schema POST to a URL to do authentication/authorization

via HTTP or UNIX socket

Authorization / authentication Apache, NGINX (HTTP), Lighttpd, ..., thttpd

NGINX Web server is built-in

FastCGI

Embedded Perl

Page 20: The Perdition and NGINX IMAP Proxies

NGINX IMAP/POP3 proxy

Client connects to NGINX NGINX passes authorization request to URL via POST or

UNIX socket

Auth back-end looks up user (optionally password, etc.) Auth back-end determines target server/port Auth back-end passes data back to NGINX NGINX proxies connection to user’s IMAP/POP3

server:port (optionally using new credentials)

NGINXIMAPproxy

IMAP

IMAP

IMAPHTTP process

IMAP client

headers

Page 21: The Perdition and NGINX IMAP Proxies

NGINX authorization

NGINX passes authorization info in HTTP headers HTTP_AUTH_PROTOCOL: imap HTTP_HOST: nano.mens.de HTTP_CLIENT_IP: 192.168.1.154 HTTP_AUTH_METHOD: plain HTTP_AUTH_USER: [email protected] HTTP_AUTH_PASS: seacret HTTP_AUTH_LOGIN_ATTEMPT: 2 HTTP_YY_AUTH: jp-mysecret

Authmethod CRAM-MD5 sets salt and HMAC-MD5 hashed password (need cleartext on server to verify and hand back to NGINX)

HTTP_AUTH_METHOD = cram-md5 HTTP_AUTH_SALT = <[email protected]> HTTP_AUTH_PASS = 1b0864a115d8ae5f3562e3bc7d05cb59

Page 22: The Perdition and NGINX IMAP Proxies

NGINX authorization

Authorization module (e.g. CGI) can Authenticate

Redirect to back-end server

Report failure

Should complete fast

Page 23: The Perdition and NGINX IMAP Proxies

NGINX authorization response

Good response HTTP/1.0 200 OK Auth-Status: OK Auth-Server: 192.168.1.20 Auth-Port: 143 Auth-User: newusername Auth-Pass: newseacret

Bad response HTTP/1.0 200 OK Auth-Status: Invalid login or password Auth-Wait: 5

Don’t forget CGI Content-type

Page 24: The Perdition and NGINX IMAP Proxies

NGINX configuration

nginx.conf error_log logs/error.log info; events { worker_connections 1024; multi_accept on; } mail { auth_http web.example.net:80/nginx/auth.cgi; auth_http_header YY-Auth "jp-mysecret"; imap_auth login plain cram-md5; imap_capabilities "IMAP4rev1" "UIDPLUS" "IDLE"; server { listen *:143; protocol imap; proxy on; proxy_pass_error_message on; } }

Page 25: The Perdition and NGINX IMAP Proxies

Sample NGINX authenticator

Perl CGI my $q = new CGI; my $username = $q->http(’HTTP_AUTH_USER’); my $password = $q->http(’HTTP_AUTH_PASS’);

if ($username eq ’jpm’ && $password eq ’ooh’) { print "Auth-Status: OK\n"; print "Auth-Server: 192.168.1.20\n"; print "Auth-Port: 143\n"; } elsif ($username eq ’sue’) { ... print "Auth-Server: 192.168.3.47\n"; } else { print "Auth-Status: Invalid login or password\n"; print "Auth-Wait: 3\n"; }

print "Content-type: text/plain\n"; print "\n";

Page 26: The Perdition and NGINX IMAP Proxies

Some numbers

Perdition 40,000 users with 2 x Perdition, 9 Courier IMAP

ISP: 10 Perdition, 10 M POP3/IMAP connections/day

NGINX fastmail.fm: 10,000 connections on 10% CPU (3.2 GHZ Xeon)

(FastMail.fm moved from Perdition to NGINX)

Page 27: The Perdition and NGINX IMAP Proxies

Summary

Perdition has built-in database lookups Easier to deploy: no coding

Perdition’s custom functions allow complex setups NGINX as IMAP/POP3 proxy requires custom code Consider using memcached for caching "expensive"

user-lookups

Integrate your monitoring system to influence choice of target IMAP server

Page 28: The Perdition and NGINX IMAP Proxies

Further reading

Perdition http://www.vergenet.net/linux/perdition/

NGINX http://wiki.nginx.org/Main

Alternative DNS Servers, UIT, 2009, Jan-Piet Mens http://mens.de/:/altdns

Page 29: The Perdition and NGINX IMAP Proxies

Thank you

Questions?