Lemat, strona prywatna

Wykorzystanie mechanizmu postlogin dovecota

Po pierwsze i najistotniejsze: https://wiki.dovecot.org/PostLoginScripting

Post Login Scripting to jest mechanizm dovecota, który pozwala wykonywać "coś" po tym jak user się zaloguje. Podstawowa konfiguracja:

service imap {
  executable = imap imap-postlogin
}

service pop3 {
  executable = pop3 pop3-postlogin
}

service imap-postlogin-imap {
  executable = script-login /usr/local/bin/imap-postlogin.sh

  user = $default_internal_user
  unix_listener imap-postlogin {
  }
}

 

service pop3-postlogin {
  executable = script-login /usr/local/bin/pop3-postlogin.sh

  user = $default_internal_user
  unix_listener pop3-postlogin {
  }
}

 

 

i sam skrypt /usr/local/bin/imap-postlogin.sh

#!/bin/bash

if [ -n "$IP" ]; then
        COUNTRY=`/usr/bin/geoiplookup $IP|cut -d: -f2-`
        REV=`/usr/bin/dig +short -x $IP`
fi
if [ -n "$USER" ]; then
        EXPIRED=`echo "SELECT 1 FROM mailbox WHERE username='$USER' AND ((ISNULL(modified) AND DATEDIFF(now(),created)>360) OR DATEDIFF(now(),modified)>360)" | /usr/bin/mysql --defaults-file=/etc/postfix/.postfixadmin.cnf |tail -n1`
        if [ "$EXPIRED" == 1 ]; then
                printf "* OK [ALERT] We advise to change password once per year.\r\n"
        fi
        QUOTA=`echo "SELECT 1 FROM mailbox LEFT JOIN quota2 on mailbox.username=quota2.username WHERE mailbox.username='$USER' AND mailbox.quota>0 AND quota2.bytes>mailbox.quota*0.95;" | /usr/bin/mysql --defaults-file=/etc/postfix/.postfixadmin.cnf |tail -n1`
        if [ "$QUOTA" == 1 ]; then
                printf "* OK [ALERT] Your mailbox is almost full.\r\n"
        fi
        echo "UPDATE mailbox SET last_login = now(),last_login_info='$REV[$IP],$COUNTRY' WHERE username = '$USER'" | /usr/bin/mysql --defaults-file=/etc/postfix/.postfixadmin.cnf
fi
exec "$@"

gdzie plik etc/postfix/.postfixadmin.cnf zawiera dane logowania do bazy danych

[client]
user=postfixadmin
password="bardzo tajne haslo"
host=localhost
database=postfixadmin

to powyżej to tylko demo tego, co można robić.

A teraz przeanalizujmy to, co jest w tym skrypcie: Przede wszystkiem do skryptu są przekazywane 2 parametry: IP i USER.

Jeżeli mamy w MySQL tabelę mailbox o takiej strukturze:

CREATE TABLE `mailbox` (
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `maildir` varchar(255) NOT NULL,
  `transport` enum('virtual','procmail') NOT NULL DEFAULT 'virtual',
  `domain` varchar(255) NOT NULL,
  `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `active` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
  `quota` bigint(20) NOT NULL DEFAULT '0',
  `local_part` varchar(255) NOT NULL,
  `filter` enum('','client_chikor_check') NOT NULL DEFAULT 'client_chikor_check',
  `sender_login_maps` tinytext NOT NULL,
  `soft_limit` int(11) NOT NULL,
  `hard_limit` int(11) NOT NULL,
  `allow_nets` varchar(255) NOT NULL DEFAULT '0.0.0.0/8',
  `last_login` datetime NOT NULL,
  `last_login_info` tinytext NOT NULL
)  DEFAULT CHARSET=utf8 COMMENT='Virtual Mailboxes - mysql_virtual_mailbox_maps' ROW_FORMAT=DYNAMIC;


ALTER TABLE `mailbox`
  ADD PRIMARY KEY (`username`);

(lub podobną - chodzi o pola "modified", "last_login" i "last_login_info") - to po każdym zalogowaniu się usera możemy zalogować z jakiego IP się łączył, jego revDNS i kraj uzyskany z bazy geoip.

Korzystając z właściwości serwera IMAP możemy userowi wyświetlić komunikat o pełnej skrzynce lub komunikat, że zalecamy zmieniać hasło raz na ruski rok. Funkcjonalność wyświetlania komunikatów obsługuje Thunderbird, w Roundcube tego nie ma.

Możemy także limitować dostęp do skrzynek z IP należącego np. do Polski:

if [ "$COUNTRY" != "PL, Poland" ]; then
  printf "* NO [ALERT] Access not allowed from $COUNTRY\r\n"
  exit 0
fi

Powyższy fragment warto dostosować mając na uwadze, że geoiplookup dla IP prywatnych 10.*, 192.168.* odpowie "IP Address not found". Można też oczywiście w bazie danych zrobić sobie pole allowed_countries - do wyboru do koloru.

Dociekliwi mogą zauważyć w tabeli SQL obecność pola allow_nets, w którym znajduje się lista sieci w formacie CIDR, rozdzielonych przecinkami - z których logowanie jest dozwolone. Gdyby tam wstawić 127.0.0.1/8 to logowanie byłoby dozwolone tylko z webmaila.

Po co znać datę ostatniego logowania?

Aby wiedzieć, które skrzynki są używane a które nie. Albo inaczej - które skrzynki zajmują niepotrzebnie miejsce na serwerze.

Po co wiedzieć z jakiego kraju łączył się user?

Aby diagnozować włamania na skrzynki pocztowe.

Po co limitować userom logowanie z określonych sieci, określonego kraju?!

Ostatnio mój fail2ban zwariował logując pierdyliardy ataków słownikowych na moje serwery. Oczywiście zawsze to występowało, ale ostatnio to już przesada. Warto dać taki dodatkowy warunek logowania. Znaczy warto by było dać logowanie dwuskładnikowe ale to już trzeba by było mieć kasę na tokeny lub SMSy.

W jako sposób w polu "modified" pojawi się data ostatniej  zmiany hasła?

Roundcube posiada plugin "password", który konfigurujemy następująco:

$config['password_driver'] = 'sql';

$config['password_db_dsn'] = 'mysql://postfixadmin:bardzotajnehaslo@localhost/postfixadmin';

$config['password_query'] = 'UPDATE mailbox SET password=%p, modified=now() WHERE username=%u';


Data utworzenia : 2020-06-24, data aktualizacji :2020-06-26

Skomentuj ten tekst

Protected by spf
[Nospam-PL.NET]
Seti@Home
www.php.net
© Lemat 2004 - ∞