概要
Mailman でメーリングリストを運用している時、自組織内から発信されたメールは全て受理・配送したいということがあります。例えば、自組織向けの問い合わせ窓口として Mailman を使っている場合など。本稿では、Mailman の司会判定用モジュールを拡張して、特定のメールサーバから投稿されたメールは全て受理・配送する方法を説明します。
背景
Mailman でメーリングリストを運用している時、メーリングリスト非参加者からのメールを受信するには、(1) generic_nonmember_action オプションを「承認」に設定する、または、(2) accept_these_nonmembers オプションに適当な正規表現を設定する、などの選択肢があります。しかし、前者(1)はあらゆるメールを受け付けますし、後者(2)も詐称が容易なヘッダー From に依存していますから、spam に対して脆弱な設定になってしまいます。
本稿では、
- 自組織の構成員が利用する送信用メールサーバを固定されている。
- 送信用メールサーバから Mailman に至るまでの経路上のメールサーバは、いずれも信用できる。
という前提のもとで、Received ヘッダの内容に基づいて、送信用メールサーバから投稿されたメールは全て配送するという設定を紹介します。
設定例
以下のようなコードを、/usr/lib/mailman/Mailman/Handlers/TrustedServerModerate.py
として配置します。なお、パス /usr/lib/mailman/
の部分は、各自の環境にしたがって適宜に読み替えてください。
# Copyright (C) 2015 by TSUCHIYA Masatoshi <tsuchm@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
"""This module implements server based moderation. If a user used one
of trusted remote servers to send his/her message, and only if it has
been delivered through trusted local servers, it is approved as a
trusted message. Otherwise, it will be handled by the default rule of
Mailman.
USAGE:
Add following codes to mm_cfg.py:
TRUSTEDLOCALSERVER = [ "127.0.0.1",
"^192\.168\.10\." ]
TRUSTEDREMOTESERVER = [ "192.168.10.1" ]
GLOBAL_PIPELINE[GLOBAL_PIPELINE.index('Moderate')] = 'TrustedServerModerate'
"""
import re
from Mailman import mm_cfg
from Mailman.Handlers.Moderate import process as moderate_process
from Mailman.Logging.Syslog import syslog
def process(mlist, msg, msgdata):
def extract_ipaddr(str):
m = re.search('\[(\d+\.\d+\.\d+\.\d+)\]', str)
if m:
return m.group(1)
m = re.search('\[((?:[a-fA-F0-9]{4}:+)+[a-fA-F0-9]{4})\]', str)
if m:
return m.group(1)
if '[IPv6:::1]'in str:
return '127.0.0.1'
else:
return ''
def matches_p(ipaddr, patterns):
for pat in patterns:
if pat.startswith('^'):
if re.match(pat, ipaddr):
return 1
else:
if pat==ipaddr:
return 1
return 0
def trusted_message_p(message):
received=[extract_ipaddr(x) for x in message.get_all('Received') if re.match("^from", x)]
syslog('error', 'Servers which deliver this message are %s', ' / '.join(received))
received.reverse()
try:
while received and matches_p(received[-1], mm_cfg.TRUSTEDLOCALSERVER):
received.pop()
remote=0
while received and matches_p(received[-1], mm_cfg.TRUSTEDREMOTESERVER):
received.pop()
remote+=1
if remote > 0:
if len(received) <= 1:
syslog('error', 'This message is trusted')
return 1
else:
return 0
else:
return 0
except AttributeError:
return 0
if mlist.generic_nonmember_action == 1 and trusted_message_p(msg):
return
return moderate_process(mlist, msg, msgdata)
その上で、/etc/mailman/mm_cfg.py
に以下の3つの指定を記述します。第1に、構成員が利用する送信用メールサーバの IP アドレスを以下のように指定します。
TRUSTEDREMOTESERVER = [ "192.168.10.1",
"192.168.10.2" ]
なお、本稿の設定では、ここで指定された送信用メールサーバの経由情報に基づいてメール配送の可否を決定します。ですから、送信用メールサーバでは、SMTP AUTH などの方法により認証されたメールのみを受け付ける必要があります。
第2に、送信用メールサーバから、Mailman にたどり着くまでの既知の信頼できるメールサーバの IP アドレスを以下のように指定します。
TRUSTEDLOCALSERVER = [ "127.0.0.1",
"192.168.10.3",
"192.168.10.4",
"192.168.10.5" ]
なお、既知の信頼できるメールサーバには、Mailman が稼働しているサーバ自身の IP アドレスを含む必要があります。
文字列の先頭に ^ があれば正規表現として解釈しますので、上記の指定は以下の指定と等価です。
TRUSTEDREMOTESERVER = [ "^192\.168\.10\.[12]$" ]
TRUSTEDLOCALSERVER = [ "127.0.0.1", "^192\.168\.10\.[345]$" ]
第3に、Mailman 本体に付属している Mailman/Handlers/Moderate.py
の代わりに、上記のモジュールを使うように指定します。
GLOBAL_PIPELINE[GLOBAL_PIPELINE.index('Moderate')] = 'TrustedServerModerate'
解説
上記の設定例では、以下のような経路で投稿されたメールを、受理・配送します。
MUA
↓
送信用メールサーバ(192.168.10.1 または 2)
↓
中継用メールサーバ(192.168.10.3 または 4)
↓
Mailman サーバ(192.168.10.5)
それに対して、以下のような経路の場合、送信用メールサーバによるユーザ認証が行われていないので、配送しません。
MUA
↓
未知メールサーバ
↓
送信用メールサーバ(192.168.10.1 または 2)
↓
中継用メールサーバ(192.168.10.3 または 4)
↓
Mailman サーバ(192.168.10.5)
また、以下のような経路の場合も、Received ヘッダの偽造の可能性があるので、配送しません。
MUA
↓
送信用メールサーバ(192.168.10.1 または 2)
↓
未知メールサーバ
↓
中継用メールサーバ(192.168.10.3 または 4)
↓
Mailman サーバ(192.168.10.5)
すなわち、送信用メールサーバ・中継用メールサーバおよび Mailman サーバは自組織の管理下にあって、そのメールサーバが付加する Received ヘッダは信頼できるという前提のもとで経路情報を取り出し、送信用メールサーバでユーザ認証されたメールのみを配送する、という設定になっています。