Обновление почтового сервера iRedMail с 0.9.5-1 до 0.9.7
Прошло уже почти два года с момента последнего обновления почтового сервера iRedMail до версии 0.9.5-1. а значит имеет смысл актуализировать нашу почтовую систему до последней на момент выхода статьи версии - 0.9.7. Пошаговый процесс установки iRedMail (MySQL Backend) и различные проблемы возникающие в процессе обслуживания сервера описаны в главной статье. В текущей сборке произошли некоторые изменения по части безопасности таких компонентов как Postfix, Amavis, Fail2ban + небольшие правки по части интерфейса в том же Roundcube, iRedAPD.
Если ставить новую версию на новый сервер, не OpenLDAP, то можно заметить что в качестве СУБД, вместо MySQL теперь MarinaDB, что на самом деле, абсолютно не страшно, поскольку MarinaDB это клон MySQL с тем же набором команд и инструкций от тех же разработчиков, только более свободный и независимый :)
Итак приступим. Для начала обновим саму ось выполнив всем известный набор команд:
apt-get update && apt-get upgrade
или
aptitude update && aptitude upgrade
Если, что-то пошло не так. У меня например в начале обновления на моем Debian 7 (Wheezy) вылезло информационное окошко PostgreSQL (С чего это вдруг, ведь данный пакет в системе не установлен?!), где в конце для выхода предлагают нажать quit (q), но при нажатии данной клавиши ничего не происходит. Следовательно приходится прерывать процесс при помощи ctrl+c. А вот если обновлять систему при помощи aptitude то нажатие "q" отрабатывает корректно.
Теперь перейдем к обновлению основных компонентов сервера.
Меняем текущий номер версии iRedMail на последнюю, открыв на изменение файлик /etc/iredmail-release
1) Обновление iRedAPD:
cd /root wget http://www.iredmail.org/yum/misc/iRedAPD-2.1.tar.bz2 tar xjf iRedAPD*.bz2 cd iRedAPD*/tools/ sh upgrade_iredapd.sh
Скрипт ругнулся на отсутствующий файлик .my.cnf, где записана инфа о подключении к MySQL-серверу. Дадим ему такой файлик и снова запустим скрипт: sh upgrade_iredapd.sh
[client] host=localhost port=3306 user=root password="<your-password>"
Если видим в конце, что "Upgrade completed", то все ОК, переходим к следующему компоненту.
2) Обновление iRedAdmin:
cd /root/ wget https://dl.iredmail.org/yum/misc/iRedAdmin-0.8.tar.bz2 tar xjf iRedAdmin*.tar.bz2 cd iRedAdmin*/tools/ shell upgrade_iredadmin.sh
3) Обновление Roundcube:
cd /root wget https://dl.iredmail.org/yum/misc/roundcubemail-1.3.3-complete.tar.gz tar xf roundcubemail*.tar.gz cd roundcubemail* bin/installto.sh /usr/share/apache2/roundcubemail-1.2.2
Нажимаем Yes. Если видим что:
This instance of Roundcube is up-to-date.
Have fun!
All done.
То процесс обновления прошел успешно.
Поправим имя директории roundcubemail на актуальную с правкой ярлыка (smlinks):
cd /usr/share/apache2 rm -i /usr/share/apache2/roundcubemail mv /usr/share/apache2/roundcubemail-1.2.2 roundcubemail-1.3.3 ln -s roundcubemail-1.3.3 roundcubemail
Убедимся что владелец файла конфигурации /usr/share/apache2/plugins/password/config.inc.php (в новых версиях iRedMail путь к файлу может быть другим) и разрешения выставлены как:
www-data:www-data, 0400;
Если нет поправим командами:
chown www-data:www-data /usr/share/apache2/plugins/password/config.inc.php chmod 0400 /usr/share/apache2/plugins/password/config.inc.php
Добавим в cron скрипт очистки директории /usr/share/apache2/roundcubemail/temp куда загружаются временные файлы пользователей, в основном это мини изображения вложений, графические элементы подписей. Со временем данная папка может существенно вырасти в размере, выжрав все свободное пространство на диске :)
Открываем на редактирование cron (crontab -e -u root) и вставляем туда следующую строчку:
# Roundcube: Удаляем временные файлы. # По умолчанию файлы хранятся два дня и контролируются в Roundcube параметром: $config['temp_dir_ttl'] 2 2 * * * php /usr/share/apache2/roundcubemail/bin/gc.sh >/dev/null
Кстати, параметр "$config['temp_dir_ttl']" не был мной обнаружен в /usr/share/apache2/roundcubemail-1.3.3/config/config.inc.php а вот в самом дистрибутиве он есть, что как бы намекает, что процесс обновления со старой версии на новую не совсем корректно происходит. Хотя ничто не мешает нам его добавить в конфиг:
$config['temp_dir_ttl'] = '48h';
Но тогда не понятно, если существует данный параметр и файлы хранятся два дня, то зачем задание в cron очищающие данную папку или они хранятся где-то еще?! Надо будет понаблюдать! К слову сказать у меня за последние 2 года использования таких файлов набралось аж 5 мб :)
4) Обновление Apache:
Исправляем уязвимость HTTProxy добавлением параметра в файл /etc/apache2/apache2.conf
RequestHeader unset Proxy early
Перезапускаем Apache командой:
service apache2 restart
4) Изменения в Postfix:
Версия iRedMail-0.9.5-1 и более ранние позволяют доверенным клиентам (указанным в параметре mynetworks) отправлять электронную почту через порт 587 без проверки подлинности smtp, что недостаточно строго и может использоваться спамерами. Для того что бы сконфигурировать механизм отправки почты через 587 порт с проверкой подлинности smtp для всех пользователей, поменяем значения параметра smtpd_client_restrictions в файле /etc/postfix/master.cf.
Открываем master.cf. на редактирование и находим строки:
submission inet n - n - - smtpd. -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
Удаляем "permit_mynetworks". Должно получится:
submission inet n - n - - smtpd. o smtpd_client_restrictions=permit_sasl_authenticated,reject
Так же в версии iRedMail-0.9.5-1 и более ранних не было поддержки безопасного соединения через TLS, что приводило к тому что другие серверы не могли передавать электронные сообщения через безопасное соединение. Добавим данную поддержку командой и обновим настройки postfix:
postconf -e smtpd_tls_security_level='may' postfix reload
Одно неправильное или дополнительное ограничение в файле etc/postfix/helo_access.pcre. Убрать строку:
/(\d{1,3}[\.-]\d{1,3}[\.-]\d{1,3}[\.-]\d{1,3})/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1}
и поставить вместо нее следующее регулярное выражение:
^(\d{1,3}[\.-]\d{1,3}[\.-]\d{1,3}[\.-]\d{1,3})$/ REJECT ACCESS DENIED. Your email was rejected because the sending mail server appears to be on a dynamic IP address that should not be doing direct mail delivery (${1})
В моем файле ошибок нет, но такой строки тоже, поэтому просто добавил себе как доп. опцию.
5) Изменения в Amavis:
Добавлены новые правила фильтрации вложений по имени файла, расширению, а так же mime-заголовкам. К слову данная фича у меня уже была реализована изначально, смотрим первую статью, хотя кое что я все таки у себя подправил:
# Compressed file types [qr'T=x-(msdownload|msdos-program|msmetafile)(,|\t)'xmi => 'DISCARD'], [qr'T=(hta)(,|\t)'xmi => 'DISCARD'], # Dangerous mime types [qr'T=(9|386|LeChiffre|aaa|abc|aepl|ani|aru|atm|aut| b64|bat|bhx|bkd|blf|bll|bmw|boo|bps|bqf|breaking_bad|buk|bup|bxz|cc|ccc| ce0|ceo|cfxxe|chm|cih|cla|class|cmd|com|cpl|crinf|crjoker|crypt|cryptolocker| cryptowall|ctbl|cxq|cyw|dbd|delf|dev|dlb|dli|dll|dllx|dom|drv|dx|dxz|dyv|dyz| ecc|exe|exe-ms|exe1|exe_renamed|exx|ezt|ezz|fag|fjl|fnr|fuj|good|gzquar|hlp| hlw|hqx|hsq|hts|iva|iws|jar|js|kcd|keybtc@inbox_com|let|lik|lkh|lnk|locky|lok| lol!|lpaq5|magic|mfu|micro|mim|mjg|mjz|nls|oar|ocx|osa|ozd|pcx|pgm|php2|php3| pid|pif|plc|pr|pzdc|qit|qrn|r5a|rhk|rna|rsc_tmp|s7p|scr|shs|ska|smm|smtmp|sop| spam|ssy|swf|sys|tko|tps|tsa|tti|ttt|txs|upa|uu|uue|uzy|vb|vba|vbe|vbs|vbx| vexe|vxd|vzr|wlpginstall|ws|wsc|wsf|wsh|wss|xdu|xir|xlm|xlv|xnt|xnxx|xtbl| xxe|xxx|xyz|zix|zvz|zoo|zzz)(,|\t)'xmi => 'DISCARD'], # Dangerous file name extensions [qr'N=.*\.(9|386|LeChiffre|aaa|abc|aepl|ani|aru|atm|aut|b64|bat|bhx|bkd|blf|bll|bmw| boo|bps|bqf|breaking_bad|buk|bup|bxz|cc|ccc|ce0|ceo|cfxxe|chm|cih|cla|class|cmd| com|cpl|crinf|crjoker|crypt|cryptolocker|cryptowall|ctbl|cxq|cyw|dbd|delf|ev|dlb| dli|dll|dllx|dom|drv|dx|dxz|dyv|dyz|ecc|exe|exe-ms|exe1|exe_renamed|exx|ezt|ezz| fag|fjl|fnr|fuj|good|gzquar|hlp|hlw|hqx|hsq|hts|iva|iws|jar|js|kcd|keybtc@inbox_com| let|lik|lkh|lnk|locky|lok|lol!|lpaq5|magic|mfu|micro|mim|mjg|mjz|nls|oar|ocx|osa|ozd| pcx|pgm|php2|php3|pid|pif|plc|pr|pzdc|qit|qrn|r5a|rhk|rna|rsc_tmp|s7p|scr|shs|ska| smm|smtmp|sop|spam|ssy|swf|sys|tko|tps|tsa|tti|ttt|txs|upa|uu|uue|uzy|vb|vba| vbe|vbs|vbx|vexe|vxd|vzr|wlpginstall|ws|wsc|wsf|wsh|wss|xdu|xir|xlm|xlv|xnt| xnxx|xtbl|xxe|xxx|xyz|zix|zvz|zzz)$'xmi => 'DISCARD'], );
Вносим изменения в главный конфиг сервиса /etc/amavis/conf.d/50-user и перезапускаем его командой;
service amavis restart
6) Изменения в Fail2ban:
Улучшаем регулярные выражение фильтра Fail2ban, чтобы поймать больше спама POP3 / IMAP и добавляем правильный фильтр для файла журнала Dovecot:
cd /etc/fail2ban/filter.d/ rm -f dovecot.iredmail.conf roundcube.iredmail.conf wget https://bitbucket.org/zhb/iredmail/raw/default/iRedMail/samples/fail2ban/filter.d/dovecot.iredmail.conf wget https://bitbucket.org/zhb/iredmail/raw/default/iRedMail/samples/fail2ban/filter.d/roundcube.iredmail.conf service fail2ban reload
7) Изменения в Awstat:
В iRedMail-0.9.5-1 и более ранних выпусках, Awstats была неправильно настроена и доступна без аутентификации. Что бы это исправить, открываем конфиг /etc/apache2/conf.d/awstats.conf на редактирование и добавляем две строки:
Require all granted Require valid-user
8) Изменения в Dovecot:
Фиксим неправильный параметр logrotate для файла журнала Dovecot, из-за которого все файлы журнала Dovecot пусты, в ввиду отсутствия необходимых разрешений для открытия файлов журнала. Что бы поправить, открываем файл /etc/logrotate.d/dovecot на редактирование и удаляем следующую сроку:
create 0600 vmail vmail
9) Обновление phpmyadmin. (опционально)
cd /tmp cp -a /usr/share/phpmyadmin /tmp cp /usr/share/phpmyadmin/config.inc.php /tmp rm -rf /usr/share/phpmyadmin wget https://files.phpmyadmin.net/phpMyAdmin/4.7.7/phpMyAdmin-4.7.7-all-languages.tar.gz tar xf /tmp/phpMyAdmin-4.6.4-all-languages.tar.gz -C /usr/share mv /usr/share/phpMyAdmin-4.6.4-all-languages /usr/share/phpmyadmin cp /tmp/config.inc.php /usr/share/phpmyadmin service apache2 restart
10) Изменения в MySQL:
Скорректируем значения (datetime) для некоторых столбцов SQL в базе данных «vmail»:
cd /tmp cp -a /usr/share/phpmyadmin /tmp cp /usr/share/phpmyadmin/config.inc.php /tmp rm -rf /usr/share/phpmyadmin wget https://files.phpmyadmin.net/phpMyAdmin/4.7.7/phpMyAdmin-4.7.7-all-languages.tar.gz tar xf /tmp/phpMyAdmin-4.6.4-all-languages.tar.gz -C /usr/share mv /usr/share/phpMyAdmin-4.6.4-all-languages /usr/share/phpmyadmin cp /tmp/config.inc.php /usr/share/phpmyadmin service apache2 restart
Добавим новые таблицы forwardings,
CREATE TABLE IF NOT EXISTS forwardings ( id BIGINT(20) UNSIGNED AUTO_INCREMENT, address VARCHAR(255) NOT NULL DEFAULT '', forwarding VARCHAR(255) NOT NULL DEFAULT '', domain VARCHAR(255) NOT NULL DEFAULT '', dest_domain VARCHAR(255) NOT NULL DEFAULT '', is_list TINYINT(1) NOT NULL DEFAULT 0, is_forwarding TINYINT(1) NOT NULL DEFAULT 0, is_alias TINYINT(1) NOT NULL DEFAULT 0, active TINYINT(1) NOT NULL DEFAULT 1, PRIMARY KEY (id), UNIQUE INDEX (address, forwarding), INDEX (domain), INDEX (dest_domain), INDEX (is_list), INDEX (is_alias) ) ENGINE=InnoDB;
и alias_moderators в базу vmail (опционально):
mysql -uroot -p use vmail; CREATE TABLE IF NOT EXISTS alias_moderators ( id BIGINT(20) UNSIGNED AUTO_INCREMENT, address VARCHAR(255) NOT NULL DEFAULT '', moderator VARCHAR(255) NOT NULL DEFAULT '', domain VARCHAR(255) NOT NULL DEFAULT '', dest_domain VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY (id), UNIQUE INDEX (address, moderator), INDEX (domain), INDEX (dest_domain) ) ENGINE=InnoDB;
Затем закачаем скрипт по миграции пользовательских аккаунтов и запустим его. Данный скрипт делает запрос к MySQL базе "vmail" и производит миграцию (копирование) почтовых акаунтов из основной таблицы mailbox в таблицу псевдонимов - alias:
cd /root/ wget https://bitbucket.org/zhb/iredmail/raw/default/iRedMail/tools/migrate_sql_alias_table.py python migrate_sql_alias_table.py
Но миграция не происходит т.к. скрипт ругается на отсутствующие поля в таблице alias, а именно: islist, is_alias.
python migrate_sql_alias_table.py * Read SQL username/password from iRedAdmin config file: /usr/share/apache2/iredadmin/settings.pyc * Backend: mysql Traceback (most recent call last): File "migrate_sql_alias_table.py", line 65, in <module> records = db.select('alias', what='address,goto,moderators,domain,active,islist,is_alias') File "/usr/lib/python2.7/dist-packages/web/db.py", line 682, in select return self.query(qout, processed=True) File "/usr/lib/python2.7/dist-packages/web/db.py", line 644, in query self._db_execute(db_cursor, sql_query) File "/usr/lib/python2.7/dist-packages/web/db.py", line 587, in _db_execute out = cur.execute(query, params) File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 174, in execute self.errorhandler(self, exc, value) File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler raise errorclass, errorvalue _mysql_exceptions.OperationalError: (1054, "Unknown column 'islist' in 'field list'")
Почему данных полей у меня нет, сказать сложно, возможно версия старая или в предыдущих обновлениях что-то где-то не дописал. Тем не менее не сложно добавить эти поля вручную:
mysql -uroot -p USE vmail; ALTER TABLE `alias` ADD `islist` TINYINT(1) NOT NULL DEFAULT 0; ALTER TABLE `alias` ADD `is_alias` TINYINT(1) NOT NULL DEFAULT 0; \q
И повторно запустить скрипт:
python migrate_sql_alias_table.py
И вуаля, надпись "Done", говорит о том, что миграция завершилась успешно.
Теперь, сообщим postfix о новых таблицах, выполнив:
cd /etc/postfix/mysql/ perl -pi -e 's#alias\.address#forwardings.address#g' *.cf perl -pi -e 's#alias\.goto#forwardings.forwarding#g' *.cf perl -pi -e 's#alias\.active#forwardings.active#g' *.cf perl -pi -e 's#alias\.domain#forwardings.domain#g' *.cf perl -pi -e 's#alias,#forwardings,#g' *.cf service postfix restart
И напоследок грохнем ранее созданные и неиспользуемые столбцы SQL в таблице alias, базе vmail:
mysql -uroot -p USE vmail; DELETE FROM alias WHERE islist <> 1; DELETE FROM alias WHERE address=domain; ALTER TABLE alias DROP COLUMN goto; ALTER TABLE alias DROP COLUMN moderators; ALTER TABLE alias DROP COLUMN islist; ALTER TABLE alias DROP COLUMN is_alias; \q
11) Послесловие
Как видим процесс обновления почтового сервера iRedMail, не самая простая и тривиальная задача, требующая внимательности и глубокого понимания работы всей системы в целом :) Особенно актуально, когда после N-го количества обновлений по инструкции должен быть один результат, а у тебя может быть совершенно другой. Поэтому при выходе последующих новых версий я решил более не заниматься апгрейдом системы, а сразу переносить конфигурацию со старого сервера на новый, как это было ранее описано в заметке. Возможно так будет быстрее и точнее в плане соответствия конфигурации от разработчиков.