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

  • 0
    いいね
  • 0
    コメント

    何の話?

    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