2022/12/30(金)メールサーバの中規模改修と基礎知識(8)~ メールサーバ稼動

ここでは、このシリーズの最初で示した
20221223_mailserver_2022enhance.jpg

の構成を稼働させる記事です。ほぼ、FreeBSD固有の手順です。ただ、参考になる部分はあるかもしれません。
(Linux系は、この辺りの仕組みは全く別物なので、読み替えることが出来るスキルが必要になる)
早速、順番に示していきます。作業は root ユーザで全てを実施します。

Postfix と dovecot の起動

先ず、下記のスクリプトファイルを、/usr/local/etc/rc.d ディレクトリ配下に postfix_dovecot というファイル名で作成します。
実行権を与えるのを忘れないようにしてください:
#!/bin/sh
#
# PROVIDE: postfix-dovecot
# REQUIRE: DAEMON NETWORKING openldap
# KEYWORD: shutdown

. /etc/rc.subr

name="postfix_dovecot"
rcvar="postfix_dovecot_enable"

start_cmd="mailserver_start"
stop_cmd="mailserver_stop"
restart_cmd="mailserver_reload"

# start postfix,dovecot, and E-Mail account control server
smtpserv=/usr/local/sbin/postfix
dovecot=/usr/local/sbin/dovecot

mailserver_start()
{
echo ' '
if [ -x $dovecot ]; then
/usr/local/sbin/dovecot -c /usr/local/etc/dovecot/dovecot.conf
echo ' dovecot 2.3.19.1 '
fi

if [ -x $smtpserv ]; then
/usr/local/sbin/postfix start > /dev/null 2>&1
echo ' Postfix 3.7.3 '
fi
}

mailserver_reload()
{
/usr/local/sbin/postfix reload
/usr/local/sbin/dovecot reload
echo ' reloaded postfix and dovecot config '
}

mailserver_stop()
{
/usr/local/sbin/postfix stop
/usr/local/sbin/dovecot stop
echo ' stoped Mail server '
}

load_rc_config $name
run_rc_command "$1" 
次に /etc/rc.conf に下記の2行を追加します
# vi /etc/rc.conf
sendmail_enable="NONE"
postfix_dovecot_enable="YES"
その後で、
# cd /usr/local/etc/rc.d
# ./postfix_dovecot start
として、エラーが表示されないことを確認したら、
で、下記のタスクが動作しているのが確認出来れば、成功です:
# ps -aux | grep postfix
root           32817  ... 13692  -  Ss   03:13         0:00.00 /usr/local/libexec/postfix/master -w
postfix        32818  ... 13704  -  S    03:13         0:00.01 pickup -l -t fifo -u
postfix        32819  ... 13796  -  S    03:13         0:00.01 qmgr -l -t fifo -u
postfix        32820  ... 13840  -  S    03:13         0:00.01 tlsmgr -l -t unix -u
postfix        32821  ... 13648  -  S    03:13         0:00.01 postlogd -l -n postlog -t unix-dgram -u
※ 記事表示スペースの関係上、実際の表示項目を一部省略しています。
# ps -aux | grep dovecot
root        64526 ...   5684  -  Is   02:11         0:00.27 /usr/local/sbin/dovecot -c /usr/local/etc/dovecot/dovecot.conf
dovecot     64528 ...   5368  -  I    02:11         0:00.07 dovecot/anvil
root        64529 ...   5444  -  I    02:11         0:00.04 dovecot/log
root        64530 ...   7808  -  I    02:11         0:00.45 dovecot/config
dovecot     64995 ...   5680  -  I    02:11         0:00.08 dovecot/stats
※ 記事表示スペースの関係上、実際の表示項目を一部省略しています。

ClamAV の起動

先述の記事で、既に起動スクリプト作成までは出来ているはずなので、
/etc/rc.conf に下記の5行を追加します:
# vi /etc/rc.conf
clamav_clamd_enable="YES"
clamav_freshclam_enable="YES"
clamav_milter_enable="YES"
clamav_milter_socket_mode="660"
clamav_milter_socket_group="mailuser"
その後で、先ず、
# cd /usr/local/etc/rc.d
# ./clamav_clamd start
として、エラーが表示されないことを確認したら、
# ps -aux | grep clamav
として、下記のように /usr/local/sbin/clamd が存在することを確認します。
clamav         56967   0.0  7.7 1371840 1291000  -  Is   03:03          2:42.64 /usr/local/sbin/clamd
続いて、同じように、
# ./clamav_freshclam start
# ps -aux | grep clamav
として、下記のように /usr/local/bin/freshclam が存在することを確認、
clamav         57001   0.0  0.2   48820   30412  -  Is   03:20          0:08.24 /usr/local/bin/freshclam --daemon -p /var/run/clamav/freshclam.pid
最後に、
# ./clamav-milter start
# ps -aux | grep clamav
として、下記のように /usr/local/sbin/clamav-milter が存在することを確認します:
clamav         57009   0.0  0.2   92520   29912  -  Ss   03:22          0:03.82 /usr/local/sbin/clamav-milter -c /usr/local/etc/clamav-milter.conf
何らかの問題が発生した場合、/var/log/clamd.log, /var/log/clamav-milter.log,/var/log/freshclam.log,/var/log/maillog などに解決のヒントが記述されているので、解決を試みることになります。

OpenDKIM の起動

先述の記事で、既に起動スクリプト作成までは出来ているはずなので、
/etc/rc.conf に下記の3行を追加します:
# vi /etc/rc.conf
milteropendkim_enable="YES"
milteropendkim_cfgfile="/usr/local/etc/opendkim/opendkim.conf"
milteropendkim_socket="local:/var/run/milteropendkim/dkim-milter"
その後で、先ず、
# cd /usr/local/etc/rc.d
# ./milter-opendkim start
として、エラーが表示されないことを確認したら、
# ps -aux | grep opendkim
として、下記のように /usr/local/sbin/opendkim が存在することを確認します:
opendkim       33260   ... 12776  -  Ss   03:31          0:01.16 /usr/local/sbin/opendkim -l -p local:/var/run/milteropendkim/dkim-milter -u opendkim:mailuser -P /var/run/milteropendkim
※ 記事表示スペースの関係上、実際の表示項目を一部省略しています。

milter-manager の起動

先述の記事で、既に起動スクリプト作成までは出来ているはずなので、
/etc/rc.conf に下記の1行を追加します:
# vi /etc/rc.conf
milter_manager_enable="YES"
これで、起動準備完了なのですが、初めての場合・milter アプリケーションを追加した場合、「miiter-manager が milter アプリケーションを自動検出できるかどうか」を必ず事前確認することを強くお勧めします。
自動検出できるか否かのチェックは、
# /usr/local/sbin/milter-manager -u milter-manager --show-config
で実行でき、この時に表示される内容で、
define_milter("clamav-milter") do |milter|
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:44
  milter.connection_spec = "unix:/var/run/clamav/clmilter.sock"
  # default
  milter.description = nil
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:37
  milter.enabled = true
  # default
  milter.fallback_status = "accept"
		・
		・
       《中略》
		・
		・
define_milter("milter-opendkim") do |milter|
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:44
  milter.connection_spec = "local:/var/run/milteropendkim/dkim-milter"
  # default
  milter.description = nil
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:37
  milter.enabled = true
  # default
  milter.fallback_status = "accept"
といった内容が含まれていることと、
特に milter.enabled = true になっている点、
milter.connection_spec が示す ソケットインタフェースのファイルパスが正しく指示していることを確認します。
上記例のようになっていれば問題ありません。

その後で、先ず、
# cd /usr/local/etc/rc.d
# ./milter-manager start
として、エラーが表示されないことを確認したら、
# ps -aux | grep milter-manager
として、下記のように /usr/local/sbin/clamd が存在することを確認します。
milter-manager 31520   ...  28472  -  S    03:57          0:41.49 /usr/local/sbin/milter-manager --pid-file /var/run/milter-manager/milter-manager.pid --user-name milter-manager --group
root           31518   ...  28072  0- S    03:57          0:05.64 /usr/local/sbin/milter-manager --pid-file /var/run/milter-manager/milter-manager.pid --user-name milter-manager --group
※ 記事表示スペースの関係上、実際の表示項目を一部省略しています。

○ FreeBSD 版 milter-manager における自動検出の仕組み
単純にソースコードからインストールしただけだと、「自動検出」が可能な状態にはなりません。
ですが、milter-manager 日本語版 の説明を隅々まで眺めると、『milter アプリケーションを Ports/Packages でインストールしたことを前提としている』と書かれています。

ということは、/usr/local/etc/rc.d ディレクトリ配下に、決まった形式の起動・終了スクリプトを用意すれば、自動検出が可能になるのでは? 
ということで、試しに設置することにします。
スクリプトの雛形は 各 Ports の files ディレクトリ配下にあり、これを実運用環境に合わせて変更します。
この時、 /etc/rc.conf の変更も必要です。/etc/rc.conf の中に最低限 clamav_clamd_enable="YES" のような一文が無いと、手動で起動・停止スクリプトを実行する際にエラーを吐いて起動しないのです。

ClamAV はこれで自動検出できるようになったのですが、OpenDKIM は自動検出しません。
散々悩んだ挙句、/usr/local/etc/rc.d ディレクトリ配下に設置する、スクリプトファイル名の問題でした。

当初、opendkim_milter というファイル名で作成したのですが、これを opendkim-milier に変えたら自動検出できるようになりました。このあたりの仕組みがブラックボックスなので、悩むところです。
おそらく、各起動スクリプトの3行目 にある PROVIDE 行と実際のファイル名を一致させないと駄目なのかもしれません。
トラブル解決の際の参考になれば幸いです。

SpamAssassion の起動

先述の記事で、既に起動スクリプト作成までは出来ているはずなので、
/etc/rc.conf に下記の1行を追加します:
# vi /etc/rc.conf
spamd_enable="YES"
その後で、先ず、
# cd /usr/local/etc/rc.d
# ./sa-spamd start
として、エラーが表示されないことを確認したら、
# ps -aux | grep spamd
として、下記のように spamd が存在することを確認します。
root           49139   0.0  0.7  162040  124744  -  Ss   04:53         1:13.97 spamd (perl)
spamd          49141   0.0  0.8  162040  127988  -  I    04:53         0:03.52 spamd child (perl)
spamd          49142   0.0  0.7  162040  124816  -  I    04:53         0:00.51 spamd child (perl)

送受信のテスト

テストの前に、テストで使用する受信者のメールボックスディレクトリ直下に .dovecot.sieve のファイル名で、
下記のような sieve スクリプトを用意します。
require ["fileinto","vnd.dovecot.filter"] ;

 filter "spamass.sh" "user@example.com" ;
 # rule:[SpamAssassin]
 if header :is "X-Spam-Status" "Yes" {
    fileinto "spamdrop" ;
    stop ;
 }
 # rule:[Clamav]
 if header :is "X-Virus-Status" "Yes" {
    fileinto "spamdrop" ;
    stop ;
 }
更に、/usr/local/etc/dovecot/sieve-filter ディレクトリ配下に spamass,sh というファイル名で、下記スクリプトを用意します:
#!/bin/sh

randomid=`/usr/bin/od -An -tu4 -N4 /dev/random | /usr/bin/tr -d ' '`
tmpfname1="/var/tmp/_${randomid}_1"
tmpfname2="/var/tmp/_${randomid}_2"

while read line
do
  /bin/cat >> $tmpfname1
done

usernam=`echo -n $1 | /usr/bin/cut -d @ -f 1`
userdom=`echo -n $1 | /usr/bin/cut -d @ -f 2`

if [ -d /var/mail/${userdom}/${usernam}/spamassassin/spamd ]; then
  /usr/local/bin/spamc -u $1 < $tmpfname1 > $tmpfname2

  /bin/cat $tmpfname2
  /bin/rm $tmpfname1
  /bin/rm $tmpfname2
else
  /bin/cat $tmpfname1
  /bin/rm $tmpfname1
fi

exit 0
このスクリプトは、実行権限を付与するのを忘れないでください。
これで、電子メール配信毎に、配信最終段階で、自動的に spamass.sh を実行し、その中で spamassassin による電子メール spam チェックを行い、spamassassin がメールヘッダ部に追加した spam チェック結果により spamdrop ディレクトリ配下にメッセージを隔離する処理を自動振り分けの形で行う挙動になります。

この時、隔離先に指定している spamdrop は、テストで使用する受信者のメールボックスディレクトリ直下に .spamdrop のディレクトリ名で用意しなければなりません。この点がどこにも明記されておらず、ディレクトリを用意しているのに「spamdrop が無い」と、sieve スクリプトでエラーを吐かれるという現象に何時間も悩みました。。

spamassassin の挙動設定や、フィルタのデータは、各受信者のメールボックスディレクトリ直下の spamassassin/spamd ディレクトリ配下の user_prefs などを参照します。

この状態でテスト受信者宛てに電子メールを送信してみて、受信電子メールのメールヘッダに以下のようなヘッダが含まれていれば、成功です:
X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-14) on mx0.example.com
X-Spam-Level: 
X-Spam-Status: No, score=-2.5 required=4.0 tests=BAYES_00,KHOP_HELO_FCRDNS,
	NICE_REPLY_A,SPF_HELO_NONE,SUBJ_ALL_CAPS autolearn=ham
	autolearn_force=no version=4.0.0
また、テスト受信者から、返信か新規に電子メールを送信してみて、下記のようなDKIMヘッダが付いていれば、成功です:
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=mx0;
	t=1672471637; bh=3mQXSVMo2kr2sHu262xQGwzCfRBaMvLhHS2T4KSLTSw=;
	h=Date:Subject:To:References:From:In-Reply-To;
	b=AjxunnUSbCBDAP3yGcB9lCa1Gjys9PYqZ0cup0a0D2QibriW1KpJPxeUKc84e+/aQ
	 Q3FkBGJ42pe0tReKbA/G40SI3+TI07q5Ktdn2M+Zz3WK1vyeQfnyZ8gZEvj2tLiin2
	 9Jc6H5qKeEvIx5AQrvIEAyukmXCuXVjGIbujHF2WZbfOmsqeI5eBvDPYK5QAcdrkM+
	 Ewgc8asLgEIxhOzpMruDEyvJJ8UYJnEPf/hqT5ULWcivOkzvgKL95EEzI42xo3QBd6
	 DgpQ8kjx9KpsNRJv7IYDrmD9aFoP5mvjzTx51f9+K1uKENXimM7d7MB1kaktiNVKtO
	 XB7v6ywP9dQCw==