질문

질문

나는 할 수 있는 간단한 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}다음 해당 이메일 서버로 메시지를 전달하는 것으로 이해됩니다.

요청된 솔루션

엔지니어:제목과 본문이 간단한 특정 주소에서 보낸 이메일이 수신자에게 전달되기 전에 시스템에서 가로채어 수정되도록 요구할 수 있나요? 예를 들어 제목과 본문에 "leak"라는 단어가 전송되는데 메시지를 전달하기 전에 "freezer"로 변경해도 되나요?

그래서 본질적으로 메시지 내용을 수정해야 합니다.앞으로다른 이메일 서버로 전달됩니다. 메시지가 도착하기 전에 메시지 근처에서 {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파일에는 필요한 두 가지 주요 섹션이 있습니다.

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/해당 디렉토리에 사용자가 실행할 수 있는 하나 이상의 스크립트를 만드는 것 입니다 postfix-filter. 이 작업을 수행하는 방법을 알려 드리겠습니다. 하지만 스크립트 제안은 그대로 두겠습니다.할 수 있는들어오는 매개변수(최종적으로 sendmail명령에 전달됨)를 수정하고 다음 종료 코드 중 하나를 반환해야 합니다.
    • 0(성공에 대해그리고매개변수 sendmail가 수정되었습니다)
    • 2(성공한 경우, 그러나 매개변수는 수정되지 않습니다)
    • 어쨌든(문제가 무엇입니까, 종료하고 메시지를 반환하십시오).

일을 시작하다

이제 남은 것은 Postfix가 mailmunger새로운 구성으로 시작되는지 확인하는 것입니다.

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

답변2

예를 들어 Milt를 사용하지 않는 이유는 무엇입니까?메일 상인? 이를 통해 두 번째 Postfix 인스턴스나 기타 이상한 스크립트 및 해킹을 사용하지 않고도 필요한 작업을 정확하게 수행할 수 있습니다.

관련 정보