この記事はPostfix Advent Calendar 2014の8日目の記事です。
ConoHaの薄い本 Vol2「メールサーバーを立てよう」がホント最低限しか書かれてないので迷惑メールを減らす仕組みとWebメールを追加してそこそこ使えるようにしてみようというコンセプトです。
初期インストールからやる感じなのでConoHaの薄い本から変更する場合はいろいろお察しください。

環境

  • ConoHaで検証(このはちゃん清楚あざとかわいい)
  • CentOS6.6
  • selinuxはdisabled(石川さんごめんなさい)
  • iptablesは必要最低限(ssh:22, SMTP:25, HTTPS:443)
  • 作業はrootで
  • ドメイン名は mail.test.zumwalt.info を使う
  • DNSのAレコード、MXレコード、逆引きは設定済み

リポジトリ インストール

epel, remi, milter, MySQL のリポジトリ

yum install http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum install http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
yum install http://sourceforge.net/projects/milter-manager/files/centos/milter-manager-release-1.2.0-1.noarch.rpm
yum install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm

postfix インストール

※ デフォルトでインストール済みのはず

yum install postfix

設定は後で。

milter

milterで迷惑メール対策をするためにインストール。

milter-greylist インストール

yum install milter-greylist

milter manager インストール

yum install milter-manager

milter-greylist 設定

  • IPアドレスのマッチには前半24ビットのみを使う(送信元が複 数のMTAを利用している場合のGreylistの悪影響を抑えるため)
  • 再送チェック時間を30分後(デフォルト)から10分後に短くす る(Greylistの悪影響を抑えるため)
  • オートホワイトリストの期間を1日(デフォルト)から1週間に 伸ばす(Greylistの悪影響を抑えるため)
  • デフォルトでGreylistを使う

/etc/mail/greylist.conf を修正

--- /etc/mail/greylist.conf.orig        2014-01-09 20:24:46.000000000 +0900
+++ /etc/mail/greylist.conf     2014-09-10 16:47:44.618000113 +0900
@@ -6,7 +6,7 @@
 #
 
 #pidfile "/var/run/milter-greylist.pid"
-socket "/var/run/milter-greylist/milter-greylist.sock"
+socket "/var/run/milter-greylist/milter-greylist.sock" 660
 dumpfile "/var/lib/milter-greylist/db/greylist.db" 600
 geoipdb "/usr/share/GeoIP/GeoIP.dat"
 dumpfreq 1
@@ -139,7 +139,11 @@
 #               msg "Sender IP caught in NJABL blacklist"
 #racl greylist list "grey users" dnsrbl "SORBS DUN" delay 24h autowhite 3d
 racl greylist list "grey users" delay 30m autowhite 3d
-racl whitelist default
+subnetmatch /24
+greylist 10m
+autowhite 1w
+#racl whitelist default
+racl greylist default
 
 # Example of content filtering for fighting image SPAM
 #dacl blacklist body /src[:blank:]*=(3D)?[:blank:]*["']?[:blank:]*cid:/ \

権限付与

chmod +rx /var/run/milter-greylist/

milter-greylist 起動

chkconfig milter-greylist on
/etc/init.d/milter-greylist start

milter-manager 設定

usermod -G grmilter -a milter-manager

milter-managerから認識されているか確認

milter-manager --show-config | egrep 'define_milter|milter.connection_spec|milter.enabled'
define_milter("milter-greylist") do |milter|
  milter.connection_spec = "unix:/var/run/milter-greylist/milter-greylist.sock"
  milter.enabled = true

milter-manager 起動

/etc/init.d/milter-manager restart
chkconfig milter-manager on

起動試験

sudo -u milter-manager milter-test-server -s unix:/var/run/milter-manager/milter-manager.sock
  status: accept
  elapsed-time: 0.00442549 seconds

Postfixadmin

ユーザー管理にPostfixAdminを使えるようにする

MySQLインストール・設定

MySQLインストール

yum install mysql-community-server mysql-community-devel

/etc/my.cnf を修正

--- /etc/my.cnf.orig    2014-07-24 23:04:01.000000000 +0900
+++ /etc/my.cnf 2014-09-11 10:01:09.178998182 +0900
@@ -20,6 +20,11 @@
 datadir=/var/lib/mysql
 socket=/var/lib/mysql/mysql.sock
 
+innodb_buffer_pool_size = 256M
+innodb_buffer_pool_instances = 2
+innodb_file_per_table = 1
+innodb_flush_log_at_trx_commit=2
+
 # Disabling symbolic-links is recommended to prevent assorted security risks
 symbolic-links=0

MySQL起動

/etc/init.d/mysqld start 
chkconfig mysqld on

MySQL初期設定

mysql_secure_installation

ガイドにしたがって初期設定を実施する。

httpd インストール・設定

yum install httpd php mod_ssl php-mysql php-mbstring php-imap

証明書作成

mkdir /usr/local/src/ssl
cd /usr/local/src/ssl
openssl md5 /var/log/* > rand.dat
openssl genrsa -rand rand.dat 2048 > server.key
openssl req -new -key server.key > server.csr
※質問には適当に
openssl x509 -in server.csr -days 3650 -req -signkey server.key > server.crt
mkdir /etc/httpd/ssl
cp server.crt server.key /etc/httpd/ssl/.
chmod 600 /etc/httpd/ssl/server.key

/etc/httpd/conf.d/ssl.conf を修正

--- /etc/httpd/conf.d/ssl.conf.orig     2014-12-08 17:16:27.982999836 +0900
+++ /etc/httpd/conf.d/ssl.conf  2014-12-08 17:18:04.133999953 +0900
@@ -76,6 +76,7 @@
 # General setup for the virtual host, inherited from global configuration
 #DocumentRoot "/var/www/html"
 #ServerName www.example.com:443
+ServerName mail.test.zumwalt.info:443
 
 # Use separate log files for the SSL virtual host; note that LogLevel
 # is not inherited from httpd.conf.
@@ -102,14 +103,14 @@
 # the certificate is encrypted, then you will be prompted for a
 # pass phrase.  Note that a kill -HUP will prompt again.  A new
 # certificate can be generated using the genkey(1) command.
-SSLCertificateFile /etc/pki/tls/certs/localhost.crt
+SSLCertificateFile /etc/httpd/ssl/server.crt
 
 #   Server Private Key:
 #   If the key is not combined with the certificate, use this
 #   directive to point at the key file.  Keep in mind that if
 #   you've both a RSA and a DSA private key you can configure
 #   both in parallel (to also allow the use of DSA ciphers, etc.)
-SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
+SSLCertificateKeyFile /etc/httpd/ssl/server.key
 
 #   Server Certificate Chain:
 #   Point SSLCertificateChainFile at a file containing the
@@ -124,7 +125,7 @@
 #   Set the CA certificate verification path where to find CA
 #   certificates for client authentication or alternatively one
 #   huge file containing all of them (file must be PEM encoded)
-#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
+SSLCACertificateFile /etc/httpd/ssl/server.crt
 
 #   Client Authentication (Type):
 #   Client certificate verification type and depth.  Types are

PostfixAdmin DB作成

# mysql -u root -p
Enter password: MySQLのrootパスワード
mysql> CREATE DATABASE postfix;
mysql> CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'postfixadminのDBのパスワード';
mysql> GRANT ALL PRIVILEGES ON `postfix` . * TO 'postfix'@'localhost';
mysql> quit

iptables 設定

iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
/etc/init.d/iptables save
/etc/init.d/iptables restart

PostfixAdmin インストール・設定

mkdir /usr/local/src/postfixadmin
cd /usr/local/src/postfixadmin
wget http://jaist.dl.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-2.92/postfixadmin-2.92.tar.gz
tar zxvf postfixadmin-2.92.tar.gz 
mv postfixadmin-2.92 /var/www/html/postfixadmin

/var/www/html/postfixadmin/config.inc.php の修正

--- /var/www/html/postfixadmin/config.inc.php.orig      2014-12-08 17:21:49.663001849 +0900
+++ /var/www/html/postfixadmin/config.inc.php   2014-12-08 17:23:42.051005753 +0900
@@ -22,7 +22,7 @@
  * Doing this implies you have changed this file as required.
  * i.e. configuring database etc; specifying setup.php password etc.
  */
-$CONF['configured'] = false;
+$CONF['configured'] = true;
 
 // In order to setup Postfixadmin, you MUST specify a hashed password here.
 // To create the hash, visit setup.php in a browser and type a password into the field,
@@ -31,7 +31,7 @@
 
 // Language config
 // Language files are located in './languages', change as required..
-$CONF['default_language'] = 'en';
+$CONF['default_language'] = 'ja';
 
 // Hook to override or add translations in $PALANG
 // Set to the function name you want to use as hook function (see language_hook example function below)
@@ -83,7 +83,7 @@
 $CONF['database_type'] = 'mysqli';
 $CONF['database_host'] = 'localhost';
 $CONF['database_user'] = 'postfix';
-$CONF['database_password'] = 'postfixadmin';
+$CONF['database_password'] = 'PostfixAdminのDBのパスワード';
 $CONF['database_name'] = 'postfix';
 // If you need to specify a different port for a MYSQL database connection, use e.g.
 //   $CONF['database_host'] = '172.30.33.66:3308';

権限付与と起動

cd /var/www/html
chown -R .apache postfixadmin/
chmod 770 postfixadmin/
/etc/init.d/httpd start
chkconfig httpd on

PostfixAdmin 初期設定

https://IPアドレスorホスト名/postfixadmin/setup.php

ex) https://mail.test.zumwalt.info/postfixadmin/setup.php

に接続して設定

setup password を設定

DB等が設定された後の画面に表示されたsetup_passwordを、/var/www/html/postfixadmin/config.inc.php のsetup_password に登録する。

$CONF[‘setup_password’] = ‘changeme’;

$CONF[‘setup_password’] = ‘hogehogehogeohoegogoegogoeogeogeogeoegoegogeo’;

管理者登録

PostfixAdmin 管理

https://IPアドレスorホスト名/postfixadmin/login.php

ex) https://mail.test.zumwalt.info/postfixadmin/login.php

上記で登録した管理者アカウントにてログイン

管理ドメイン追加

ユーザー(メールアドレス)追加

Postfix 設定

PostfixAdmin のアカウント連携設定

/etc/postfix/main.cf の修正

--- /etc/postfix/main.cf.orig   2014-09-10 17:14:53.140000056 +0900
+++ /etc/postfix/main.cf        2014-10-14 18:16:42.135004759 +0900
@@ -74,6 +74,7 @@
 #
 #myhostname = host.domain.tld
 #myhostname = virtual.domain.tld
+myhostname = mail.test.zumwalt.info
 
 # The mydomain parameter specifies the local internet domain name.
 # The default is to use $myhostname minus the first component.
@@ -81,9 +82,10 @@
 # parameters.
 #
 #mydomain = domain.tld
+mydomain = test.zumwalt.info
 
 # SENDING MAIL
@@ -95,7 +97,7 @@
 # myorigin also specifies the default domain name that is appended
 # to recipient addresses that have no @domain part.
 #
-#myorigin = $myhostname
+myorigin = $myhostname
 #myorigin = $mydomain
 
 # RECEIVING MAIL
@@ -110,13 +112,14 @@
 #
 # Note: you need to stop/start Postfix when this parameter changes.
 #
-#inet_interfaces = all
+inet_interfaces = all
 #inet_interfaces = $myhostname
 #inet_interfaces = $myhostname, localhost
-inet_interfaces = localhost
+#inet_interfaces = localhost
 
 # Enable IPv4, and IPv6 if supported
-inet_protocols = all
+#inet_protocols = all
+inet_protocols = ipv4
 
 # The proxy_interfaces parameter specifies the network interface
 # addresses that this mail system receives mail on by way of a
@@ -161,10 +164,11 @@
 #
 # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
 #
-mydestination = $myhostname, localhost.$mydomain, localhost
+#mydestination = $myhostname, localhost.$mydomain, localhost
 #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
 #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
 #      mail.$mydomain, www.$mydomain, ftp.$mydomain
+mydestination = $myhostname
 
 # REJECTING MAIL FOR UNKNOWN LOCAL USERS
 #
@@ -264,6 +268,7 @@
 #mynetworks = 168.100.189.0/28, 127.0.0.0/8
 #mynetworks = $config_directory/mynetworks
 #mynetworks = hash:/etc/postfix/network_table
+mynetworks = 127.0.0.0/8, 自ホストのグローバルIP
 
 # The relay_domains parameter restricts what destinations this system will
 # relay mail to.  See the smtpd_recipient_restrictions description in
@@ -293,7 +298,7 @@
 # list this system as their primary or backup MX host. See the
 # permit_mx_backup restriction description in postconf(5).
 #
-#relay_domains = $mydestination
+relay_domains = $mydestination
 
 # INTERNET OR INTRANET
 
@@ -416,8 +421,8 @@
 # "Maildir/" for qmail-style delivery (the / is required).
 #
 #home_mailbox = Mailbox
-#home_mailbox = Maildir/
- 
+home_mailbox = Maildir/
+
 # The mail_spool_directory parameter specifies the directory where
 # UNIX-style mailboxes are kept. The default setting depends on the
 # system type.
@@ -568,6 +573,7 @@
 #
 #smtpd_banner = $myhostname ESMTP $mail_name
 #smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
+smtpd_banner = popopo-n
 
 # PARALLEL DELIVERY TO THE SAME DESTINATION
 #
@@ -675,8 +681,30 @@
 #
 readme_directory = /usr/share/doc/postfix-2.6.6/README_FILES
 
+# virtual
+local_transport = local
+virtual_transport = dovecot
+virtual_mailbox_base = /home/vuser
+virtual_minimum_uid = 10000
+virtual_uid_maps = static:10000
+virtual_gid_maps = static:10000
+
+virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
+virtual_alias_domains = $virtual_alias_maps
+
+virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
+virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
+virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
+virtual_mailbox_limit = 0
+
+milter_protocol = 6
+milter_default_action = accept
+milter_mail_macros = {auth_author} {auth_type} {auth_authen}
+
+smtpd_milters = unix:/var/run/milter-manager/milter-manager.sock
+
+unknown_local_recipient_reject_code = 550
+unknown_address_reject_code = 450
+unverified_recipient_reject_code = 550
+message_size_limit = 20480000
+mailbox_size_limit = 20480000

/etc/postfix/mysql_virtual_alias_maps.cfを新規に作成

cat /etc/postfix/mysql_virtual_alias_maps.cf

user = postfix
password = PostfixAdminのDBのパスワード
hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address

/etc/postfix/mysql_virtual_domains_maps.cfを新規に作成

cat /etc/postfix/mysql_virtual_domains_maps.cf

user = postfix
password = PostfixAdminのDBのパスワード
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain

/etc/postfix/mysql_virtual_mailbox_limit_maps.cfを新規に作成

cat /etc/postfix/mysql_virtual_mailbox_limit_maps.cf

user = postfix
password = PostfixAdminのDBのパスワード
hosts = localhost
dbname = postfix
table = mailbox
select_field = quota
where_field = username
#additional_conditions = and active = '1'

/etc/postfix/mysql_virtual_mailbox_maps.cfを新規に作成

cat /etc/postfix/mysql_virtual_mailbox_maps.cf

user = postfix
password = PostfixAdminのDBのパスワード
hosts = localhost
dbname = postfix
table = mailbox
select_field = maildir
where_field = username

iptables 設定

iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
/etc/init.d/iptables save
/etc/init.d/iptables restart

Dovecot

Roundcube の振り分け設定が使えるようにdovecotをインストール・設定

Dovecot インストール

 yum install dovecot-devel dovecot-mysql dovecot-pigeonhole 

Dovecot 設定

/etc/dovecot/conf.d/00-base.confを新規に作成

cat /etc/dovecot/conf.d/00-base.conf


#auth_debug_passwords = yes
#auth_verbose = yes
#auth_debug = yes

listen = *
disable_plaintext_auth = no
auth_mechanisms = plain login
mail_location = maildir:%h
first_valid_uid = 10000
first_valid_gid = 10000
#mail_plugins = quota sieve

protocol imap {
  imap_client_workarounds = delay-newmail tb-extra-mailbox-sep
#  mail_plugins = $mail_plugins imap_quota sieve
}
protocol pop3 {
  pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
#protocol lmtp {
#  mail_plugins = $mail_plugins quota sieve
#}
protocol lda {
  mail_plugins = $mail_plugins quota sieve
}

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-postfixadmin-mysql.conf
}
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-postfixadmin-mysql.conf
}
service auth {
  #unix_listener /var/spool/postfix/private/auth {
  unix_listener auth-userdb {
    mode = 0666
    group = vuser
    user = vuser
  }

}
plugin {
  quota = maildir:User quota
  sieve = %h/.dovecot.sieve
  sieve_dir = %h/sieve
  sieve_global_dir = /etc/dovecot/sieve/
  sieve_global_path = /etc/dovecot/sieve/default.sieve
}

protocols = $protocols sieve

/etc/dovecot/dovecot-postfixadmin-mysql.confを新規に作成

cat /etc/dovecot/dovecot-postfixadmin-mysql.conf 

driver = mysql
connect = host=/var/lib/mysql/mysql.sock dbname=postfix user=postfix password=PostfixAdminのDBのパスワード
default_pass_scheme = MD5-CRYPT
password_query = SELECT password FROM mailbox WHERE username='%u' AND active='1'
user_query = SELECT concat('/home/vuser/', maildir) AS home, 10000 AS uid,10000 AS gid FROM mailbox WHERE username='%u' AND active='1'

ユーザー&ディレクトリ作成

groupadd -g 10000 vuser
useradd -g vuser -u 10000 -d /home/vuser vuser
chown vuser:vuser /home/vuser
chmod 771 /home/vuser

/etc/postfix/master.cf の修正

--- /etc/postfix/master.cf.orig 2014-02-20 19:07:51.000000000 +0900
+++ /etc/postfix/master.cf      2014-12-08 10:07:14.445801936 +0900
@@ -102,3 +102,6 @@
 #mailman   unix  -       n       n       -       -       pipe
 #  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
 #  ${nexthop} ${user}
+dovecot unix    -       n       n       -       -      pipe
+  flags=DRhu user=vuser:vuser argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop} -m INBOX.${extension}

起動

/etc/init.d/dovecot start
chkconfig dovecot on
/etc/init.d/postfix restart

Roundcube

Webメールシステムとして使う

roundcube インストール

yum install php-dom php-intl php-mcrypt
mkdir /usr/local/src/roundcube
cd /usr/local/src/roundcube/
wget http://downloads.sourceforge.net/project/roundcubemail/roundcubemail/1.0.3/roundcubemail-1.0.3.tar.gz
tar zxvf roundcubemail-1.0.3.tar.gz
mv roundcubemail-1.0.3 /var/www/html/roundcube
cd /var/www/html/
chown -R root:apache roundcube/
cd roundcube/
chmod 775 temp/ logs/

DB作成

mysql -u root -p
mysql> create database roundcubemail character set utf8 collate utf8_bin;
mysql> grant all privileges on roundcubemail.* to roundcubemail@localhost identified by 'roundcubemailDBのパスワード';
mysql> flush privileges;
mysql> quit

cd /var/www/html/roundcube/SQL/
mysql -u roundcubemail -p roundcubemail < mysql.initial.sql 
Enter password: roundcubemailDBのパスワード

/etc/php.ini の修正

--- /etc/php.ini.orig   2014-09-19 15:49:54.165999866 +0900
+++ /etc/php.ini        2014-09-19 15:50:15.483000234 +0900
@@ -944,6 +944,7 @@
 ; Defines the default timezone used by the date functions
 ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
 ;date.timezone =
+date.timezone = Asia/Tokyo
 
 ; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-latitude
 ;date.default_latitude = 31.7667

設定反映のためhttpd 再起動

/etc/init.d/httpd restart

Roundcube 初期設定

https://IPアドレスorホスト名/roundcube/installer/

ex) https://mail.test.zumwlat.info/roundcube/installer/

インストール確認

設定

必須項目

  • Database setup
    • Database user name:roundcubemail DBのユーザー名
    • Database password:roundcubemail DBのパスワード
  • IMAP Settings
    • username_domain:ドメイン名 ex)test.zumwalt.info
  • SMTP Settings
    • smtp_server:localhost
  • Display settings & user prefs
    • language :ja_JP

設定反映

Webで表示されたconfigを以下に書き込む

/var/www/html/roundcube/config/config.inc.php

SMTP・IMAP動作確認

postfixadminで作成したユーザーにてSMTP・IMAPの動作をチェック

インストーラー削除

rm -rf /var/www/html/roundcube/installer/

ログイン

https://アドレスorホスト名/roundcube/

ex) https://mail.test.zumwlat.info/roundcube

roundcube フィルター設定

/var/www/html/roundcube/config/config.inc.php を修正

--- /var/www/html/roundcube/config/config.inc.php.orig  2014-12-08 18:17:48.787999829 +0900
+++ /var/www/html/roundcube/config/config.inc.php       2014-12-08 20:14:44.439999479 +0900
@@ -72,10 +72,15 @@
 // PLUGINS
 // ----------------------------------
 // List of active plugins (in plugins/ directory)
-$config['plugins'] = array();
+$config['plugins'] = array('managesieve');
 
 // the default locale setting (leave empty for auto-detection)
 // RFC1766 formatted language name like en_US, de_DE, de_CH, fr_FR, pt_BR
 $config['language'] = 'ja_JP';
 
+// show up to X items in messages list view
+$config['mail_pagesize'] = 100;
+
+// show up to X items in contacts list view
+$config['addressbook_pagesize'] = 100;

これで諸々使えるはず。

なんとか今日中に間に合った…

数日分を1日にまとめたのここらへんが限界です…orz

milter の詳細な使い方とかはきっと誰かが書いてくれるはず…

明日は@satoh_fumiyasuさんのparent_domain_matches_subdomainsです。