Postfix Dovecot MYSQL
32. sor: | 32. sor: | ||
<pre> |
<pre> |
||
# megjelenítendő hostnév |
# megjelenítendő hostnév |
||
− | myhostname = carpoon.hu |
+ | myhostname = domain1.hu |
− | myorigin = carpoon.hu |
+ | myorigin = domain1.hu |
− | mydestination = localhost.carpoon.hu, localhost |
+ | mydestination = localhost.domain1.hu, localhost |
# azok a hálózatok amiket biztonságosnak ítélünk és bizonyos ellenőrzéseket átugrunk ezekről a címekről |
# azok a hálózatok amiket biztonságosnak ítélünk és bizonyos ellenőrzéseket átugrunk ezekről a címekről |
||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
||
130. sor: | 130. sor: | ||
| userID | user | domain | password | active | quota | |
| userID | user | domain | password | active | quota | |
||
+--------+---------+------------+----------------------------------------------------------+--------+----------+ |
+--------+---------+------------+----------------------------------------------------------+--------+----------+ |
||
− | | 3 | test | carpoon.hu |apfAlBBFtlYefTNlFF9+RZ3Xdz8og5E/86upbmrCw64tI1Z8cTNXMQ== | 1 | 10485760 | |
+ | | 3 | test | domain1.hu |apfAlBBFtlYefTNlFF9+RZ3Xdz8og5E/86upbmrCw64tI1Z8cTNXMQ== | 1 | 10485760 | |
+--------+---------+------------+----------------------------------------------------------+--------+----------+ |
+--------+---------+------------+----------------------------------------------------------+--------+----------+ |
||
</pre> |
</pre> |
||
143. sor: | 143. sor: | ||
* domains példaadatok: |
* domains példaadatok: |
||
<pre> |
<pre> |
||
− | +----------+---------------+ |
+ | +----------+------------+ |
− | | domainID | domain | |
+ | | domainID | domain | |
− | +----------+---------------+ |
+ | +----------+------------+ |
− | | 1 | carpoon.hu | |
+ | | 1 | domain1.hu | |
− | | 2 | mattewvigo.hu | |
+ | | 2 | domain2.hu | |
− | +----------+---------------+ |
+ | +----------+------------+ |
</pre> |
</pre> |
||
* forwardings: |
* forwardings: |
||
167. sor: | 167. sor: | ||
| forwardingsID | source | destination | active | |
| forwardingsID | source | destination | active | |
||
+---------------+--------------------------+------------------+--------+ |
+---------------+--------------------------+------------------+--------+ |
||
− | | 1 | @carpoon.hu | lost@carpoon.hu | 1 | |
+ | | 1 | @domain1.hu | lost@domain1.hu | 1 | |
− | | 2 | postmaster@carpoon.hu | admin@carpoon.hu | 1 | |
+ | | 2 | postmaster@domain1.hu | admin@domain1.hu | 1 | |
− | | 3 | root@carpoon.hu | admin@carpoon.hu | 1 | |
+ | | 3 | root@domain1.hu | admin@domain1.hu | 1 | |
− | | 4 | hostmaster@carpoon.hu | admin@carpoon.hu | 1 | |
+ | | 4 | hostmaster@domain1.hu | admin@domain1.hu | 1 | |
− | | 5 | administrator@carpoon.hu | admin@carpoon.hu | 1 | |
+ | | 5 | administrator@domain1.hu | admin@domain1.hu | 1 | |
+---------------+--------------------------+------------------+--------+ |
+---------------+--------------------------+------------------+--------+ |
||
</pre> |
</pre> |
||
188. sor: | 188. sor: | ||
| transportID | domain | transport | |
| transportID | domain | transport | |
||
+-------------+----------------+-----------+ |
+-------------+----------------+-----------+ |
||
− | | 1 | carpoon.hu | : | |
+ | | 1 | domain1.hu | : | |
− | | 2 | matthewvigo.hu | : | |
+ | | 2 | domain2.hu | : | |
+-------------+----------------+-----------+ |
+-------------+----------------+-----------+ |
||
</pre> |
</pre> |
A lap 2012. október 3., 10:39-kori változata
Tartalomjegyzék |
1 Szerver alkalmazások kiválasztása
Az email rendszert amit bemutatok egy honlap rendszerhez tartozik. Szempont volt hogy közös felhasználói adatábzis legyes és hogy minden platform képes legyen a felhasználókat authentikálni. A rendzser minden felhasználója autómatikusan kapott egy email címet.
Az általam válaszott szerver alkalazások, inkoklás miért ezek mellett döntöttem:
- MTA (Mail Transfer Agent): Postfix.
- MDA (Mail Delivery Agent): Dovecot. Több open source rendszert megnézetem, ezek közül a dovecot jól skálázható, robusztus. Natívan támogatja a felhasználók adatbázisban tárolását és az SSHA(Salted Safe Hash Algorithm) agloritmust. Dovecot további előnye, hogy a levelek fiókokba helyezését is el tudja látni így az esetlegesen eltérő megvalósítások mailbox megvalósítások nem okoznak hibát. Élesben kipróbáltam a Courier-t is, de sokkal nagyobb volt a memóriaigénye a tesztidőszak alatt.
- DBMS: MYSQL. A MYSQL az egyik széleskörben alkalmazott adatbáziskezelő rendszer, könnyen használható különböző programozási nyelvek alól, ami a project megvalósításánál fontos szempont volt (php, node.js, java, stb).
2 Működés áttekintése
A levelek fogadásáról és küldéséről a postfix gondoskodik. A levelek elhelyezéséről, tartóstárba írásáról, azonosításáról pedig a dovecot. A működéshez szükséges adatokat 4 MYSQL táblában tárolja, így azok könnyen managelhetőek. A leveleket a postfix amikor megkapja átadja a különböző szűrő alkalmazásoknak ezek egyenlőre nem részei ennek az írásnak. A levelelzőszerverek a leveleket a /var/vmail/ mappába teszik, a leveleket mint vmail(uid: 150) felhasználó teszik be, aki a mail(gid: 8) csoport tagja. Lehetőség van minden fiók számára saját linux felhasználó létrehozására ezzel biztonságosabbá téve a fiók hozzáférését, ha az IMAP szerverben biztonsági rés lenne.
A felhasználókról külön tároljuk a felhasználónevüket és a domainjüket, amihez az emailcím tartozik, ennek megvannak a maga sajátosságai.
- előnyök
- azonosításnál elég a felhasználónév megadása nem kell a teljes emailcímet megadni
- ha nem csak a levelekhasználják a felhasználói adatbázis azok számára is könnyebb a használat
- hátrányok
- nem tartozhat több domainhez ugyan olyan felhasználónév, vagy ha ezt szeretnénk akkor elveszítjük az előnyöket
3 Egy gyakorlati megvalósítás
3.1 Postfix beállítása
3.1.1 main.cf
Beállítások amik eltérnek az alapértékektől (teljes file a melléketek közt).
- Dovecot SASL autentikáció beállítása:
smtpd_sasl_type = dovecot #/var/spool/postfix/private/auth - dovecot auth socket smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes broken_sasl_auth_clients = yes smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = smtpd_sasl_authenticated_header = yes
- Hálózati paraméterek:
# megjelenítendő hostnév myhostname = domain1.hu myorigin = domain1.hu mydestination = localhost.domain1.hu, localhost # azok a hálózatok amiket biztonságosnak ítélünk és bizonyos ellenőrzéseket átugrunk ezekről a címekről mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 mailbox_size_limit = 0 recipient_delimiter = + # minden interfacen fogad leveleket inet_interfaces = all # több subnethez is kapcsolódik a server, megadhatjuk az interfacet amin keresztül kapcsolatokat kezdeményez a szerver default_transport = 10.0.0.24 mynetworks_style = host
- Levelek elhelyezésére vonatkozó információk:
virtual_mailbox_base = /var/vmail virtual_uid_maps = static:150 virtual_gid_maps = static:8
- MYSQL felé való átjárás, részletek az adatábzistábláknál. Ahova több lekérés is tartozik, ott
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf, mysql:/etc/postfix/mysql_virtual_email2email.cf virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf transport_maps = mysql:/etc/postfix/mysql_virtual_transports.cf smtpd_sender_login_maps = mysql:/etc/postfix/mysql_virtual_email_verify.cf
- Levelek virusírtónak való átadása:
content_filter = amavis:[127.0.0.1]:10024
- Levelek fiókokba helyezése dovecotnak való átadása:
virtual_transport = dovecot dovecot_destination_recipient_limit = 1
3.1.2 master.cf
A master.cf a postfix kapcsolatati leíró file.
- beérkező levelek számára a 25-ös és a ssl port
smtp inet n - - - - smtpd smtps inet n - - - - smtpd
- tartalom szűrők fele
amavis unix - - - - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes -o max_use=20 127.0.0.1:10025 inet n - - - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_delay_reject=no -o smtpd_client_restrictions=permit_mynetworks,reject -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions=reject_unauth_pipelining -o smtpd_end_of_data_restrictions= -o mynetworks=127.0.0.0/8 -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o smtpd_client_connection_count_limit=0 -o smtpd_client_connection_rate_limit=0 -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
- dovecot fele a levelek továbbítása
dovecot unix - n n - - pipe flags=DRhu user=vmail:mail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)
3.1.3 Adattárolás és adatbázis kapcsolat
- Célszerű egy külön táblát és saját felhasználót létrehozni postfixnek és dovecotnak és csak olvasási joggot adni az accountra. A managementet egy külön felhasználóval lehet végezni.
- Két táblában van 'active' oszlop ezeket a sorokat a lekérések csak 1 érték esetén veszik figyelembe (ezt minden táblánál meg lehetne tenni, de a többinél ennek gyakorlati haszna nem lenne). Ennek a segítségével egy átirányátás, vagy felhasználói fiók ideiglenesen is kikapcsolható.
- Ebben a konfigurációban a quota byteokban értendő, 0 esetén a dovecot nem alkalmaz korlátozást.
Adattáblák felépítése:
- users:
CREATE TABLE `users` ( `userID` int(10) unsigned NOT NULL AUTO_INCREMENT, `user` varchar(128) NOT NULL, `domain` varchar(128) NOT NULL, `password` varchar(128) DEFAULT '', `active` int(11) NOT NULL DEFAULT '0', `quota` int(10) unsigned NOT NULL DEFAULT '10485760', PRIMARY KEY (`userID`) )
- users példaadatok:
+--------+---------+------------+----------------------------------------------------------+--------+----------+ | userID | user | domain | password | active | quota | +--------+---------+------------+----------------------------------------------------------+--------+----------+ | 3 | test | domain1.hu |apfAlBBFtlYefTNlFF9+RZ3Xdz8og5E/86upbmrCw64tI1Z8cTNXMQ== | 1 | 10485760 | +--------+---------+------------+----------------------------------------------------------+--------+----------+
- domains:
CREATE TABLE `domains` ( `domainID` int(11) NOT NULL AUTO_INCREMENT, `domain` varchar(45) NOT NULL, PRIMARY KEY (`domainID`) )
- domains példaadatok:
+----------+------------+ | domainID | domain | +----------+------------+ | 1 | domain1.hu | | 2 | domain2.hu | +----------+------------+
- forwardings:
CREATE TABLE `forwardings` ( `forwardingsID` int(11) NOT NULL AUTO_INCREMENT, `source` varchar(128) NOT NULL, `destination` varchar(128) NOT NULL, `active` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`forwardingsID`) )
- forwardings példaadatok:
- 1: minden nem létező címere szóló levelet a lost postafiókba továbbítunk
- 2-5: a kölönböző adminisztrációs címket az admin postafiókba továbbítjuk
+---------------+--------------------------+------------------+--------+ | forwardingsID | source | destination | active | +---------------+--------------------------+------------------+--------+ | 1 | @domain1.hu | lost@domain1.hu | 1 | | 2 | postmaster@domain1.hu | admin@domain1.hu | 1 | | 3 | root@domain1.hu | admin@domain1.hu | 1 | | 4 | hostmaster@domain1.hu | admin@domain1.hu | 1 | | 5 | administrator@domain1.hu | admin@domain1.hu | 1 | +---------------+--------------------------+------------------+--------+
- transport:
CREATE TABLE `transport` ( `transportID` int(11) NOT NULL AUTO_INCREMENT, `domain` varchar(45) DEFAULT NULL, `transport` varchar(45) DEFAULT NULL, PRIMARY KEY (`transportID`) )
- transport példaadatok: mindekét domainünket helyben kiszolgáljuk, nem továbbítjuk (pl ha másnak az MX tartalék levelezőszervere vagyunk, az ő elsődleges servere felé továbbítunk)
+-------------+----------------+-----------+ | transportID | domain | transport | +-------------+----------------+-----------+ | 1 | domain1.hu | : | | 2 | domain2.hu | : | +-------------+----------------+-----------+
A /etc/postfix/ mappába a következő fileokra van szükség, amik az adatbázissal kötik össze. Mivel minden filenak tartalmazni kell a jelszót ezeknek a fileoknak a hozzáférésére fokozottan figyeljünk oda!
- Miden file elejére be kell illeszteni az adatbázis kapcsolat adatait ezek az adatokatok:
user = <adatbázis felhasználónév - mail> password = <adatbázisjelszó - ****> hosts = <adatbázis címe - x.x.x.x> dbname = <adatábzis tábla neve - mail>
- mysql_virtual_email2email.cf - virtual_alias_maps: felhasználók azonosítására szolgál
query = SELECT concat(user, '@', domain) FROM users WHERE user='%u' AND domain="%d"
- mysql_virtual_alias_maps.cf - virtual_alias_maps: címfordítások
query = SELECT destination FROM forwardings WHERE source='%s' AND active = '1'
- mysql_virtual_domains_maps.cf - virtual_mailbox_domains: a server által kiszolgált domainek listája
query = SELECT domain FROM domains WHERE domain='%s'
- mysql_virtual_email_verify.cf - smtpd_sender_login_maps: bejelentkezett felhasználó emailcímének lekérdezésére szolgál
query = SELECT user FROM users WHERE user='%u'
- mysql_virtual_mailbox_maps.cf - virtual_mailbox_maps: a felhasználók fiókjainak a helyét adja meg
query = SELECT CONCAT(domain,'/',user) FROM users WHERE user='%u' AND active = '1'
- mysql_virtual_transports.cf - transport_maps:
query = SELECT transport FROM transport WHERE domain='%s'
3.2 Dovecot beállítása
A különböző konfigurációs fileok elött számok a fileok végrehajtásának sorrendjét garantálják.
- /etc/dovecot/conf.d/10-auth.conf - authentikációs beállítások
# azonosítás csak titkosított csatornán disable_plaintext_auth = yes # legtöbb levelező ismeri és használja a 'plain' autentikációt, de az outlook csak a 'login' megtódust auth_mechanisms = plain login # includeoljuk a saját adatbázisfileunkat !include auth-sql.conf.ext
- /etc/dovecot/conf.d/10-mail.conf - levelek
# postafiókok helye mail_location = maildir:/var/vmail/%d/%n # levelek írásához/olvasásához használt felhasználó, és csoport mail_uid = vmail mail_gid = mail # ezek az értékek ebben a konfigurációban nem first_valid_uid = 150 last_valid_uid = 150 first_valid_gid = 8 last_valid_gid = 8 # meg kell adni a plugin könyvtárat ha használni akarunk kvótát mail_plugin_dir = /usr/lib/dovecot/modules
- /etc/dovecot/conf.d/10-master.conf - authentikációs socketek beállítása
service auth { # dovecot saját folyamatai számára az authentikációs unix socket unix_listener auth-userdb { mode = 0600 user = vmail group = mail } # postfix szára az authentikációs unix socket unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } }
- /etc/dovecot/conf.d/20-imap.conf - imap sepcifikus beállítások
# engedélyezni kell a kvótát imapon felül mail_plugins = $mail_plugins imap_quota
- /etc/dovecot/conf.d/auth-sql.conf.ext - az alkalmazott DBMS specifikálása:
passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext }
- /etc/dovecot/conf.d/90-quota.conf - kvóta beállítások
plugin { quota = maildir:User quota quota_rule = *:bytes=1000000 }
- /etc/dovecot/dovecot-sql.conf.ext - dovecot mysql lekérései:
driver = mysql connect = host=<adatbázis címe - x.x.x.x> dbname=<adatbázis felhasználónév - mail> user=<adatábzis tábla neve - mail> password=<adatbázisjelszó - ****> default_pass_scheme = SSHA256 password_query = SELECT user as user, password, concat('/var/vmail/', domain,'/%n') as userdb_home, concat('maildir:/var/vmail/', domain,'/%n') as userdb_mail, 150 as userdb_uid, 8 as userdb_gid FROM users WHERE user = '%n' AND active ='1' user_query = SELECT concat('/var/vmail/', domain,'/%n') as home, concat('maildir:/var/vmail/', domain,'/%n') as mail, 150 AS uid, 8 AS gid, concat('*:bytes=', quota) AS quota_rule FROM users WHERE user = '%n' AND active = '1'
4 Mellékletek
- Egy php class ami a dovecot számára is olvasható formátumban állít elő SSHA256 jelszavakat.
<?php class Crypt { public static $allowedABC = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; public static $allowed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{|}~[\]^_!#$%&()*+,-./`:;<=>?'; public static function authenticate($ssha, $password) { $salt = substr(base64_decode($ssha, true), 32); if(Crypt::calculatePasswordHash($password, $salt) == $ssha) { return true; } else { return false; } } public static function generatePasswordHash($password) { $salt = Crypt::randomCharsFull(8); return base64_encode(hash('sha256', $password . $salt, TRUE) . $salt); } public static function calculatePasswordHash($password, $salt) { return base64_encode(hash('sha256', $password . $salt, TRUE) . $salt); } public static function randomCharsFull($length){ $string = ''; $limit = strlen(Crypt::$allowed); for($i = 0 ; $i < $length ; $i++) { $string .= substr(Crypt::$allowed, mt_rand(0, $limit-1), 1); } return $string; } public static function randomCharsAbc($length){ $string = ''; $limit = strlen(Crypt::$allowedABC); for($i = 0 ; $i < $length ; $i++) { $string .= substr(Crypt::$allowedABC, mt_rand(0, $limit-1), 1); } return $string; } } ?>
2 rövid segédfile, hogy consoleból is könnyen lehessen jelszót generálni
mkpwd.php: <?php require_once 'Crypt.php'; echo ''.Crypt::generatePasswordHash($argv[1]); ?> mkpwd.sh: #!/bin/bash read -s -p "Type password:" pwd echo -e "\nPassword SSHA256 hash:" php mkpwd.php $pwd echo -e ""