0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Mailman がメールを受理・配送する前に、投稿者自身による確認を行う

Last updated at Posted at 2018-03-02

概要

Mailman でメーリングリストを運用している時、非会員からもメールを受理・配送したい場合があります。しかし、非会員によって投稿された全てのメールを単純に受理・配送すると、spam が大量にあふれかえってしまい、使い物になりません。本稿では、Mailman の司会依頼メールの仕組みを利用して、spam ボットによる投稿を抑止しながらも、任意の投稿者からのメールを受理・配送する方法を説明します。

背景

Mailman でメーリングリストを運用している時、非会員からもメールを受理・配送したい事例があります。例えば、筆者の所属部門では、事務室の問合せ窓口に Mailman を使っています。これには2つの理由があります。第1は、過去の問合せ及び対応の記録を残すためです。窓口アドレスを、単純なエイリアスとして実装すると、過去の問合せ及び回答の記録が残らず、事務室メンバーの交代時に引継ぎが困難になります。少なくとも、新人がアクセスできる過去メールの書庫が必要です。第2は、メール以外のコミュニケーション手段と併用する場合の利便性です。タスク管理システムやチャット、Wikiなどのメール以外のコミュニケーション手段を併用している場合、そのコミュニケーション手段から個別のメールを参照するには、個別のメールに対してURLが発行されている(言い換えれば、ウェブ上に書庫が存在している)必要があります。この2つの理由により、窓口アドレスを Mailman を用いたメーリングリストとして実装していますが、当然ながら、部門外の所属組織構成員だけでなく、所属組織外の関係者からもメールを受け付ける必要があります。

Mailman でメーリングリストを運用している時、非会員によって投稿されたメールを受理・配送するには、(1) generic_nonmember_action オプションを「承認」に設定する、または、(2) accept_these_nonmembers オプションに適当な正規表現を設定する、などの選択肢があります。しかし、前者(1)はあらゆるメールを受け付けますし、後者(2)も詐称が容易なヘッダー From に依存していますから、spam に対して脆弱な設定になってしまいます。

それに対して、所属組織構成員が利用する送信用メールサーバは固定されているという前提が利用できる場合には、特定のメールサーバから投稿されたメールは全て配送するという設定が可能です。しかし、この設定にも2つの問題がありました。第1は、所属組織の送信用メールサーバを経由せずに、Gmail やプロバイダのメールサーバからメールを送信する所属組織構成員が多いという問題です。第2は、所属組織外の関係者からのメールについては、送信用メールサーバが固定されていないため、この設定では原理的に対応できないという問題です。この2つの問題により、メーリングリストサーバ管理者による司会作業が追いつかずに、メールの滞留が多発していました。

提案手法

本稿では、Mailman の司会依頼メールの仕組みを利用して、投稿者自身による確認を組み込むことにより、任意の投稿者・メールサーバからメールを受理・配送する方法を説明します。

具体的には、以下のような挙動を実現します。

  1. Mailman の司会依頼メールを、アップロードスクリプトを経由して、確認用CGIに転送する。
  2. 確認用CGIは確認用URLを生成し、投稿者に対して「この確認用URLにアクセスしてください」という確認依頼メールを送信する。
  3. 指定された確認用URLにアクセスがあると、確認用CGIは、当該メールの配信を依頼するコマンドメールを Mailman に送信する。

確認用URLにアクセスした投稿者のメールアドレスは、データベースに登録されて、30日間は確認なしに配送されるようになります。

設定

必要なスクリプト類は、GitHub に公開しました。まずは、このリポジトリを clone してください。

$ git clone https://github.com/tsuchm/mmpostauth.git

重要なスクリプトは2つだけです。

  1. action: 確認用CGI
  2. mmpostauth-handler: 司会依頼メールのアップロードスクリプト

司会用パスワードの設定

まず、Mailman にテスト用メーリングリストを作成し、司会者として自分自身を設定、テストメールをテスト用メーリングリストに送って、司会依頼メールのサンプルを入手してください。

次に、Mailman のウェブインターフェースを使って、テスト用メーリングリストの司会用パスワードを設定して下さい。設定した司会用パスワードは、確認用CGIと同じディレクトリにある設定ファイル mmpostauth.ini に以下のように書き込んでおいて下さい。

mmpostauth.ini
[testlist@lists.example.net]
password = 司会用パスワード

確認用CGIのインストール

まず、mod_fcgid と必要な perl モジュールをインストールしておきます。

$ apt-get install libapache2-mod-fcgid libfcgi-perl libwww-perl libhtml-template-perl libcgi-session-perl libconfig-simple-perl libio-stringy-perl libmail-dkim-perl libdbix-class-perl libdbix-class-timestamp-perl libdbd-sqlite3-perl libdatetime-format-sqlite-perl

最初に、確認用CGIが mod_fcgid 経由で動作していることを確認します。例えば、確認用CGIのURLが、https://www.example.net/mmpostauth/action であるとします。以後、このURLを基準URLと呼びます。基準URLの末尾に /status を付け加えた https://www.example.net/mmpostauth/action/status に、ウェブブラウザでアクセスしてみて、「OK」という出力が得られたならば、確認用CGIは正しく動作しているでしょう。

次に、確認用CGIに対して司会依頼メールをアップロードできるネットワークの範囲を制限しておきます。初期状態では、アップロード用URL(基準URL+/post)に対するアクセス制限(抜粋)は、以下のようになっています。

.htaccess
SetEnvIf Request_URI "/action/post$" post_action
SetEnvIf Remote_Addr "^192\.168\." !post_action
<Files action>
    SetHandler fcgid-script
    Order Allow,Deny
    Allow from all
    Deny from env=post_action
</Files>

この設定は、以下のように振る舞います。

  • アップロード用URL(基準URL+/post)に対するアクセスは基本的に拒否する。
  • ただし、アクセス元のIPアドレスが正規表現(^192\.168\.)に一致する場合は、許可する。

司会依頼メールのアップロードスクリプトをインストールするサーバのIPアドレスと一致するように、適切に正規表現を書き換えて下さい。

また、設定ファイルには、秘密を要する情報(司会用パスワードなど)が記入されていますから、適切にアクセス制限しておく必要があります。初期状態は、以下のようになっています。

.htaccess
<FilesMatch "\.(ini|tmpl)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

司会依頼メールのアップロードスクリプトのインストール

その上で、司会依頼メールのアップロードスクリプトが正しく動作していることを、以下のコマンドで確認してください。

$ cat サンプル | perl mmpostauth-handler --debug --url https://www.example.net/mmpostauth/action/post

--url オプションで、アップロード用URL(基準URL+/post)を指定して下さい。このコマンドが正常に動作すると、以下のように確認依頼メールのヘッダと文面を含む結果が得られるはずです。

HTTP/1.1 200 OK
Connection: Keep-Alive
Date: Fri, 02 Mar 2018 01:25:15 GMT
Server: Apache/2.4.25 (Debian)
Vary: Accept-Encoding
Content-Type: text/plain; charset=UTF-8

From: testlist-owner@lists.example.net
To: alice@example.com
Subject: Your message requires the additional confirmation step
Date: Fri, 02 Mar 2018 01:25:15 GMT
X-Mailer: MIME-tools 5.508 (Entity 5.508)

The additional confirmation step is required, because your message
posted for testlist@lists.example.net is received from an untrusted mail server.
Access the following url:

    https://www.example.net/mmpostauth/action/confirm/ランダム文字列

アップロードされた司会依頼メールは、確認用CGIと同じディレクトリの spool/ ディレクトリに貯まるようになっています。確認用CGIの動作権限に留意して、spool/ ディレクトリの所有者・パーミッションを適切に変更して下さい。

最後に、司会依頼メールのアップロードスクリプトが、MTA 経由で呼び出されるように、/etc/aliases または ~/.forward を適当に変更して下さい。本稿では、mmpostauth@mail.example.net 宛のメールがアップロードされるものとします。以下は設定例です。

/etc/aliases
mmpostauth: |"/somewhere/mmpostauth-handler --url https://www.example.net/mailman/action/post"

司会者の追加

  1. Mailman のウェブインターフェースを使って、テスト用メーリングリストの司会者に mmpostauth@mail.example.net を加えて下さい。
  2. テスト用メーリングリストに、非会員のアドレスからテストメールを投稿し、投稿者自身に確認依頼メールが戻ってくることを確認して下さい。
  3. 確認依頼メールに記載されている確認用URL(基準URL+/confirm/+ランダム文字列)にアクセスします。

アクセス制御

初期状態では、確認用URL(基準URL+/confirm/+ランダム文字列)に対するアクセス制御は行わない(あらゆるアクセスを受け付ける)設定になっています。この状態でも、確認依頼メールから確認用URLを取り出し、更にアクセスするような高度な対応は spam ボットには到底不可能ですから、spam の投稿は十分に抑止されると期待されます。

ただ、対象のメーリングリストの性質によっては、より厳しいアクセス制御が必要になる場合も考えられます。その場合は、以下の設定を検討して下さい。

reCAPTCHA によるアクセス制御

確認用URL(基準URL+/confirm/+ランダム文字列)にアクセスしているクライアントが人間であることを、reCAPTCHA によって確認します。この機能を利用する場合は、https://www.google.com/recaptcha/intro/android.html から reCAPTCHA 用のサイト鍵と秘密鍵を取得して、以下のように設定ファイルに記入して下さい。

mmpostauth.ini
[testlist@lists.example.net]
password = 司会用パスワード
sitekey = Googleから取得したサイト鍵
secretkey = Googleから取得した秘密鍵

なお、default セクションで設定すると、全てのメーリングリストに対して reCAPTCHA が有効になります。

ウェブサーバ上の認証・認可モジュールによるアクセス制御

Shibboleth 認証や LDAP 認証、Basic 認証など、上位ウェブサーバ上で動作する各種の認証・認可モジュールを用いてアクセス制御することが可能です。最も簡単な方法は、確認用CGI全体を、認証・認可モジュールの管理下に置くことです。

.htaccess
Satisfy Any
SetEnvIf Remote_Addr "^192\.168\." trusted_network

AuthType Shibboleth
ShibRequestSetting requireSession 1
Require valid-user

<Files action>
    SetHandler fcgid-script
    Order Deny,Allow
    Deny from all
    Allow from env=trusted_network
</Files>

この設定例は、以下のように振る舞います。

  • 確認用CGIに対するアクセスは、基本的に拒否する。
  • ただし、Shibboleth モジュールによって認証されている場合は、アクセスを許可する。
  • または、信頼できるネットワークからは、アクセスを許可する。

しかし、アクセス制御の必要水準が異なるメーリングリストが混在している場合には、この設定例では対応できません。

アクセス制御の必要水準が異なるメーリングリストが混在している場合には、ログイン用URLのみを、認証・認可モジュールの管理下に置くという設定を行います。この機能を利用する場合は、まず以下のように設定ファイルで login オプションを設定して下さい。

mmpostauth.ini
[testlist@lists.example.net]
password = 司会用パスワード
login = 1

このように設定すると、確認用URL(基準URL+/confirm/+ランダム文字列)に対するアクセスは一旦、ログイン用URL(基準URL+/login/+ランダム文字列)にリダイレクトされるようになります。

その上で、ログイン用URL(基準URL+/login/+ランダム文字列)に対して、ウェブサーバ側で認証・認可を行うように設定します。

.htaccess
Satisfy Any
SetEnvIf Request_URI "/action/login/" login_action

AuthType Shibboleth
ShibRequestSetting requireSession 1
Require valid-user

SetEnvIf Request_URI "/action/post$" post_action
SetEnvIf Remote_Addr "^192\.168\." !post_action

<Files action>
    SetHandler fcgid-script
    Order Allow,Deny
    Allow from all
    Deny from env=login_action
    Deny from env=post_action
</Files>

この設定例は、以下のように振る舞います。

  • ログイン用URL(基準URL+/login/+ランダム文字列)に対するアクセスは、基本的に拒否する。
  • ただし、Shibboleth モジュールによって認証されている場合は、アクセスを許可する。
  • 司会依頼メッセージのアップロード用URL(基準URL+/post)に対するアクセスは、信頼できるネットワークのみ許可する。

ログイン用URL(基準URL+/login/+ランダム文字列)にアクセスがあると、確認用CGIは、環境変数 REMOTE_USER の値をチェックして、確認用URL(基準URL+/confirm/+ランダム文字列)に更にリダイレクトします。環境変数 REMOTE_USER が空の場合には、認証・認可されていないものと見なして、403 エラーページを返します。

文面の調整

実際の運用にあたっては、以下の文面を調整する必要があるでしょう。

  • notify.tmpl: 確認依頼メール
  • confirm.tmpl: 確認用ウェブページ
  • approve.tmpl: 確認・送信承認後の結果表示ウェブページ
  • revoke.tmpl: 確認・送信取消後の結果表示ウェブページ

確認用URLにアクセスした投稿者のメールアドレスのキャッシュ

確認用URLにアクセスした投稿者のメールアドレスは、データベースに保存され、30日間は確認なしにメールが配送されるようになります。この挙動を変更したい場合は、以下のように設定ファイルで senderperiod オプションを設定して下さい。値を0にすると「キャッシュせずに、毎回確認する」設定になります。

mmpostauth.ini
[default]
senderperiod = 0

古い司会依頼メールの破棄

30日以上経過した司会依頼メールについては、自動的に破棄する設定になっています。この挙動を変更したい場合は、以下のように設定ファイルで expire オプションを設定して下さい。値を0にすると「破棄しない」設定になります。

mmpostauth.ini
[default]
expire = 0
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?