Postfix + ヴァーチャルドメイン(VDAパッチ+MySQL) + POP3/IMAP4/SMTP-auth(Dovecot)

  • qmailがシンプルで好きだったけれど、RFC的にもスループット的にも迷惑メール対策的にも、限界を感じ始めたので、時代の流れでPostfixに移行中。
    • とりあえず無難なMTAであること。
      • qmailはsendmailを、Postfixはqmailを参考として作られたらしいので、Postfixが一番いいとこ取りしていると思った。
      • Courier-MTAもあったが、パッケージが複雑化していたり、うまくコンパイルできないことがあったので、却下した。
    • ヴァーチャルドメインをそれぞれのドメイン毎に利用者に権限譲渡(アカウント追加・削除)ができ、それぞれのヴァーチャルドメインが干渉しないこと。
      • qmailが一番構築しやすかったが、qmail事態が時代に合っていなかったので、PostfixをソースからコンパイルしてVDAパッチ当てすることとした。
    • MLを構築できること。
      • できればSubjectにPrefixと番号を振ることができるようにしたかったので、Mailmanを選んだ。
  • written by member/すながわひろゆき
    • とりあえず実践仕様に書き直し中。
    • とりあえずPostfix + VDAパッチ + ClamAVまで完成。fmlは一つのサーバでは無理な予感。2014/11/12

前提条件

  • CentOS 6.4 x86_64 minimal
    • Apache
    • selinux無効化(未だに手懐けていないだけ)

Postfix + VDA

  • 役割
    • SMTPサーバ。
    • ヴァーチャルドメインやSMTP-authに対応するためにVDAパッチを導入する。
  • CentOS標準のPostfixをアンインストール
    yum remove postfix
  • CentOS 6.4 minimal で足りないパッケージをインストール。
    yum install yum-utils wget rpm-build db4-devel zlib-devel openssl-devel make
    gcc-c++ sudo openldap-devel cyrus-sasl-devel pcre-devel mysql-devel cronie
    sysstat
    • 1行で。
  • メール専用のユーザとメールボックスのディレクトリを作成
    groupadd -g 10000 vuser
    useradd -g vuser -u 10000 vuser
    mkdir /home/vuser/virtual
    chown vuser:vuser /home/vuser/virtual
    chmod 771 /home/vuser/virtual
    • メールボックスディレクトリは/home/vuser/virtualにした。何となくqmailの流れで。
  • PostfixのSRPMを展開
    rpm -ivh postfix-2.6.6-2.2.el6_1.src.rpm
    • ホームディレクトリのrpmbuildに展開される。
  • VDAパッチダウンロードとパッチ当て
    cd /root/rpmbuild
    wget http://vda.sourceforge.net/VDA/postfix-2.6.5-vda-ng.patch.gz
    wget http://vda.sourceforge.net/VDA/postfix-2.6.5-vda-ng-bigquota.patch.gz
    gunzip postfix-2.6.5-vda-ng.patch.gz
    mv postfix-2.6.5-vda-ng.patch SOURCES/
    cd SPECS/
  • postfix.spec(SRPMにVDAパッチを適用)(変更点付近のみ)
    (略)
    Release: 2.2_VDA%{?dist}
    Epoch: 3
    (略)
    Patch10: postfix-2.6.6-CVE-2011-0411.patch
    Patch11: postfix-2.6.6-CVE-2011-1720.patch
    Patch12: postfix-2.6.5-vda-ng.patch
    Patch13: postfix-2.6.5-vda-ng-bigquota.patch
    (略)
    %patch10 -p1 -b .CVE-2011-0411
    %patch11 -p1 -b .CVE-2011-1720
    %patch12 -p1 -b .VDA
    %patch13 -p1 -b .vda-ng-bigquota
    (略)
  • SRPMをコンパイルしてRPM化
    rpmbuild -ba postfix.spec
    • ホームディレクトリのrpmbuild/RPMS/(アーキテクチャ)以下にrpmができあがる。
    • 同時にログ解析postfix-perl-scriptsもできあがる。必要ならこれもインストール。
  • インストール
    cd ../RPMS/x86_64
    rpm -ivh postfix-2.6.6-2.2_VDA.el6.x86_64.rpm
  • テスト
    • VDAパッチが適用されているか確認
      postconf|grep virtual_maildir_
      • 何か出てくれば適用されているということ。
  • yumでPostfixがアップデートされないように除外する。
    • /etc/yum.conf
      exclude=postfix*
  • 設定
    • /etc/postfix/main.cf(変更点のみ)
      # サーバホスト名
      #myhostname = host.domain.tld
      #myhostname = virtual.domain.tld
      myhostname = mail.example.com
      
      # 自ドメイン
      #mydomain = domain.tld
      mydomain = example.com
      
      # ドメイン省略時のドメイン
      #myorigin = $myhostname
      myorigin = $mydomain
      
      # SMTPを受け付ける帯域
      inet_interfaces = all # どこからでも
      #inet_interfaces = $myhostname
      #inet_interfaces = $myhostname, localhost
      #inet_interfaces = localhost # 送信専用となる
      
      # バックアップMTAのみ設定(NATアドレス・グローバルアドレスを指定)
      #proxy_interfaces =
      
      # 受信するドメイン(バーチャルドメインで指定されるので空で良い)
      #mydestination = $myhostname, localhost.$mydomain, localhost
      #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
      #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
      #       mail.$mydomain, www.$mydomain, ftp.$mydomain
      mydestination =
      
      # 信頼するネットワーク帯域(今回ではSMTP-auth無しでもリレーを受け付けるようになる)
      #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
      
      # メールボックス形式
      #home_mailbox = Mailbox
      home_mailbox = Maildir/
      
      
      # 以下、ヴァーチャルドメインに関する設定を追記
      # 基本的にunixユーザではなく、Postfix内部で仮想的に作ったユーザに配送する。
      
      # メールの配送エージェント
      local_transport = local
      virtual_transport = virtual
      
      # メールボックスのパス
      virtual_mailbox_base = /home/vuser/virtual
      
      # エイリアスのリスト
      virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
      virtual_alias_domains = $virtual_alias_maps
      
      # メールボックスやドメインのリスト
      virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
      virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
      
      # メールを配送するUIDの最小値
      virtual_minimum_uid = 10000
      
      # ヴァーチャルメールのユーザIDやグループID
      virtual_uid_maps = static:10000
      virtual_gid_maps = static:10000
      
      
      # 以下、quotaに関する設定を追記
      virtual_create_maildirsize = yes
      virtual_maildir_extended = yes
      virtual_mailbox_limit_maps = mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
      virtual_mailbox_limit_override = yes
      virtual_overquota_bounce = no
      virtual_trash_count = no
      
      
      # 以下、SMTP-authに関する設定を追記
      smtpd_sasl_auth_enable = yes
      smtpd_sasl_type = dovecot
      smtpd_sasl_path = private/auth
      smtpd_sasl_local_domain = $myhostname
      smtpd_client_restrictions = reject_rbl_client bl.spamcop.net
      smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
      smtpd_sasl_security_options = noanonymous
      broken_sasl_auth_clients = yes
  • /etc/postfix/mysql_virtual_alias_maps.cf
    user = postfix
    password = postfixdbpasswd
    hosts = localhost
    dbname = postfix
    table = alias
    select_field = goto
    where_field = address
    • passwordに、MySQLのDB Postfixに設定したパスワード。以下同様。
  • /etc/postfix/mysql_virtual_domains_maps.cf
    user = postfix
    password = postfixdbpasswd
    hosts = localhost
    dbname = postfix
    table = domain
    select_field = domain
    where_field = domain
  • /etc/postfix/mysql_virtual_mailbox_maps.cf
    user = postfix
    password = postfixdbpasswd
    hosts = localhost
    dbname = postfix
    table = mailbox
    select_field = maildir
    where_field = username
  • /etc/postfix/mysql_virtual_mailbox_limit_maps.cf
    user = postfix
    password = postfixdbpasswd
    hosts = localhost
    dbname = postfix
    table = mailbox
    select_field = quota
    where_field = username
  • サブミッションポート(587)の有効化
    • /etc/postfix/master.cf
      submission inet n       -       n       -       -       smtpd
      #  -o smtpd_tls_security_level=encrypt
        -o smtpd_sasl_auth_enable=yes
        -o smtpd_client_restrictions=permit_sasl_authenticated,reject
      #  -o milter_macro_daemon_name=ORIGINATING

MySQL

  • 役割
    • Postfixのユーザ(メールボックス)情報の管理
  • MySQL本体をインストールする。
  • phpMyAdminをインストールする(任意:メンテが楽だから)
  • Postfix用ユーザとDBを作る。
    • ユーザ postfix, DB postfix, パスワードはpostfixdbpasswdとした。

PostfixAdmin

  • 役割
    • WebGUIでドメインやメールボックスの追加削除を行う。
  • phpの必須モジュールをインストール。
    yum install php-mysql php-imap
    • phpMyAdminでphp-mbstring php-mysqlもインストールしている。
  • インストール
    tar zxvf postfixadmin-2.3.6.tar.gz
    mv postfixadmin-2.3.65 /var/www/html/postfixadmin
    cd /var/www/html/postfixadmin
  • 設定
    • config.local.php (本来はconfig.inc.phpを編集すべきだが、上書き設定が可能なファイルに記述。将来バージョンアップした場合に設定を上書きしてしまわないように。)
      <?php
      // 設定済みフラグ
      $CONF['configured'] = true;
      
      // セットアップで使用するパスワード(ただし、後ほど書き直す必要がある)
      $CONF['setup_password'] = 'postfixadminpassword';
      
      // postfixadminのログインページ(管理者向け)
      $CONF['postfix_admin_url'] = 'http://example.com/postfixadmin';
      
      // 言語
      $CONF['default_language'] = 'ja';
      
      // MySQL DB
      $CONF['database_type'] = 'mysql';
      $CONF['database_host'] = 'localhost';
      //$CONF['database_host'] = '192.168.0.2:3308';
      $CONF['database_user'] = 'postfix';
      $CONF['database_password'] = 'postfixdbpasswd';
      $CONF['database_name'] = 'postfix';
      
      // 管理者メールアドレス
      $CONF['admin_email'] = 'test@example.com';
      
      // パスワードの暗号化方式
      $CONF['encrypt'] = 'md5crypt';
      
      // 1ページあたりのユーザ表示数
      $CONF['page_size'] = '100';
      
      // 各ドメインの標準エイリアス
      $CONF['default_aliases'] = array (
          'abuse' => 'abuse@change-this-to-your.domain.tld',
          'hostmaster' => 'hostmaster@change-this-to-your.domain.tld',
          'postmaster' => 'postmaster@change-this-to-your.domain.tld',
          'webmaster' => 'webmaster@change-this-to-your.domain.tld'
      );
      
      // メールボックスにドメイン名を付加
      $CONF['domain_path'] = 'YES';
      $CONF['domain_in_mailbox'] = 'YES';
      
      // デフォルトのドメインに関する制限
      $CONF['aliases'] = '100';
      $CONF['mailboxes'] = '100';
      $CONF['maxquota'] = '200'; // MB
      // クオータを強制する
      $CONF['quota'] = 'NO';
      
      // Fetchmailタブを表示
      $CONF['fetchmail'] = 'NO';
      
      // ヘッダテキスト
      $CONF['show_header_text'] = 'NO';
      $CONF['header_text'] = ':: Postfix Admin ::';
      
      // 一般ユーザログイン時のフッタリンク
      $CONF['user_footer_link'] = "http://example.com/postfixadmin/main";
      
      // フッタテキスト
      $CONF['show_footer_text'] = 'YES';
      $CONF['footer_text'] = 'Postfix Admin Top';
      $CONF['footer_link'] = 'http://example.com/postfixadmin/';
      
      // メールボックスやエイリアス作成時にドメインをチェックする
      $CONF['emailcheck_resolve_domain']='NO';
      
      // メールボックスやドメイン削除時のフォルダ削除スクリプト
      $CONF['mailbox_postdeletion_script'] = 'sudo -u vuser /home/vuser/virtual/bin/p
      ostfixadmin-mailbox-postdeletion.sh';
      $CONF['domain_postdeletion_script'] = 'sudo -u vuser /home/vuser/virtual/bin/po
      stfixadmin-domain-postdeletion.sh';
      
      ?>
    • $CONF['domain_in_mailbox'] = 'YES';がいつの間にか増えてる気がする。。。
  • メールボックスとドメイン削除時のフォルダ削除スクリプト
    mkdir /home/vuser/virtual/bin
    cp ADDITIONS/*.sh /home/vuser/virtual/bin
    chown -R vuser:vuser /home/vuser/virtual/bin
    chmod 700 /home/vuser/virtual/bin/*.sh
    mkdir /home/vuser/virtual/deleted-maildirs
    chown vuser:vuser /home/vuser/virtual/deleted-maildirs
  • /home/vuser/virtual/bin/postfixadmin-mailbox-postdeletion.sh(変更点のみ)
    #basedir=/var/spool/maildirs
    basedir=/home/vuser/virtual
    
    #trashbase=/var/spool/deleted-maildirs
    trashbase=/home/vuser/virtual/deleted-maildirs
    
    #subdir=`echo "$1" | sed 's/@.*//'`
    subdir=`echo "$1" | sed 's/@/\@/'`
  • /home/vuser/virtual/bin/postfixadmin-domain-postdeletion.sh(変更点のみ)
    #basedir=/var/spool/maildirs
    basedir=/home/vuser/virtual
    
    #trashbase=/var/spool/deleted-maildirs
    trashbase=/home/vuser/virtual/deleted-maildirs
  • visudo(フォルダ削除スクリプトがsudoするための設定)(変更点のみ)
    #Defaults    requiretty
    
    apache ALL=(vuser) NOPASSWD: /home/vuser/virtual/bin/*.sh
  • SuEXECしているならphpセッションパスに気をつけたり、パーミッションに気をつけること。
  • 管理者アカウントの設定
    • http://example.com/postfixadmin/setup.php
      • Setup passwordには、$CONF['setup_password']で設定したパスワードを入力するが、そもそも$CONF['setup_password']は平文は許可されていない。そのため、赤文字で怒られる。
      • そのエラーの中に、ハッシュ化されたパスワードが表示されているので、それを再度$CONF['setup_password']に設定する。
    • ログインできることを確認する
  • セットアップ用ファイルを削除する。
    mv setup.php setup.php_
  • postfixadminにユーザログイン時の注意書きを表示されないようにする
    mv motd-users.txt motd-users.txt_
  • postfixadminに管理者ログイン時の注意書きを表示されないようにする
    mv motd.txt motd.txt_

Dovecot

  • 役割
    • POP3とIMAP4
    • SMTP-authの認証
  • Dovecot本体とMySQLモジュールのインストール
    yum install dovecot dovecot-mysql
  • 設定(/etc/dovecot/conf.d/の中を舐める仕様のため、dovecot.confはいじらない)
    • /etc/dovecot/conf.d/00-base.conf
      listen = *, ::
      disable_plaintext_auth = no
      auth_mechanisms = PLAIN LOGIN CRAM-MD5
      mail_location = maildir:/home/vuser/virtual/%d/%n@%d
      first_valid_uid = 10000
      first_valid_gid = 10000
      mail_plugins = quota
      login_greeting = Dovecot ready.
      
      protocols = pop3 imap
      protocol imap {
        imap_client_workarounds = delay-newmail tb-extra-mailbox-sep
        mail_plugins = $mail_plugins imap_quota
      }
      protocol pop3 {
        pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
      }
      passdb {
        driver = sql
        args = /etc/dovecot/dovecot-sql.conf
      }
      userdb {
        driver = sql
        args = /etc/dovecot/dovecot-sql.conf
      }
      service auth {
        unix_listener /var/spool/postfix/private/auth {
          mode = 0666
        }
      }
      plugin {
        quota = maildir:User quota
      }
  • /etc/dovecot/conf.d/10-auth.conf
    #!include auth-system.conf.ext
  • /etc/dovecot/dovecot-sql.conf
    driver = mysql
    default_pass_scheme = MD5-CRYPT
    connect = dbname=postfix user=postfix host=/var/lib/mysql/mysql.sock password=postfixdbpasswd
    password_query = SELECT password FROM mailbox WHERE username = '%n\@%d' AND active = '1'
    user_query = SELECT concat('/home/vuser/virtual/', maildir) as home, 10000 as uid, 10000 as gid FROM mailbox WHERE username = '%n\@%d' AND active = '1'
  • テスト
    • doveconf -nで規定値からの変更点のみを表示してくれる。

起動とテスト

  • Dovecot起動
    /etc/init.d/dovecot start
    chkconfig dovecot on
  • Postfix起動
    /etc/init.d/postfix start
    chkconfig postfix on
  • メールアドレス作成
    • PostfixAdminにログイン
    • ドメイン一覧からドメインを追加する
      • /home/vuser/virtual/にドメイン名のディレクトリができあがる。
    • アドレス一覧からアドレスを追加する
      • まずは$CONF['admin_email']の管理者メールアドレスを作成すること。
      • /home/vuser/virtual/ドメイン名)/にメールアドレスのディレクトリができあがる。(ようこそメールの送信を指定するか、1通目のメールが配送されたタイミングで作成される)
  • 配送や送受信のテスト
    • メールクライアントから送信したり受信したり。
    • SMTPauth無しでSMTPして送信できないことと、SMTPauth有りでSMTPして送信できることを確認。なお、Postfixのmain.cfのmynetworksで指定したネットワークからはSMTPauthしなくても送信できる。

Tips

バウンスメールテンプレート

  • バウンスメール(自動返信)は、Postfixのテンプレートをいじると変更できる。
    • /etc/postfix/main.cf
      bounce_template_file = /etc/postfix/bounce.cf
    • テンプレをコピーする
      cp /usr/share/doc/postfix-2.6.6/bounce.cf.default /etc/postfix/bounce.cf
    • いじる。

メールサイズ上限の設定

  • メール1通あたりのサイズ上限を変更する。
    • vi /etc/postfix/main.cf
      message_size_limit = 20480000
    • デフォルトは10240000(10MB)
    • postconf -dしてもなぜか変更が反映されてないように見えるが、実際は反映されているのは何故?

参考