#author("2018-09-01T18:34:09+09:00","default:nowsky","nowsky")
*policyd-spf [#yf2c1aa0]
メール受信時にPostfixでSPF検査を行う為のスクリプト。
設定変更が出来ないPerl版と、細かい変更が可能なPython版の2種類がある。
Postfixで使う時はポリシーチェックとしてスクリプトを呼び出す。

- 参考情報
[[Postfix SMTP アクセスポリシー委譲:+http://www.postfix-jp.info/trans-2.2/jhtml/SMTPD_POLICY_README.html]]
[[holly's wiki - policyd-spf-python:+https://sites.google.com/site/hollyroyaltea/home/mail/postfix/policyd-spf-python]]
~
*構築環境 [#he9feea4]
今回検証した環境はこちら
-debian 9.5 x86_64
-CentOS 7.5 x86_64
-openSUSE 42.3 x86_64

~
設定ファイル・スクリプト本体がディストリビューション毎に違うが、
設定と説明を統一化する為、同ファイル名のシンボリックリンクを作成する。
シンボリックリンクを作りたく無い時は、実ファイルPATHを直設定する。
~
*構築 [#b9907809]
&size(16){&font(b){1. インストール};};
インストールはディストリビューションによってパッケージ名に違いがある。
今回はパッケージ管理を利用してインストールするので各々の環境にあわせる。
- Debian
 # apt-get install postfix-policyd-spf-python
 # ln -s /etc/postfix-policyd-spf-python/policyd-spf.conf /etc/policyd-spf.conf
 # ln -s /usr/local/bin/policyd-spf /usr/bin/policyd-spf

- CentOS
 # yum install pypolicyd-spf
 # ln -s /etc/python-policyd-spf/policyd-spf.conf /etc/policyd-spf.conf
 # ln -s /usr/libexec/postfix/policyd-spf /usr/local/bin/policyd-spf

- openSUSE
 # zypper install python-policyd-spf
 # ln -s /etc/python-policyd-spf/policyd-spf.conf /etc/policyd-spf.conf
 # ln -s /usr/libexec/postfix/policyd-spf /usr/local/bin/policyd-spf

 
SPFレコードをAR形式(Authentication-Resultsヘッダ)で追加する場合、
&color(#ff0000){python-authresモジュール};が必要となる。
ただし、Python2環境ではモジュールが用意されていないので自力でrpmを作成してインストールする。
 # cd /usr/local/src
 # wget https://files.pythonhosted.org/packages/08/ae/3976998b0f8838a5781234710cee17b6717bbf5cc17db6f528531b975a83/authres-1.1.0.tar.gz
 # tar zxvf authres-1.1.0.tar.gz
 # cd authres-1.1.0
 # python setup.py bdist_rpm
 # yum install dist/*.noarch.rpm
~
&size(16){&font(b){2. 設定};};
policyd-spfは受信側の処理となる為、DNSのtxtレコード設定については割愛。
ドキュメントは[[Debianの公開している物:+https://manpages.debian.org/testing/postfix-policyd-spf-python/policyd-spf.conf.5.en.html]]を確認する。
 [01] debugLevel       = 1
 [02] Header_Type      = SPF
 [03] #Authserv_Id     = mx.test.org
 [04] HELO_reject      = False
 [05] Mail_From_reject = False
 [06] PermError_reject = False
 [07] TempError_Defer  = False
 [08] skip_addresses   = 127.0.0.0/8,::ffff:127.0.0.0/104,::1
 [09] Whitelist        = 192.168.0.1
 [10] Domain_Whitelist = mail.test.org
 
 --------------------------------------------------
 
 [01] 出力ログレベル。1(最低限)~5(デバッグログ)を設定出来る
 [02] SPFのヘッダ形式。SPFは"Received-SPF"、ARは"Authentication-Results"
 [03] ヘッダ形式にARを設定した時にヘッダ識別子として使用する
 [04] HELOコマンドのSPF評価方針。ヘッダ付与のみ行い拒否しない時は"False"を設定
 [05] MAIL FROMコマンドのSPF評価方針。ヘッダ付与のみ行い拒否しない時は"False"を設定
 [06] SPF PermErrorの拒否方針。Falseを設定すると無効となる
 [07] SPF TempErrorの遅延方針。Falseを設定すると無効となる
 [08] SPF評価を無効化するIPアドレス。ローカルホストなど不変な物を設定
 [09] SPF評価を無効化するIPアドレス。ドメイン内の他MXサーバなどユーザ毎に変わる値を設定
 [10] SPF評価を無効化するドメイン。アスタリスクレコードは利用不可
~
&size(16){&font(b){3. master.cf};};
policyd-spfを呼び出す為、Postfixのmaster.cfを書き換える。
今回はポリシーとして呼び出す為、下記設定を最終行に追記する。
 # SPF Check
 policy-spf  unix    -    n    n    -    0    spawn
     user=nobody argv=/usr/local/bin/policyd-spf /etc/policyd-spf.conf

 
上の設定でSPFチェックが出来ない場合、argvの中でPythonがスクリプトを直接実行する様に書き換える。
この時、ディストリビューションによってはPythonのバージョン毎にPATHが変わるので注意する。
利用するPythonのバージョンは実スクリプトの1行目を読んで判断する。
 # SPF Check
 policy-spf  unix    -    n    n    -    0    spawn
     user=nobody argv=/usr/bin/python2 /usr/local/bin/policyd-spf /etc/policyd-spf.conf
~
&size(16){&font(b){4. main.cf};};
master.cfに追加したpolicy-spfを呼び出す為、check_policy_serviceを追加する。
この時、設定は下記の様に&color(#ff0000){ "reject_unauth_destination" の後に追加する。};
前に設定すると、check_policy_serviceで処理したメールが全て許可となり、&color(#ff0000){&font(b){MTAがオープンリレー};};化する。
 smtpd_recipient_restrictions =
      permit_mynetworks,
      reject_unauth_destination,
      check_policy_service unix:private/policy-spf

 
追加した "policy-spf" はmaster.cfに追加したポリシー名と同じにする。
また、デフォルト状態では1,000秒程でポリシープロセスがkillされてしまう為、
下記設定も追加してプロセスのkill間隔を調整する。
 # PROC Kill
 policy-spf_time_limit = 3600s
~
*確認 [#c93e023d]
実際に外部のメールサーバからメールを送信し、SPFヘッダが追加されるか確認する。
下記は実際に外部からメールを送信し、ヘッダ付与テストを行った結果となる。
 Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=59.135.**.**; helo=ezweb.ne.jp; envelope-from=*****@ezweb.ne.jp; receiver=*****@***.***.***