これが正しいかどうかはわかりません。XYの問題ただし、最新のメールサーバーと正しく通信できない恐ろしいソフトウェアをサポートする必要があります。 SMTPのみを実行でき、AUTH ...
リレーサーバーがそれを提供しないか要求しなくても、プロトコルの別のフィールドにあっても、ユーザー名に基づいて送信者アドレスを設定すると、単に切断されます。250-AUTH PLAIN ...
サーバーから入力していない場合は正しい応答ですEHLO
。オンラインでは、このソフトウェアについて解決されていない苦情がたくさんあるため、サプライヤーは何の役にも立たないことがわかります。 SMTPサーバー(Postfix)にsasl認証を追加しようとしましたが、成功しませんでした。資格情報を検証できず、relayhost
それを拒否する人に資格情報が渡されるのではないかと心配です。また、送信された資格情報を無視するようにPostfixに指示する方法もありません。
これらすべての問題を試して解決するために、独自のポートでリッスンし、SMTPトラフィックをプロキシして、プロセス内のいくつかのランダムな資格情報を検証する基本スクリプトを作成しました。
#!/bin/bash
user=<<REDACTED from>>
pw=<<REDACTED password>>
function reset {
send_auth=1
authing=0
ok=1
p=/tmp/smtp_backpipe
if [[ -p $p ]]; then
# drain pipe
dd if=$p iflag=nonblock of=/dev/null 2>/dev/null
else
mkfifo $p
fi
}
function pw_check {
if [[ "${1%%[[:space:]]}" == "${auth%%[[:space:]]}" ]]; then
echo 235 2.7.0 Authentication successful > $p
else
echo 535 5.7.0 Authentication failed > $p
ok=0
fi
}
function changeo {
while (( ok )) && IFS= read -r line; do
case $1 in
in)
if (( authing )); then
>&2 printf '%s\n' "$line"
pw_check "$line"
authing=0
elif [[ "$line" =~ ^AUTH[[:space:]]+PLAIN([[:space:]]+([^[:space:]]+))?[[:space:]]*$ ]]; then
if [[ "${BASH_REMATCH[1]}" ]]; then
>&2 printf '%s\n' "$line"
pw_check "${BASH_REMATCH[2]}"
else
authing=1
echo 334 | tee -a /dev/stderr > $p
fi
else
printf '%s\n' "$line"
fi
;;
out)
if [[ ! "$line" =~ ^250[^[:alpha:]]+AUTH[[:space:]] ]]; then
printf '%s\n' "$line"
if (( send_auth )) && [[ "$line" =~ ^250[^[:alpha:]] ]]; then
send_auth=0
echo 250-AUTH PLAIN
fi
fi
;;
esac
if ! (( ok )); then
exit 1
fi
done
}
auth="`printf '\0%s\0%s' "$user" "$pw" | base64`"
i=0
while true; do
>&2 echo "$(( ++i ))"
reset
cat $p | tee -a /dev/stderr | netcat -4Clp $1 | changeo in | tee -a /dev/stderr | nc -4C 127.0.0.1 25 | changeo out > $p
done
実行してみる./smtp_proxy 9025
と、2番目はnc
すぐに実際のSMTPサーバーに接続され、タイムアウトしたトランザクションを開始することを除いてうまくいきます。
$ ./smtp_proxy 9025
1
220 <<REDACTED host>> ESMTP Postfix
EHLO [10.0.0.99]
250-<<REDACTED host>>
250-AUTH PLAIN
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-DSN
250-SMTPUTF8
250 CHUNKING
AUTH PLAIN <<REDACTED auth>>
235 2.7.0 Authentication successful
MAIL FROM:<<<REDACTED from>>>
250 2.1.0 Ok
RCPT TO:<<<REDACTED to>>>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: <<REDACTED from>>
Subject: hi
To: <<REDACTED to>>
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit
there
.
250 2.0.0 Ok: queued as F23DFE0A1B
QUIT
221 2.0.0 Bye
2
220 <<REDACTED host>> ESMTP Postfix
421 4.4.2 <<REDACTED host>> Error: timeout exceeded
nc
パイプからデータを受信するまで、2番目の呼び出しを何らかの方法で遅延させることができることを願っています。おそらく関数などでラップして実行できます。socat
未変更の接続でこれを行うようです。
socat -v tcp4-l:9025,crlf tcp4:127.0.0.1:25,crlf
...しかし、ストリームをパイプに入れて変更しようとすると、nc
すぐにSMTPサーバーに接続するのと同じことが行われます。 (nc
上記のsをそれぞれsocat TCP4-LISTEN:$1,crlf -
とに置き換えますsocat - TCP4:127.0.0.1:25,crlf
。)
答え1
@muruにリンクされたいくつかの答えと、read
入力が改行で終わらないときにfalse戻りを克服するというより一般的な答えに基づいて、入力が受け取られるまでプログラムの起動を実際に遅らせる関数を考えました。
function until_input {
>&2 echo waiting for input # debug only, remove this line
local line
local nl=0
local format='%s'
while IFS= read -r line; do
nl=1
format='%s\n'
break
done
>&2 echo done waiting # debug only, remove this line
if (( nl )) || [[ "$line" ]]; then
>&2 echo was input # debug only, remove this line
{ printf "$format" "$line"; cat; } | "$@"
fi
}
動作していることを確認するには、次のテストを参照してください。このテストは初期ステートメントのグループを示し、期待どおりに並列until_input
に開始されますが、遅延操作(ここではcat
)は入力が開始された後に開始されます。
{ echo wait >&2; sleep 2; echo go >&2; echo -n pipe$'\n'it baby; } | until_input cat
これは入力を待つ一般的な問題に対する良い解決策のようですが、残念ながら私の問題は解決されませんでした。私はuntil_input nc -4C 127.0.0.1 25
パイプを置き、netcat
誰かが最初のパイプに接続するとすぐに、行が送信される前にサーバーが最初にSMTPで応答するので、2番目のパイプが起動することがわかりました。ただ入るべきだと思いますsocat
。