何の話?
WebApplication等と同居するNginxからみて常にlocalhost:25にSMTPサーバが見えるようにNginxでSMTP ServerのProxyを構築する方法の紹介です。
最終的にTCP Proxy機能を使ってSMTPサーバと会話するので、そのあたりで複数のSMTPサーバへの分散を記述することが出来ます。
Application内部の変数などでSMTPサーバを設定していたり、インフラ屋さんの都合でSMTPサーバが変更になったり、分散しているSMTPサーバが増減したり、テストサーバと本番サーバとかでSMTPサーバの設定が異なったりする環境の場合に便利です。
また、メールの送信ログをNginxが動作しているサーバ側に残すことが出来るので、SMTPサーバに乗り込んでの調査が出来ない/やり辛い場合にも便利です。
例えば以下のような環境であれば動きます。
$ nginx -V 2>&1 | sed -e 's/--/\n--/g' | grep -e '\(version\|stream\|mail\)'
nginx version: nginx/1.11.9
--with-stream=dynamic
--with-stream_ssl_module
--with-mail=dynamic
--with-mail_ssl_module
正確な必要になるVersionやPluginが気になる方は自分で調べてください。
設定
デフォルト設定に追記していく想定です。
自身のNginxの設定や環境に合わせて読み替えてください。
/etc/nginx/nginx.conf
の最下行に以下を追加します。
stream {
upstream smtp-server{
server my.mail.server1.com:25 weight=3;
server my.mail.server2.com:25;
server my.mail.server3.com:25;
}
server {
listen 2525;
proxy_pass smtp-server;
error_log /var/log/nginx/mail-tcp-proxy.log info;
}
}
mail {
# See /etc/nginx/sites-available/mail_auth
auth_http localhost:8025/mail_auth/;
proxy on;
proxy_pass_error_message on;
smtp_auth none;
smtp_capabilities "SIZE 10485760" 8BITMIME ENHANCEDSTATUSCODES DSN ;
ssl off;
xclient off;
server {
listen 25;
protocol smtp;
error_log /var/log/nginx/mail-smtp-proxy.log info;
}
}
/etc/nginx/sites-available/mail_auth
を以下の内容で作成します。
log_format mail-auth-log '$host - $remote_user [$time_local] '
'$request_time '
'"$http_auth_smtp_helo" '
'"$http_auth_smtp_from" '
'"$http_auth_smtp_to"';
server {
listen 8025;
server_name localhost;
charset utf-8;
access_log /var/log/nginx/mail-send.log mail-auth-log;
error_log /var/log/nginx/mail-auth-error.log;
location ~ /mail_auth/ {
add_header Auth-Status OK;
add_header Auth-Server 127.0.0.1;
add_header Auth-Port 2525;
empty_gif;
break;
}
}
SymbolicLinkを作っておきます。
$ sudo ln -sf /etc/nginx/sites-available/mail_auth /etc/nginx/sites-enabled/mail_auth
$ sudo ls -l /etc/nginx/sites-enabled/mail_auth
lrwxrwxrwx 1 root root ss MMM d hh:mm /etc/nginx/sites-enabled/mail_auth -> /etc/nginx/sites-available/mail_auth
リロードしたら有効になるはずです。
$ sudo service nginx reload
送信に成功した場合のログはこんな感じになるはずです。
$ tail -n100 /var/log/nginx/mail-*.log
==> /var/log/nginx/mail-send.log <==
localhost - - [02/May/2017:18:31:31 +0900] 0.000 "app-srv.c.app-grp.internal" "MAIL FROM:<test@mail.com>" "RCPT TO:<someone@foo.org>"
==> /var/log/nginx/mail-smtp-proxy.log <==
2017/05/02 18:31:31 [info] 17222#17222: *3811 client 127.0.0.1:54096 connected to 0.0.0.0:25
2017/05/02 18:31:31 [info] 17222#17222: *3811 client logged in, client: 127.0.0.1, server: 0.0.0.0:25
2017/05/02 18:31:32 [info] 17222#17222: *3811 proxied session done, client: 127.0.0.1, server: 0.0.0.0:25
==> /var/log/nginx/mail-tcp-proxy.log <==
2017/05/02 18:31:31 [info] 17221#17221: *3815 client 127.0.0.1:38740 connected to 0.0.0.0:2525
2017/05/02 18:31:31 [info] 17221#17221: *3815 proxy nnn.nnn.nnn.nnn:33726 connected to xxx.xxx.xxx.xxx:2525
2017/05/02 18:31:32 [info] 17221#17221: *3815 upstream disconnected, bytes from/to client:832/267, bytes from/to upstream:267/832
mail-send.log以外のログは、動作確認が終わればinfoレベルじゃなくてもいいと思います。
以上です。
参考
モジュール・リファレンス(公式)
https://nginx.org/en/docs/http/load_balancing.html
https://nginx.org/en/docs/stream/ngx_stream_core_module.html
https://nginx.org/en/docs/mail/ngx_mail_core_module.html
https://nginx.org/en/docs/mail/ngx_mail_smtp_module.html
ラウンドロビンをmail_auth(http)で行う場合の例
http://qiita.com/ma3ki/items/44dab8d93423978dd5d9