IMAP AuthバックエンドとしてのPerlスクリプトの例

認証バックエンドとして imap/pop プロキシと同じサーバで nginx-embedded-perl モジュールを使用する

注意

この解決方法は、ユーザ情報をDBから読み込む時にNGINXワーカー全体をブロックするため、実際の使用にはお勧めしません。

この解決方法はISPで 35000+ のメールボックスで2年間今でも使われています。恥ずべき広告が必要であれば、そのISPは Worldsoft です(http://www.worldsoft.info)

IMAP プロキシの例の設定から始めます。異なる設定パラメータについての詳細な情報は、ngx_mail_core_moduleドキュメントを見てください。

組み込みのPerlとメールを使ったNGINXの設定

./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;
  }
}

超高速NGINXベースのauthentifier, nginx/perl/lib/mailauth.pm:

package mailauth;
use nginx;
use DBI;
my $dsn="DBI:mysql:database=DBNAME;host=HOSTNAME";
our $dbh=DBI->connect_cached($dsn, 'dbusername', 'dbpass', {AutoCommit => 1});
our $sth=$dbh->prepare("select password,mail_server from mailaccounts where username=? limit 1");

our $auth_ok;
our $mail_server_ip={};
our $protocol_ports={};
$mail_server_ip->{'mailhost01'}="192.168.1.22";
$mail_server_ip->{'mailhost02'}="192.168.1.33";
$protocol_ports->{'pop3'}=110;
$protocol_ports->{'imap'}=143;

sub handler {
  my $r = shift;
  $auth_ok=0;

  $sth->execute($r->header_in("Auth-User"));
  my $hash=$sth->fetchrow_hashref();
  # assuming that the query results password and mail_server
  # assuming that the password is in crypt format

  if (crypt($r->header_in("Auth-Pass"), $hash->{'password'}) eq $r->header_in("Auth-Pass")){
    $auth_ok=1;
  }
  if ($auth_ok==1){
    $r->header_out("Auth-Status", "OK") ;
    $r->header_out("Auth-Server", $mail_server_ip->{$hash->{'mail_server'}});
    $r->header_out("Auth-Port", $protocol_ports->{$r->header_in("Auth-Protocol")});
  } else {
    $r->header_out("Auth-Status", "Invalid login or password") ;
  }

  $r->send_http_header("text/html");

  return OK;
}

1;
__END__
inserted by FC2 system