質問

質問

私はできる単純なPostfixサーバーを探しています。特定のSMTPメッセージの内容と受信者を変更します。
これまで私は私のアプローチについてあまり確信がなく、Postfixの仕組みに関する基本的な知識が欠けているようで、いくつかのガイドラインを受けたいと思います。


コンテキスト

私が働いている組織の設定は、私のようにPostfixを実際に使ったことがない人にとっては、最初は少し難しいことなので、私の説明が理解できることを願っています。

DMZネットワーク上のLinuxコンピュータが{1}Postfixサーバーを実行しており、すべての着信メールがそのサーバーに転送されることがわかりました。その後、サーバーは、ドメインに基づいてメッセージを中継する別のメールサーバーを
決定するいくつかの規則をファイルに定義します。/etc/postfix/transport{3..N}(たとえば@domain1.company.org、、、@domain2.company.org。ドメイン名がデフォルト名の場合(例えば@company.org、メッセージは、{2}従業員がログインしてメールなどを確認するデフォルトの電子メールサーバーに転送されます。

INTERNET   |     DMZ    |   INTERNAL 
   SMTP ---|---> {1} ---|---> {2} 
                        \---> {3..N}

私が言及した「特定のSMTPメッセージ」は、一部のエンジニアが設定したいくつかの簡単なデバイスから収集されたものです。これらのデバイスが送信できる内容にはいくつかの制限があります。

エンジニア:件名やメール本文の特定の領域を変更することはできません。

これらのデバイスがメッセージを送信すると、ネットワークはメッセージを漏洩し、その{1}電子メールサーバーにメッセージを転送することがわかります。

要求されたソリューション

エンジニア:件名と本文は、単純な特定のアドレスから送信された電子メールが受信者に配信される前にシステムが傍受して変更するように要求できますか?たとえば、件名と本文に「リーク」という単語が送信されますが、メッセージを配信する前に「フリーザー」に変更してもよいですか。

したがって、本質的にメッセージの内容を変更する必要があります。今後別のメールサーバーに転送されます。メッセージが到着する前に、メッセージの近くで{1}何かが起こるはずです。{1}{2..N}

これまでの私のアプローチ

すべてが順調に進むこと{1}と、このシステムを介してメールがどのように流れるかを大幅に変更したくないことを考慮して、私は別のPostfixサーバーを実行する別のLinuxボックスを起動する必要があると思いました。mailmunger、図に示す)を{1a})で表示します。
その後、エンジニアはデバイスを設定し、送信するメッセージの受信者を指定します。たとえば、次のようになります[email protected]

私の場合は、新しいLinuxシステムにメールを転送するための別の規則(/etc/postfix/transport私の考えでは)を追加します。{1}*@mailmunger.company.org

次に、{1a}次のようなものを使用します。キュー後のコンテンツフィルタメッセージを処理し、要求どおりに内容を変更し、受信者アドレスから内容を削除しmailmunger.、メッセージを再配信します{1}
これは、Postfixサーバーrelay_hostの属性が{1a}サーバー名を使用して構成されているためです{1}

INTERNET   |     DMZ    |   INTERNAL 
   SMTP ---|---> {1} ---|---> {2} 
                 / ^    \---> {3..N}
                |  |
                v  /
                {1a}

私はこのアプローチが誤って書かれたフィルタの影響を制限するので、できるだけ安全だと思います。しかし、おそらく私が気づいていないまま、このデザインに間違いを犯した可能性があります。私はすべての通常のメールフローが期待どおりに続き、メールだけが私の新しいコンピュータに停滞することを願っています
[email protected]mailmunger


質問

  1. 私の「キューの後のコンテンツフィルタ」は正しい方向に行きますか?または、次のような他のメカニズムを検討する必要があります。キュー前のコンテンツフィルタ
  2. {1a}サーバーは実際にtransportファイルを構成する必要がありますか?それとも、私はこの属性の目的を誤解していますか?
  3. これらの単純なデバイスは、SMTPメッセージを送信するサーバーをどのように知ることができますか?
  4. 私が知っておくべき問題がありますか?

答え1

懸命に考え、慎重にテストした最後に解決策を見つけました!

欠点は次のとおりです。

  • MXレコードを誤って理解して、サーバー用のmailmunger新しいレコードを作成する必要がありました。
  • いいえ、サーバーはファイルを変更するmailmunger必要はありません。修正/etc/postfix/transportのみが/etc/postfix/main.cf必要です。/etc/postfix/master.cf
  • 問題があまりにも多く、メッセージが意図した宛先に到達できない場合、デバッグはやや残念です。

より詳細なソリューション

したがって、最初のステップは/etc/postfix/transportサーバーを変更することです{1}[email protected]マイサーバーにメッセージを送信するには、トランスポートマップに線を追加する必要がありますmailmunger

/mailmunger.company.org/  relay:[mailmunger.company.org]

私のトランスポートマップファイルは正規表現テーブルなので、ファイルmain.cfには{1}次の行が含まれています。

transport_maps = regexp:/etc/postfix/transport

次のステップは設定ですmailmunger

mailmunger~のmain.cf

このmain.cfファイルには、必要な2つの主要なセクションがあります。

relayhost = {1}.company.org
local_recipient_maps =

変数を定義したら、relayhostサーバーに「メッセージを受け取る必要がある人ではない場合は、この人に渡してください」と通知します。
メッセージを修正して再びキューに入れるので、これは重要な部分です。その他受信者。

このlocal_recipient_maps変数にはNULL値が必要です。そうしないと、フィルタスクリプトがメッセージを処理する前にサーバーが指定された受信者のメールボックスを見つけることができない場合、メッセージは拒否されるためです。
私の目的はメッセージの内容を変更することですので、受信者がサーバーにアカウントを持っていなくても構いません。そして受信者アドレス。
スクリプトが失敗すると、メッセージは送信者に返送されます。

mailmunger~のmaster.cf

ここで変更した内容は基本的に正確に次のとおりです。キュー後のコンテンツフィルタ指示が指定されます。

smtp      inet  n       -       y       -       -       smtpd
  -o content_filter=filter:dummy
...
filter    unix  -       n       n       -       10      pipe
  flags=Rq  user=postfix-filter  null_sender=
  argv=/opt/postfix-filters/start-filter -f ${sender} -- ${recipient}

このサービスは、メッセージをパイプラインサービスsmtpに転送する追加のオプションを追加します。サービスは私が作成した特別なユーザーとして私のスクリプトを実行し、スクリプトの終了コードに従ってメッセージをキューに戻すか、送信者に返信します。filter
filterpostfix-filter

他はすべてあります。mailmunger

サービス構成でfilter作成/構成する必要があるものがいくつかあることがわかります。

  1. 最初のステップは、その場所が好きな新しいディレクトリを作成することです/opt/postfix-filters/
  2. 次のステップはpostfix-filterユーザーを作成することです。シェルを使用してこのユーザーを指定し、/usr/sbin/nologinホームディレクトリを/opt/postfix-filter
  3. 次に、 start-filter次のロジックを使用してディレクトリにファイルを作成しました。/opt/postfix-filters/
    #!/bin/bash
    
    ##############################################################################
    #
    # Based on documented example here:
    #  http://www.postfix.org/FILTER_README.html
    #
    # Example Execution:
    #  /path/to/script -f sender -- recipient... <message-file
    #
    ##############################################################################
    
    shopt -s extglob
    
    ## Making of copy of the positional arguments
    _ARGS=("$@")
    
    ## Defining paths to directories that we will be using
    _BASE_DIR="/opt/postfix-filters"
    
    _TMP_DIR="${_BASE_DIR}/tmp"
    [ -d ${_TMP_DIR} ] || {
        echo "${_TMP_DIR} does not exist"; exit $EX_TEMPFAIL; }
    _TMP_FILE="${_TMP_DIR}/in.$$"
    
    _LOG_FILE="${_BASE_DIR}/log"
    
    _FILTERS_DIR="${_BASE_DIR}/filters"
    SENDMAIL="/usr/sbin/sendmail -G -i " # NEVER NEVER NEVER use "-t" here.
    
    
    ## Exit codes from <sysexits.h>
    EX_TEMPFAIL=75
    EX_UNAVAILABLE=69
    
    ## Clean up when done or when aborting.
    function _cleanup() {
      #echo ${_ARGS[@]}
      #cat ${_TMP_FILE}
      rm -f ${_TMP_FILE}
    }
    trap "_cleanup" 0 1 2 3 15
    
    
    ## Creating a temp file (in the INSPECT_DIR directory) with a name that uses
    ## the current Process ID ($$).
    ## This script assumes that the message content is coming in via stdin.
    cat >${_TMP_FILE} || {
        echo "Cannot save mail to file"; exit $EX_TEMPFAIL; }
    
    ## Pass the file and args to each script in the directory containing
    ## filter scripts. If any of them fails with exit code 1, then exit
    ## this parent script. Assume 0 and all other error codes mean
    ## continue.
    for _SCRIPT in ${_FILTERS_DIR}/!(README*) ; do
        ## A quick test that the path is a file and is executable
        ( [ -f "${_SCRIPT}" ] && [ -x "${_SCRIPT}" ] ) || continue
        ## Now we run the script
        echo "running: ${_SCRIPT} -- ${_TMP_FILE} ${_ARGS[@]}" >> "${_LOG_FILE}"
        _NEWARGS=$( ${_SCRIPT} "${_TMP_FILE}" ${_ARGS[@]} )
        if [ "$?" -eq 0 ]
        then
            _ARGS=("${_NEWARGS}")
            echo "newargs? ${_ARGS[@]}" >> "${_LOG_FILE}"
        elif [ "$?" -eq 2 ]
        then
            echo "args not modified" >> "${_LOG_FILE}"
        else
            ## If the script exits with any exit code other than 0 or 2, then we
            ## will "reject" the message based on the content. To do the rejection,
            ## we exit this script with the EX_UNAVAILABLE exit code.
            echo "Message content rejected"
            exit $EX_UNAVAILABLE
        fi
    done
    
    ## Putting the mail back in the queue using the args given to this
    ## script by Postfix.
    $SENDMAIL ${_ARGS[@]} <"${_TMP_FILE}"
    
    ## Exiting with the return status of sending the mail
    exit $?
    
  4. など/opt/postfix-filters/のように作成する必要がある他のディレクトリがあります。filters/tmp/
  5. 残っているのは、filters/そのディレクトリにユーザーが実行できる1つ以上のスクリプトを作成することですpostfix-filter。これを行う方法をお知らせします。しかし、スクリプトの提案はそのままにします。できる着信パラメータ(最後にsendmailコマンドに渡される)を変更し、次の終了コードのいずれかを返す必要があります。
    • 0(成功についてそしてパラメータsendmailが修正されました)
    • 2(成功した場合、パラメータは変更されません)
    • とにかく(問題は何ですか、終了してメッセージを返してください)。

仕事を始める

今残っているのは、Postfixがmailmunger新しい設定で始まることを確認することです。

[root@mailmunger /etc/postfix]# postfix reload

答え2

たとえば、Miltを使用しないのはなぜですか?メールトレーダー?これにより、2番目のPostfixインスタンスやその他の奇妙なスクリプトやハッキングを必要とせずに、必要な作業を正確に実行できます。

関連情報