2025/06/04(水)milter-manager は OpenDMARC を自動検出しない!

2025/06/04 4:57 サーバ運営・管理
最近気づいたんですが、Postfix 側の milter インタフェースも安定してきていて、
複数の milter を直感的に指定できるようになっていたり(当初から?)しているので、milter-manager を使う出番はそろそろ・・・
という状況ですが、一度にあれもこれもカスタマイズ出来ないので、milter-manager を使い続けているわけですが・・・

最初は、milter-manager 経由で動作させている OpenDKIM は機能しているのに、どう頑張っても OpenDMARC が付けてくれるはずのメールヘッダが一向に付かないので悩んでいました。
OpenDMARC を milter-manager 経由で稼働させている実績はどうやら一般的に皆無で、マイナーな milter なのか、と思ってたりしましたが・・・

そもそも、milter-manager に OpenDMARC milter が識別されているのかどうかになります。
なので、おもむろに
# /usr/local/sbin/milter-manager -u milter-manager --show-config
を実施すると・・・
# /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:37
define_milter("milter-opendkim") do |milter|
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:45
  milter.connection_spec = "local:/var/run/milteropendkim/dkim-milter"
  # default
  milter.description = nil
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:38
  milter.enabled = true
  # default
  milter.fallback_status = "accept"
  # default
  milter.evaluation_mode = false
  # default
  milter.applicable_conditions = []
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:40
  milter.command = "/usr/local/etc/rc.d/milter-opendkim"
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:41
  milter.command_options = "start"
  # default
  milter.user_name = nil
  # default
  milter.connection_timeout = 297.0
  # default
  milter.writing_timeout = 7.0
  # default
  milter.reading_timeout = 7.0
  # default
  milter.end_of_message_timeout = 297.0
end
は、出てくるが、milter-opendmarc は出てきません。つまり、認識されていなかった。。orz...
ここから、自動認識させるための試行錯誤が始まります。

先ず、/usr/local/etc/milter-manager/defaults/freebsd.conf を修正してみます:
33行目あたりに、
  ["clamav-milter", []],
  ["milter-dkim", []],
  ["milter-opendkim", []],
  [
    "spamass-milter",
    [
      "Remote Network",
      "Unauthenticated",
      "No Stress",
    ],
  ],
とあるので、["milter-dkim", []] とある行の下に、 ["milter-opendmarc", []], を追加し、
  ["clamav-milter", []],
  ["milter-dkim", []],
  ["milter-opendkim", []],
  ["milter-opendmarc", []],
  [
    "spamass-milter",
    [
      "Remote Network",
      "Unauthenticated",
      "No Stress",
    ],
  ],
のようにします。これで、
# /usr/local/sbin/milter-manager -u milter-manager --show-config
を実施すると、"milter-opendmarc" は識別されるようになりました。
注意点としては、FreeBSD の場合、/usr/local/etc/rc.d 配下のスクリプトファイル名を milter-opendmarc にし、実行権を与えておくようにしておくことが必須です。

これで解決か?と思ったんですが、
今度はメールを受信する度に /var/log/maillog に
milter-manager[53830]: [egg][error] must set connection spec: milter-opendmarc
という、エラーが出て OpenDMARCは動作しません。再び、
# /usr/local/sbin/milter-manager -u milter-manager --show-config
とすると、
# /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:37
define_milter("milter-opendmarc") do |milter|
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:45
  milter.connection_spec = nil ← 注目
  # default
  milter.description = nil
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:38
  milter.enabled = true
  ・・・・
要するに、milter-manager からは、接続先不明状態という状況。
幸いにも OpenDKIM が機能しているので、これを手掛かりに 自動検出スクリプトの修正を行いました。。。

先ず、/usr/local/lib/milter-manager/binding/lib/milter/manager にディレクトリを移動します:
修正したのは、
detector.rb
freebsd-rc-detector.rb
の2つ。新規に opendkim-config-parser.rb を参考に、 opendmarc-config-parser.rb を追加で作成しています。
結構あちこち修正したので、差分を提示しておきます。
1) detector.rb
--- detector.rb.old 2024-08-12 05:01:29.000000000 +0900
+++ detector.rb.new 2025-06-03 23:53:01.772724000 +0900
@@ -16,6 +16,7 @@
 require 'milter/manager/clamav-milter-config-parser'
 require 'milter/manager/milter-greylist-config-parser'
 require 'milter/manager/opendkim-config-parser'
+require 'milter/manager/opendmarc-config-parser'
 require 'milter/manager/rmilter-socket-detector'
 require 'milter/manager/rspamd-proxy-detector'

@@ -85,6 +86,10 @@
       opendkim_config_parser.socket
     end

+    def detect_opendmarc_connection_spec
+      opendmarc_config_parser.socket
+    end
+
     def detect_rmilter_connection_spec
       Milter::Manager::RmilterSocketDetector.new(rmilter_conf).detect
     end
@@ -138,6 +143,7 @@
       @clamav_milter_config_parser = nil
       @milter_greylist_config_parser = nil
       @opendkim_config_parser = nil
+      @opendmarc_config_parser = nil
     end

     def set_variable(name, unnormalized_value)
@@ -265,5 +271,14 @@
       end
       @opendkim_config_parser
     end
+
+    def opendmarc_config_parser
+      if @opendmarc_config_parser.nil?
+        @opendmarc_config_parser = Milter::Manager::OpenDMARCConfigParser.new
+        @opendmarc_config_parser.parse(opendmarc_conf)
+      end
+      @opendmarc_config_parser
+    end
+
   end
 end
2)freebsd-rc-detector.rb
--- freebsd-rc-detector.rb.old  2024-08-12 05:01:29.000000000 +0900
+++ freebsd-rc-detector.rb.new  2025-06-04 00:05:45.417658000 +0900
@@ -55,6 +55,10 @@
       @script_name == "milter-opendkim" or @name == "milteropendkim"
     end

+    def opendmarc?
+      @script_name == "milter-opendmarc" or @name == "milteropendmarc"
+    end
+
     def detect_rmilter_connection_spec
       Milter::Manager::RmilterSocketDetector.new(rmilter_conf).detect
     end
@@ -92,6 +96,12 @@
         "/usr/local/etc/opendkim.conf"
     end

+    def opendmarc_conf
+      @variables["cfgfile"] ||
+        extract_parameter_from_flags(command_args, "-C") ||
+        "/usr/local/etc/opendmarc.conf"
+    end
+
     def rmilter_conf
       extract_parameter_from_flags(command_args, "-c") ||
         "/usr/local/etc/rmilter.conf"
@@ -111,6 +121,7 @@
       spec ||= detect_enma_connection_spec if enma?
       spec ||= detect_clamav_milter_connection_spec if clamav_milter?
       spec ||= detect_opendkim_connection_spec if opendkim?
+      spec ||= detect_opendmarc_connection_spec if opendmarc?
       spec ||= detect_rmilter_connection_spec if rmilter?
       spec ||= detect_rspamd_proxy_connection_spec if rspamd?
       spec
@@ -141,6 +152,17 @@
           detector.detect
           detector.apply(loader)
         end
+      end
+      if opendmarc? and _profiles and !_profiles.empty?
+        _profiles.each do |profile|
+          detector = FreeBSDRCProfileDetector.new(@configuration,
+                                                  @script_name,
+                                                  profile,
+                                                  self,
+                                                  &@connection_spec_detector)
+          detector.detect
+          detector.apply(loader)
+        end
       else
         super
       end
@@ -206,6 +228,10 @@
     end

     def detect_opendkim_connection_spec
+      super || @base_variables["socket"]
+    end
+
+    def detect_opendmarc_connection_spec
       super || @base_variables["socket"]
     end
3)opendmarc-config-parser.rb
  opendkim-config-parser.rb をコピーし、下記の修正です:
--- opendkim-config-parser.rb   2025-05-26 02:31:08.119826000 +0900
+++ opendmarc-config-parser.rb  2025-06-03 23:47:40.989538000 +0900
@@ -16,7 +16,7 @@
 require "milter/manager/file-reader"

 module Milter::Manager
-  class OpenDKIMConfigParser
+  class OpenDMARCConfigParser
     def initialize
       @variables = {}
     end
当方は、ruby は殆ど扱った経験は無いので、「見よう見真似」と「推測」で修正しており、実際はもっと小規模な修正で出来るかもしれませんし、更なる修正が必要かもしれません。

上記の修正後、
# /usr/local/sbin/milter-manager -u milter-manager --show-config
を実施すると、
# /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:37
define_milter("milter-opendmarc") do |milter|
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:45
  milter.connection_spec = "local:/var/run/opendmarc/socket"  ← 注目
  # default
  milter.description = nil
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:38
  milter.enabled = true
  # default
  milter.fallback_status = "accept"
  # default
  milter.evaluation_mode = false
  # default
  milter.applicable_conditions = []
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:40
  milter.command = "/usr/local/etc/rc.d/milter-opendmarc"
  # /usr/local/lib/milter-manager/binding/lib/milter/manager/detector.rb:41
  milter.command_options = "start"
  # default
  milter.user_name = nil
  # default
  milter.connection_timeout = 297.0
  # default
  milter.writing_timeout = 7.0
  # default
  milter.reading_timeout = 7.0
  # default
  milter.end_of_message_timeout = 297.0

接続先も認識され、めでたく OpenDMARC が milter-manager で利用できるようになりました。

これで、今年2月にやりたかった DMARC 対応が、設備移転で全く出来なかった状況を脱し、やっと準備完了となりました・・orz

2025/05/26(月)〔FreeBSD Ports〕glib、gobject-introspection のコンパイルエラー

2025/05/26 24:05 サーバ運営・管理
FreeBSD の Ports を用いてソフトウェアの更新をする際、
portupgrade コマンドを常用している方々はそこそこ居られると思うのですが、
このコマンドを使用して glib と gobject-introspection をアップデートすると・・・
glib-2.84.1,2 depends on file: /usr/local/gobject-introspection-bootstrap/bin/g-ir-scanner - not found
*** Error code 1

Stop.
make[1]: stopped in /usr/ports/devel/glib20
*** Error code 1
のようなエラーとなって、構築不能となる。
要するに構築に必要な g-ir-scanner 実行ファイルが見つからないので、どうにも出来ないという状況。

この件の情報収集をしていると、「/usr/ports/UPDATING に記載がある」といいます。
確かに、提起のテキストファイル内の 20250402: と記載がある行の下に記載があります:
20250402:
AFFECTS: users of devel/glib20 and devel/gobject-introspection building outside of Poudriere
AUTHOR: arrowd@FreeBSD.org

New versions of glib started to require gobject-introspection as a build
dependency, while gobject-introspection requires glib to build. This forms a
dependency cycle that is dealt with by introducing the @bootstrap flavor for
mentioned ports. This solution is suggested by the upstream as well, see
https://discourse.gnome.org/t/dealing-with-glib-and-gobject-introspection-circular-dependency/18701

When building devel/glib20 in Poudriere no manual intervention is required.
The devel/glib20@bootstrap gets built first and provides for
devel/gobject-introspection@bootstrap. This in turn provides for a normal
devel/glib20 build, which finally fulfills a dependency for normal devel/gobject-introspection

Users that are building outside of the isolated environments will be ending
up with useless glib-bootstrap and gobject-introspection-bootstrap packages
installed after each update. These can be removed with

pkg remove glib-bootstrap gobject-introspection-bootstrap
正直、「どう対処するのか?」という観点では非常に判りにくいです:
Google翻訳をしてみました。
20250402:
影響: Poudriere 以外で devel/glib20 および devel/gobject-introspection をビルドするユーザー
作成者: arrowd@FreeBSD.org

glib の新しいバージョンでは、ビルド依存関係として gobject-introspection が必須になりました。一方、gobject-introspection はビルドに glib を必要とします。これにより依存関係の循環が発生しますが、上記の port に @bootstrap フレーバーを導入することで対処できます。この解決策はアップストリームでも提案されています。詳細は、https://discourse.gnome.org/t/dealing-with-glib-and-gobject-introspection-circular-dependency/18701 を参照してください。

Poudriere で devel/glib20 をビルドする場合、手動による介入は不要です。
devel/glib20@bootstrap が最初にビルドされ、devel/gobject-introspection@bootstrap に提供されます。これにより、通常の devel/glib20 ビルドが可能になり、最終的に通常の devel/gobject-introspection の依存関係が満たされます。

隔離環境外でビルドを行っているユーザーは、アップデートのたびに不要な glib-bootstrap および gobject-introspection-bootstrap パッケージがインストールされてしまいます。これらのパッケージは、

pkg delete glib-bootstrap gobject-introspection-bootstrap で削除できます。
更に見ていくと、どうもこの「フレーバー」という仕組みが最近 Ports に組み込まれたらしく、現行のportupgrade (Ver 2.4.16) ではこの仕組みを解釈出来ないことが原因の模様。

この解決方法を記載されていたページを見つけたので、ここで肝の部分だけ引用してみます:
1. glibをglib-bootstrapに変更(glib-bootstrapはgobject-introspectionが必要ない)する。
2. gobject-introspectionをgobject-introspection-bootstrapに変更する。
3. glib-bootstrapをglibへ更新する。
4. gobject-introspection-bootstrapをgobject-introspectionへ更新する。

具体的には以下のように実行します。

# pkg_replace glib=/usr/ports/devel/glib20@bootstrap
# pkg_replace gobject-introspection=/usr/ports/devel/gobject-introspection@bootstrap
# pkg_replace glib-bootstrap=/usr/ports/devel/glib20
# pkg_replace gobject-introspection-bootstrap=/usr/ports/devel/gobject-introspection
glibとgobject-introspectionのアップデート | 出口の興味関心あるもの
当方でもここで提示されている方法で、glibと、gobject-introspection を更新出来ました。
しかしまぁ。。 /usr/ports/UPDATING を注意深く見ている人はそう居ないような気も、、、

※注意(2025/06/05 追記):
 引用元サイトにて明記されていないので補足します。
 ・pkg_replace は、予め Ports の ports_mgmt/pkg_replace を別途インストールする必要があります。
 ・どうやら、構築時に lang/python-3.11.12 以上のバージョンと devel/meson-1.7.0 以上のバージョンが依存するらしく、
  少なくともこの2つが提起バージョン未満だと、上手くいきません。当方は、これでしばらく悩みました。