メッセージ

2022年12月28日の記事

2022/12/28(水)メールサーバの中規模改修と基礎知識(6)~ milter-manager

milter-mamager は、複数のmilter インターフェースアプリケーションを管理し、postfix や sendmail 上の設定を簡略化する目的で使用される電子メール送受信アプリケーションです。
日本語の milter-manager サポートページは、2.1.5 (2019/09/10 リリース)で更新が止まっており(但し、大いに参考にはなる)、FreeBSD の Ports は 2.1.6 (2022/01/13 リリース)で更新が止まっているのですが、milter-manager の最新バージョンはどうやら 2.2.5(2022/12/12 リリース)のようです。

milter-manager の概要

今回は、下手くそ(且つ汚ない)な手書きで描いた、下記のような挙動をさせるために使います。
20221228_miltermanager.png

複数の milter アプリケーションを使用する場合、postfix 側で単純に milter の設定を行えば事足ります。
ですが、実際はたった2つでも設定がちょっと煩雑になる。

加えて、将来的に電子メールサービスの付加機能は増えていく傾向にあると思われるため、そのような状況に先回り対処する目的で開発されたのが、この milter-manager です。

milter アプリケーションは、典型的なデーモン形式の造りになっているのが通常で、ソケット通信で電子メールメッセージの授受を行いますが、TCP/IPによるソケット通信では、サーバ負荷が重くなりがちなのです。
なので、通常は unix ソケット通信による手法で代替し、今回も milter-manager とのやりとりは、全て unix ソケット通信にて動作させています。

milter-manager は、postfix からの一度の呼び出しアクションで、バックグラウンドで複数の milter アプリケーション処理を実行する役目を担います。

milter-manager のインストール準備(1)

ここからは、基本的に root アカウントでの作業となります。
milter-manager をインストールする場合、FreeBSD13 では、下記のモジュールが事前に必要です。(但し、2022/12/24 現在)
 ・perl5-5.36.0 		 (Ports から カテゴリ:lang)
 ・ruby-3.0.5,1 		 (Ports から カテゴリ:lang)
 ・libtool-2.4.7		 (Ports から カテゴリ:devel)
 ・gettext-runtime-0.21	 (Ports から カテゴリ:devel)
 ・gettext-tools-0.21_1	 (Ports から カテゴリ:devel)
 ・libev-4.33,1		 (Ports から カテゴリ:devel)
 ・gmake-4.3_2			 (Ports から カテゴリ:devel)
 ・libxml2-2.10.3_1		 (Ports から カテゴリ:textproc)
 ・glib-2.74.4_2		 (Ports から カテゴリ:devel)
 ・gobject-introspection-1.74.0,1(Ports から カテゴリ:devel)
 ・intltool-0.51.0_1		 (Ports から カテゴリ:textproc)
 ・rubygem-glib2-4.0.3		 (Ports から カテゴリ:devel)
 ・rubygem-rexml-3.2.5		 (Ports から カテゴリ:textproc)
milter-manager も結構依存するものが多いのですが、
これらの多くは、Ports や Package でインストールしても、管理上特段問題にはなりません。
ruby で動作させている部分が案外多く、Perl と、何故か gnome ライブラリの一部(glib,gobject) も依存します。
特にに、glib の古いライブラリがサーバ上に残っていると上手く動作しない不具合が確認されています。

更に、インストールに先立ち、milter-manager のセキュリティポリシーに従うため、ユーザ milter-manager を、vipw や useradd コマンドで追加します:

vipw コマンドの場合は、下記の1行を編集画面で追加します。
milter-manager::2005:3000::0:0:milter manager execute user:/home/staff/milter-manager:/usr/sbin/nologin
※ ユーザホームディレクトリを内部処理でワークエリア的に使うため、ホームディレクトリを必ず割り当てる

vipw でユーザ追加した場合、/etc/group に下記の1行を例示のように変更しておきます:
mailuser:*:3000:opendkim,milter-manager
更に vipw でユーザ追加した場合は、つまらないセキュリティホールを作らないために、下記コマンドも一応実行しておきます:
# passwd milter-manager

milter-manager のインストール準備(2)

先ず、ソースコードの展開を行います。
# cp milter-manager-2.2.5.tar.gz /usr/local/src	 
# cd /usr/local/src	 
# tar xvzf milter-manager-2.2.5.tar.gz	 
# cd milter-manager-2.2.5
実は、実際にソースコードのコンパイルを実施したところ、FreeBSDにおいては、素のソースコードではエラーが発生し、上手く出来ません。
具体的には、configure スクリプト、binding/ruby/test/run-test.sh、Makefile.in の3本の変更が必要なようです。

これらは、patch コマンドを使用するか、手入力修正して、作業実施前にソースコードの修正を行う必要があります。
ここでは、量が少ないのと、用意が面倒なので手入力で修正しまいます。

FreeBSD12/FreeBSD13 においては、以下のように修正することで、milter-manager 2.2.5 のソースコードでコンパイルできるようになります。(確認済)
binding/ruby/test/run-test.sh 1行目
 #!/bin/bash
   ↓
 #!/bin/sh

Makefile.in 516行目
        milter-manager.pc libmilter.pc $(am__append_1)
                          ↓
        milter-manager.pc $(am__append_1)

configure 15177 行目
    RUBY_GLIB2_CFLAGS="-I$ruby_glib2_gem_dir/ext/glib2"
             ↓
    RUBY_GLIB2_CFLAGS="-I$ruby_glib2_gem_dir/lib"

milter-manager のインストール

以下の手順に従ってインストールしていきます:
# setenv CPPFLAGS '-I/usr/local/include -I/usr/include'	(configure が上手くライブラリを探せないため)
# setenv LDFLAGS '-L/usr/local/lib -L/usr/lib' 		(configure が上手くライブラリを探せないため)
# unsetenv LD_LIBRARY_PATH	 
# ./configure --localstatedir=/var
configure スクリプトの実行が完了すると、以下のようなサマリーが出力されます:
Configure Result:

  Package Platform        : freebsd
  Package Options         :

  Default Effective User  :
  Default Effective Group :
  Default Socket Group    :
  Default Connection Spec : unix:/var/run/milter-manager/milter-manager.sock
  Default PID File        :

  GLib                    : 2.74.4
  libev                   : yes
  Ruby                    : /usr/local/bin/ruby
    CFLAGS                : -I/usr/local/include/ruby-3.0/amd64-freebsd13 -I/usr/local/include/ruby-3.0/
    LIBS                  : -L/usr/local/lib -fstack-protector-strong -Wl,--compress-debug-sections=zlib -Wl,-E -lruby30 -lm -lpthread -L/usr/local/lib
  Ruby version            : ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c5) [amd64-freebsd13]
  Ruby/GLib2              : -I/usr/local/lib/ruby/gems/3.0/gems/glib2-4.0.3/lib
  Ruby milter PATH        :

  rd2                     : rd2-not-found
  GTK-Doc                 : no

  Cutter                  :
  LCOV                    :
  coverage                :
  coverage report by LCOV :

  Cutter Source Path      : $(top_srcdir)/vendor/cutter-source

  Launchpad PGP key       :
  GPG UID                 : 3F09D1EA68E5F18B4EC8FEEAFF2030C057B9884E
続いて、下記のコマンドを順に実行し、エラーが無ければ、本体のインストールは完了です。
# gmake
# gmake install
最後に下記手順で動作環境を準備して、インストール完了です:
# mkdir /home/staff/milter-manager
# chown milter-manager:mailuser /home/staff/milter-manager
# mkdir /var/run/milter-manager
# chown milter-manager:maliuser /var/run/milter-manager

起動・停止スクリプトの設置(FreeBSD に特化している項目)

このスクリプトは一度作っておくと、バージョンアップの際に再作成の必要はありません。

○ milter-manager の起動スクリプト
/usr/local/etc/rc.d/ ディレクトリ配下に、milter-manager のファイル名で下記内容を作成します。
実行権限を与えることを忘れないようにしてください:
#!/bin/sh

# PROVIDE: milter-manager
# REQUIRE: LOGIN
# BEFORE: mail
# KEYWORD: shutdown

#
# Add the following lines to /etc/rc.conf to enable milter-manager:
#
#   milter_manager_enable=yes
#

. /etc/rc.subr

name="milter_manager"
rcvar="milter_manager_enable"
extra_commands="reload"

load_rc_config $name
: ${milter_manager_enable="NO"}
: ${milter_manager_pid_file="/var/run/milter-manager/milter-manager.pid"}
if getent passwd milter-manager > /dev/null; then
    : ${milter_manager_user_name="milter-manager"}
else
    : ${milter_manager_user_name="mailnull"}
fi
if getent group milter-manager > /dev/null; then
    : ${milter_manager_group_name="milter-manager"}
else
    : ${milter_manager_group_name="mailuser"}
fi
: ${milter_manager_socket_group_name="mailuser"}
: ${milter_manager_connection_spec=""}
: ${milter_manager_debug="NO"}

command=/usr/local/sbin/milter-manager
pidfile="${milter_manager_pid_file}"
command_args="--pid-file ${milter_manager_pid_file}"
if test -n "${milter_manager_user_name}"; then
    command_args="${command_args} --user-name ${milter_manager_user_name}"
fi
if test -n "${milter_manager_group_name}"; then
    command_args="${command_args} --group-name ${milter_manager_group_name}"
fi
if test -n "${milter_manager_socket_group_name}"; then
    command_args="${command_args} --unix-socket-group ${milter_manager_socket_group_name}"
fi
if test -n "${milter_manager_connection_spec}"; then
    command_args="${command_args} --spec ${milter_manager_connection_spec}"
fi
if test "$milter_manager_debug" = "YES"; then
    command_args="${command_args} --verbose"
else
    command_args="${command_args} --daemon"
fi

run_rc_command "$1"
今回意図した環境では、FreeBSD においては、デフォルト設定(自動検出)で問題なく動作しますが、実際には試行錯誤があったため、別記事でそのあたりを示していきます。