Using nginx-embedded-perl module on the same server as the imap/pop proxy as the auth backend
Note: this solution will block entire nginx worker when reading user information from DB and therefore not recommended for real use.
Note2: This solution is being used at at ISP with 35000+ mailboxes for almost 2 years now fine. If you want shameful plug, the ISP is Worldsoft (http://worldsoft.info)
Start with the configuration from [NginxImapProxyExample]. For detail information about different configuration parameters, see the [NginxMailCoreModule] page.
- Configure nginx with embedded perl and mail
- /configure --with-http_perl_module --with-mail
nginx/conf/nginx.conf
user nobody;
worker_processes 1;
error_log logs/error.log info;
pid logs/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
http {
perl_modules perl/lib;
perl_require mailauth.pm;
server {
location /auth {
perl mailauth::handler;
}
}
}
mail {
auth_http 127.0.0.1:80/auth;
pop3_capabilities "TOP" "USER";
imap_capabilities "IMAP4rev1" "UIDPLUS";
server {
listen 110;
protocol pop3;
proxy on;
}
server {
listen 143;
protocol imap;
proxy on;
}
}
The ultrafast nginx based authentifier. nginx/perl/lib/mailauth.pm
1
2 package mailauth;
3 # Author: Atif Ghaffar
4 # version 1.0
5 use nginx;
6 use DBI;
7 my $dsn="DBI:mysql:database=DBNAME;host=HOSTNAME";
8 our $dbh=DBI->connect_cached($dsn, 'dbusername', 'dbpass', {AutoCommit => 1});
9 our $sth=$dbh->prepare("select password,mail_server from mailaccounts where username=? limit 1");
10
11 our $auth_ok;
12
13
14 our $mail_server_ip={};
15 our $protocol_ports={};
16 $mail_server_ip->{'mailhost01'}="192.168.1.22";
17 $mail_server_ip->{'mailhost02'}="192.168.1.33";
18 $protocol_ports->{'pop3'}=110;
19 $protocol_ports->{'imap'}=143;
20
21 sub handler {
22 my $r = shift;
23 $auth_ok=0;
24
25 $sth->execute($r->header_in("Auth-User"));
26 my $hash=$sth->fetchrow_hashref();
27 # assuming that the query results password and mail_server
28 # assuming that the password is in crypt format
29
30 if (crypt($r->header_in("Auth-Pass"), $hash->{'password'}) eq $r->header_in("Auth-Pass")){
31 $auth_ok=1;
32 }
33 if ($auth_ok==1){
34 $r->header_out("Auth-Status", "OK") ;
35 $r->header_out("Auth-Server", $mail_server_ip->{$hash->{'mail_server'}});
36 $r->header_out("Auth-Port", $protocol_ports->{$r->header_in("Auth-Protocol")});
37 } else {
38
39 $r->header_out("Auth-Status", "Invalid login or password") ;
40 }
41
42
43 $r->send_http_header("text/html");
44
45
46 return OK;
47 }
48
49 1;
50 __END__
