проксирование почты через nginx, FreeBSD 13

Обсуждаем сайт и форум.

Модератор: f0s

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35457
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

проксирование почты через nginx, FreeBSD 13

Непрочитанное сообщение Alex Keda » 2024-02-05 12:18:01

наброски для себя, чтоб не забыть
конфигурация полгода отработала в продакшене, проблем не наблюдалось
сертфикат. выпускаем через certbot, рисуем скрипт на автоообновление: /root/scripts/work/certbot.sh

Код: Выделить всё

#!/bin/sh

service nginx stop

certbot renew

chmod 755 /usr/local/etc/letsencrypt/archive
chmod 755 /usr/local/etc/letsencrypt/live
chmod 755 /usr/local/etc/letsencrypt/live/*/*

service nginx start
и лепим в планировщик

Код: Выделить всё

rproxy.canada-pindoss.local# crontab -l -u toor
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
MAILTO=""

@weekly         sh /root/scripts/work/certbot.sh

конфиг /usr/local/etc/nginx/nginx.conf

Код: Выделить всё

# модуль проксирования почты. пришлось собирать из портов, по дефолту его нет в сборке из пакетов
load_module "/usr/local/libexec/nginx/ngx_mail_module.so";

........

http {

	............

        # первый виртуалхост
        server {
                listen          80      default_server;
                server_name     "";

#               location = /basic_status {
#                       stub_status;
#                       allow 127.0.0.1;
#                       allow 10.181.160.0/19;
#                       deny all;
#               }
                # php-fpm
                location ~ \.php$ {
                        set $root_path /usr/local/www/nginx;
                        fastcgi_pass unix:/var/run/php-fpm.sock;
                        fastcgi_index index.php;
                        fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
                        include fastcgi_params;
                        fastcgi_param DOCUMENT_ROOT $root_path;
                }

#               return          444;
        }

	..........

}


# проксирование почты
mail {
        server_name             mx.canada-pindoss.pro;

        ssl_certificate         /usr/local/etc/letsencrypt/live/mx.canada-pindoss.pro/fullchain.pem;
        ssl_certificate_key     /usr/local/etc/letsencrypt/live/mx.canada-pindoss.pro/privkey.pem;
        ssl_session_timeout 5m;
        xclient off;
        starttls                on;
        proxy                   on;

        error_log /var/log/nginx/mail_proxy_error.log info;

        auth_http   localhost/mail.auth.php;
        proxy_pass_error_message on;

        server {
                listen          25;
                protocol        smtp;
                smtp_auth       none login plain cram-md5;
                proxy_smtp_auth on;
        }
        server {
                listen          465;
                protocol        smtp;
                smtp_auth       none login plain cram-md5;
                proxy_smtp_auth on;
        }
        server {
                listen          587;
                protocol        smtp;
                smtp_auth       none login plain cram-md5;
                proxy_smtp_auth on;
        }

        server {
                listen          110;
                protocol        pop3;
                pop3_auth       plain apop cram-md5;
        }

        server {
                listen          143;
                protocol        imap;
        }

        server {
                listen          993 ssl;
                protocol        imap;
        }
}
запрещаем релей с прокси, разрешаем с остальной сети, /usr/local/etc/exim/configure

Код: Выделить всё

hostlist   relay_from_hosts = localhost : @ : 127.0.0.0/8 : !192.168.120.20 : 192.168.0.0/16
авторизационный файл: /usr/local/www/nginx/mail.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
*/

ob_start();

$Line = "\n" . date('Y-m-d G:i:s') . ": " . $_SERVER['HTTP_CLIENT_IP'] . ", " . $_SERVER["HTTP_AUTH_USER"] . ", " . $_SERVER["HTTP_AUTH_PASS"] . ", " . $_SERVER["HTTP_AUTH_PROTOCOL"];
Logg($Line);

if (!IsSet($_SERVER["HTTP_AUTH_USER"] ) || !IsSet($_SERVER["HTTP_AUTH_PASS"] )){
        fail();
        //Pass('mx.canada-pindoss.pro',25);
}
#Logg("after IsSet");

$UserName       = $_SERVER["HTTP_AUTH_USER"] ;
$UserPassword   = $_SERVER["HTTP_AUTH_PASS"] ;
$Protocol       = $_SERVER["HTTP_AUTH_PROTOCOL"] ;

//Logg(print_r($_SERVER,true));


// вариант приёма без авторизации
if(!$_SERVER['HTTP_AUTH_USER']){
        // [HTTP_AUTH_SMTP_TO] => RCPT TO:<admin@california-pindoss.ca>
        Preg_Match('/:\<(.*)\>/', $_SERVER['HTTP_AUTH_SMTP_TO'],$Matches, PREG_OFFSET_CAPTURE);
        $UserName = $Matches[1][0];
        Logg("non-auth user: " . $UserName);
}


// default backend port
$BackEndPort=110;

if($Protocol == "imap")
        $BackEndPort = 143;

if($Protocol == "smtp")
        $BackEndPort = 25;

// NGINX likes ip address so if your
// application gives back hostname, convert it to ip address here
$BackEndIP["mx.canada-pindoss.pro"]    = "192.168.120.21";
$BackEndIP["canada-pindoss.pro"]          = "192.168.120.21";
$BackEndIP["california-pindoss.ca"]        = "192.168.120.26";
$BackEndIP["another-pindoss-1-e.ru"]     = "192.168.120.26";
$BackEndIP["another-pindoss-2.com"]     = "192.168.120.26";

// Authenticate the user or fail
if(!AuthUser($UserName,$UserPassword)){
        fail();
        exit;
}

//Logg("after AuthUser");

// Get the server for this user if we have reached so far
$UserServer = GetMailServer($UserName);
Logg("after GetMailServer, UserServer = $UserServer");
// 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
$ServerIP = (IsSet($BackEndIP[$UserServer]))?$BackEndIP[$UserServer] : $UserServer;

// Pass!
Pass($ServerIP, $BackEndPort);
//Logg("after Pass");

//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){
        // разбираем логин по @
        $Array = Explode('@',$User);
        // если домен есть - используем его, если нет - дефолтовый
        //Logg("into GetMailServer, " . print_r($Array,true));
        if(IsSet($Array[1])){
                return $Array[1];
        }else{
                return "canada-pindoss.pro";
        }
}

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");
        //Logg("Header sent: $Server:$Port");
        exit;
}


function Logg($Line){
        $File = '/tmp/mail.auth.log';
        if(!$fp = fopen($File, 'a')){
                echo "Не могу открыть файл ($File)";
                exit;
        }
        if (fwrite($fp, $Line . "\n") === FALSE) {
                echo "Не могу произвести запись в файл ($File)";
                exit;
        }
        fclose($fp);
}


?>
fail2ban
/usr/local/etc/fail2ban/jail.d/nginx-dovecot.conf

Код: Выделить всё

#
[nginx-dovecot]
enabled = true
action = bsd-ipfw[table=dovecot]
bantime.increment = false
bantime.overalljails = true
filter = nginx-dovecot
logpath = /var/log/nginx/mail_proxy_error.log
/usr/local/etc/fail2ban/jail.d/nginx-exim.conf

Код: Выделить всё

#
[nginx-exim]
enabled  = true
action = bsd-ipfw[table=exim]
bantime.increment = true
bantime.overalljails = true
filter = nginx-exim
logpath = /var/log/nginx/mail_proxy_error.log
/usr/local/etc/fail2ban/filter.d/nginx-dovecot.conf

Код: Выделить всё

#
[Definition]
failregex = .*Authentication failed.*while reading response from upstream, client: <HOST>, server: 0.0.0.0:(110|143|993),.*
/usr/local/etc/fail2ban/filter.d/nginx-exim.conf

Код: Выделить всё

#
[Definition]
failregex = .*Incorrect authentication data.*while reading response from upstream, client: <HOST>, server: 0.0.0.0:(25|465|587),.*

ну как-то так.

настройка php-fpm пропущена, я не помню как и что там настраивал - но по какой-то первой попавшейся в инете инcтрукции делалось с поправкой на пути FreeBSD
Убей их всех! Бог потом рассортирует...

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
Neus
капитан
Сообщения: 1980
Зарегистрирован: 2008-09-08 21:59:56

проксирование почты через nginx, FreeBSD 13

Непрочитанное сообщение Neus » 2024-02-05 15:40:00

Троллишь именами доменов пиндостан? 😏
Physics is mathematics with the constraint of reality.
Engineering is physics with the constraint of money.

LOR захватили ситхи.
Добро пожаловать на светлую сторону!

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35457
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

проксирование почты через nginx, FreeBSD 13

Непрочитанное сообщение Alex Keda » 2024-02-05 16:32:33

ну там реально и те и другие пиндосы =)
Убей их всех! Бог потом рассортирует...