В одной из знакомых мне фирм, есть требование использовать исключительно рабочую почту для взаимодействия с клиентами и работы внутри организации. Сделано это в основном из-за продажников, что бы они завязывали клиентов на корпоративную почту и в любой момент можно было вынуть любое письмо из длинной переписки. Но не все так просто, в организации есть так называемые продакт-менеджеры некоторым из которых необходимо с определенной периодичностью представляясь не своим именем запрашивать у конкурентов цены на продукцию, при этом даже мобильные телефоны приходится менять раз в пол года. В результате было принято решение нескольким сотрудникам разрешить пользоваться внешней почтой через дополнительный почтовый клиент Outlook Express или почту Windows Live.

Как мне кажется, наше образование давно перестало делать из человека творческую личность и пытается в основном состряпать потребителей пережеванной информации и готовых рефератов. Не смотря на это мы столкнулись с ситуацией, когда один из продакт-менеджеров настроил у себя в Outlook Express личные почты всех близситящих сотрудников, и пока он ходил курить, все эти сотрудники бегали за его компьютер смотреть чего нового им написали. Забава, но нужно исправлять ситуацию, причем кроме мер административного характера, имеет смысл сделать “защиту от дурака”, что бы на будущее не повторять сей печальный опыт. Проще говоря нужно разрешить подключения по протоколам SMTP, POP3 и IMAP к удаленным серверам только с определенным логином.

После не продолжительных поисков я наткнулся в документации к nginx на описание настройки его как прокси сервера для протоколов POP3 и IMAP. Логика работы немного другая, но если немого подправить скрипт аутентификации, то вполне можно использовать его для наших целей.

Настройку будем делать на CentOS 6.4 x64.

1. Аутентификация

Аутентификация в nginx работает по протоколу HTTP, в запросе передаются заголовки Auth-User, Auth-Password и Auth-Protocol, а от скрипта возвращаются заголовки Auth-Status, Auth-Server и Auth-Port. Иначе говоря получив аутентификационные данные скрипт должен вернуть сервер и порт куда нужно подключаться.

Все необходимые данные будут храниться в таблице на сервере MySQL, о настройке расскажу немного позже. Скрипт по имени пользователя находит в этой таблице адреса серверов SMTP, POP3 и IMAP, и возвращает их серверу nginx; если записей в базе нет, то серверу возвращается статус “Invalid login”.

Подключаем репозиторий EPEL:

[root@mailproxy ~]# rpm -ihv http://mirror.yandex.ru/epel/6/x86_64/epel-release-6-8.noarch.rpm

Устанавливаем perl и модули для работы с MySQL:

[root@mailproxy ~]# yum install perl perl-DBI perl-Class-DBI-mysql.noarch

Создаем в каталоге /usr/share/perl5 файл mailauth.pm следующего содержания:

package mailauth;
use nginx;
use DBI;
 
our $dbh=DBI->connect_cached("DBI:mysql:database=nginx;host=localhost", 'nginx', 'nginx', {AutoCommit => 1});
our $sth=$dbh->prepare("select pop3_server,smtp_server,imap_server from mailaccounts where username=? limit 1");
 
our $protocols = {
'smtp' => {'port'=>25, 'column'=>'smtp_server'},
'pop3' => {'port'=>110, 'column'=>'pop3_server'},
'imap' => {'port'=>143, 'column'=>'imap_server'}};
 
sub handler {
    my $r = shift;
    $sth->execute($r->header_in("Auth-User"));
    if ($sth->rows) {
        my $result=$sth->fetchrow_hashref();
        my $port=$protocols->{$r->header_in("Auth-Protocol")}->{'port'};
        my $server=$result->{$protocols->{$r->header_in("Auth-Protocol")}->{'column'}};
        if ($server && $port) {
            print log_file "server and port ok\n";
            $r->header_out("Auth-Status", "OK") ;
            $r->header_out("Auth-Server", $server);
            $r->header_out("Auth-Port", $port);
        } else {
            $r->header_out("Auth-Status", "Invalid upstream server or port");
        }
    } else {
        $r->header_out("Auth-Status", "Invalid login");
    }
    $r->send_http_header("text/html");
    return OK;
}
 
1;
__END__

2. Настройка базы данных

Настраивать мы будем обычный MySQL-сервер, который в недавнем прошлом из-за цепочки перепродаж перекочевал в MariaDB. Мне не так легко перестроится на новое название, поэтому называть его буду по старинке MySQL, а часть команд юзать относящихся уже к MariaDB.

Устанавливаем MySQL-сервер, а затем добавляем в автозапуск и запускаем:

[root@mailproxy ~]# yum install mysql-server
[root@mailproxy ~]# service mysqld start
[root@mailproxy ~]# chkconfig mysqld on

Делаем базовую настройку при помощи скрипта mysql_secure_installation, скриптик простой, но сильно упрощающий жизнь. Со всем соглашаемся и обязательно меняем рутовый пароль MySQL-сервера.

[root@mailproxy ~]# mysql_secure_installation
Set root password? [Y/n] Y
New password:
Re-enter new password:
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Reload privilege tables now? [Y/n] Y

Создаем базу данных nginx, с пользователем nignx и паролем тоже nginx:

[root@mailproxy ~]# mysql -uroot -p
Enter password:
mysql> create database nginx;
mysql> grant all privileges on nginx.* to 'nginx'@'localhost' identified by 'nginx';
mysql> flush privileges;

Создаем таблицу mailaccounts:

mysql> use nginx;
mysql> create table mailaccounts (`username` text, `pop3_server` text, `smtp_server` text, `imap_server` text) engine=InnoDB;

Для работы скрипта нам нужно забить в таблицу данные – имя пользователя и адреса серверов на которые будет переадресовываться пользователь. Для примера я беру свою учетку alsigned@mail.ru и соответствующие IP-адреса серверов mail.ru.

mysql> insert into mailaccounts (`username`, `pop3_server`, `smtp_server`, `imap_server`) values ('alsigned', '94.100.180.74', '94.100.177.1', '217.69.139.90');

Это действие мы повторяем для каждого пользователя, кому мы предоставляем доступ к внешней электронной почте, в моем случае это все-ничего 5 человек. Выходим из консоли MySQL:

mysql> quit;

3. Настройка NGINX

Подключаем репозиторий CentAlt и ставим nginx:

[root@mailproxy ~]# rpm -ihv http://centos.alt.ru/pub/repository/centos/6/x86_64/centalt-release-6-1.noarch.rpm
[root@mailproxy ~]# yum install nginx

Приводим конфигурационный файл /etc/nginx/nginx.conf к следующему виду:

user  nginx;
worker_processes  10;
worker_rlimit_nofile 100000;
error_log   /var/log/nginx/error.log;
pid        /var/run/nginx.pid;
 
events {
    worker_connections  1024;
    use epoll;
}
 
http {
    perl_modules  perl/lib;
    perl_require  mailauth.pm;
    server { 
# При обращении к директории /auth запускаем обработчик из Perl-скрипта
        location /auth {
            perl  mailauth::handler;
        }
    }
}
 
mail {
# Адрес обработчика для аутентификации, собственно говоря обращаемся сами к себе
    auth_http  127.0.0.1:80/auth;
    pop3_capabilities  "TOP"  "USER";
    imap_capabilities  "IMAP4rev1"  "UIDPLUS";
# Настройки POP3-сервера
    server {
        listen     110;
        protocol   pop3;
        proxy      on;
    }
# Настройки IMAP-сервера
    server {
        listen     143;
        protocol   imap;
        proxy      on;
    }
# Настройки SMTP-сервера
    server {
        server_name     myserver.local; # не любят внешние почтовики localhost ;)
        listen          25;
        protocol        smtp;
        proxy           on;
        xclient         off;
    }
}

Добавляем nginx в автозагрузку и запускаем:

[root@mailproxy nginx]# chkconfig nginx on
[root@mailproxy nginx]# service nginx start

На этом в общем-то настройка завершена, берем какой-нибудь Outlook Express вместо серверов SMTP, POP3 или IMAP, прописываем наш сервер и проверяем. Должно работать ;)

4. Заключение

Такой вариант решения подойдет скорее больше на любителя, но обозначенную проблему он решает и работает бесперебойно. Пока писал статью появилась еще одна мыслишка, попробовать nginx в качестве форонтенда к внутреннему почтовику, что бы отсечь часть пользователей котором не разрешен доступ через интернет к внутренней почте. Например, в Exchange 2007 умеет для определенного ящика отключать доступ по IMAP или POP3, но в случае если эти сервисы используются внутри сети, то зарыть их снаружи для определенных пользователей можно при помощи такого фронтенда, правда процедуру проверки пользователя придется малость переписать.

4 Коммент. : “NGINX как SMTP, POP3 и IMAP прокси”

  1. semper пишет:

    Хорошая статья. Побольше бы таких статей.

  2. bubnov-pi пишет:

    Чисто теоретическая польза от статьи есть, но вот сама задача, в ней решаемая вызывает некоторое недоумение – на моём скромном опыте, почти все, кто хочет читать личную почту (а равно VK/ICQ/FB/etc) на рабочем месте, пользуются мобильными телефонами – благо, это умеют и копеечные модели, а мобильный интернет последнее время стоит в месяц как пачка сигарет+бутылка пива (ну, или шоколадка+пакет сока – кому что роднее), да и доступен повсеместно…
    Единственный раз, когда был вынужден решать подобную задачу – это когда работодатель потребовал организовать доступ _некоторым_ сотрудникам к почте извне, но вот как раз этот сценарий в статье не развёрнут… (к слову, тогда задача решилась самым простым путём – доступ через VPN)

  3. Alsigned пишет:

    Привет, Bubnov-PI.

    Я часто решаю вопросы связанные с безопасностью информации, и прекрасно понимаю что можно лазить на одноклассники или в любую почту со своего коммуникатора, которыми обзавелись по-моему уже все. Как правило менегеры люди достаточно умные, и поэтому идут по пути наименьшего сопротивления, какой бы не был прекрасный коммуникатор, писать на нем сообщения более чем из 10 слов очень не удобно, скорость намного ниже чем на компьютере, дальше простая логика: скорость = время, время = деньги ;)

  4. ferix пишет:

    Ребят помогите. Настраивал все как в статье, но ничего не работает. Проверял телнетом и просто клиентом (Outlook) Что я мог сделать не так?

Оставить комментарий