Help us understand the problem. What is going on with this article?

NginxのTCP Proxy機能とMail Proxy機能を使って常にSMTPをlocalhost:25で受けられるようにする

More than 3 years have passed since last update.

何の話?

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の最下行に以下を追加します。

ngix.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を以下の内容で作成します。

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

送信に成功した場合のログはこんな感じになるはずです。

log
$ 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

aya_eiya
主要な開発言語は軒並み扱えるオールラウンドプログラマです。サーバーサイドの仕事が多いですが、最近はFlutterとかやってます。
http://aya-eiya.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした