NGINX Mail Proxy mit IMAP, POP3 und SMTP

Für bestimmte Aufgaben ist es notwendig einen Mail-Proxy zu konfigurieren. Dies lässt sich relativ einfach mit einem NGINX-Server und dem dazugehörigen Mail-Modul erledigen. Im Video zeige ich den ganzen Konfigurationsprozess.

Die Quellen zu den Links im Video finden Sie hier

NGINX Mail Proxy mit IMAP, POP3 und SMTP
Dieses Video auf YouTube ansehen.
Mit dem abspielen des Videos stimmst du den Datenschutzrichtlinien (siehe Datenschutz) von Youtube zu.

NGINX-Pakete die notwendig sind

Debian / Ubuntu basierte Systeme:
apt install nginx-full nginx-common libnginx-mod-mail php-fpm certbot

Redhat / CentOS basierte Systeme:
yum install epel-release
yum install nginx nginx-mod-mail

nginx.conf

mail {
  auth_http  localhost/auth.php;
  pop3_capabilities  "TOP"  "USER";
  imap_capabilities  "IMAP4rev1"  "UIDPLUS";

  server {
    listen     110;
    protocol   pop3;
    proxy      on;
  }

  server {
    listen     25;
    protocol   smtp;
    proxy      on;
  }

  server {
    listen     143;
    protocol   imap;
    proxy      on;
  }

auth.php

<?php
/*
NGINX sends headers as
Auth-User: somuser
Auth-Pass: somepass
On my php app server these are seen as
HTTP_AUTH_USER and HTTP_AUTH_PASS
*/
if (!isset($_SERVER["HTTP_AUTH_USER"] ) || !isset($_SERVER["HTTP_AUTH_PASS"] )){
  fail();
}

$username=$_SERVER["HTTP_AUTH_USER"] ;
$userpass=$_SERVER["HTTP_AUTH_PASS"] ;
$protocol=$_SERVER["HTTP_AUTH_PROTOCOL"] ;

// default backend port
$backend_port=110;

if ($protocol=="imap") {
  $backend_port=143;
}

if ($protocol=="smtp") {
  $backend_port=25;
}

// NGINX likes ip address so if your
// application gives back hostname, convert it to ip address here
$backend_ip["mailhost01"] ="192.168.1.22";
$backend_ip["mailhost02"] ="192.168.1.33";

// Authenticate the user or fail
if (!authuser($username,$userpass)){
  fail();
  exit;
}

// Get the server for this user if we have reached so far
$userserver=getmailserver($username);

// Get the ip address of the server
// We are assuming that you backend returns hostname
// We try to get the ip else return what we got back
$server_ip=(isset($backend_ip[$userserver]))?$backend_ip[$userserver] :$userserver;

// Pass!
pass($server_ip, $backend_port);

//END

function authuser($user,$pass){
  // password characters encoded by nginx:
  // " " 0x20h (SPACE)
  // "%" 0x25h
  // see nginx source: src/core/ngx_string.c:ngx_escape_uri(...)
  $pass = str_replace('%20',' ', $pass);
  $pass = str_replace('%25','%', $pass);

  // put your logic here to authen the user to any backend
  // you want (datbase, ldap, etc)
  // for example, we will just return true;
  return true;
}

function getmailserver($user){
  // put the logic here to get the mailserver
  // backend for the user. You can get this from
  // some database or ldap etc
  // dummy logic, all users that start with a,c,f and g get mailhost01
  // the others get mailhost02
    return "mailhost01";
}

function fail(){
  header("Auth-Status: Invalid login or password");
  exit;
}

function pass($server,$port){
  header("Auth-Status: OK");
  header("Auth-Server: $server");
  header("Auth-Port: $port");
  exit;
}

SSL-Configuration in der nginx.conf

  starttls  on; ## enable STARTTLS for all mail servers
  ssl_prefer_server_ciphers  on;
  ssl_protocols              TLSv1 SSLv3;
  ssl_ciphers                HIGH:!ADH:!MD5:@STRENGTH;
  ssl_session_cache          shared:TLSSL:16m;
  ssl_session_timeout        10m;
  ssl_certificate            /folder/to/ssl/fullchain.pem;
  ssl_certificate_key        /folder/to/ssl/private/privkey.pem;
  ssl_dhparam                /etc/ssl/certs/dhparam.pem 

NGINX-Kompilierung mit Modulen für Mail

./configure --with-mail --with-mail_ssl_module