Re: Возможность сделать bind() для исходящих запросов модуля mail

Maxim Dounin mdounin на mdounin.ru
Вт Янв 15 13:43:51 UTC 2019


Hello!

On Tue, Jan 15, 2019 at 01:28:52PM +0200, Dmitriy M. wrote:

> Спасибо за развернутый ответ и патч.
> 
> Мы модифицировали патч, добавив логику перебора IP исходящих соединений. В
> нашем случае нам достаточно 4х IP, т.е.:
> 
> proxy_bind      10.10.0.1 10.10.0.2 10.10.0.3 10.10.0.4;
> 
> Вроде работает пока, балансируя соединения с 4 IP поровну.

Нет, так мы точно делать не будем.  Если хочется вращать много 
локальных адресов в рамках одного сервера - то вот патч, который 
позволяет задать локальный адрес из auth-скрипта с помощью 
заголовка Auth-Bind:

# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1547559561 -10800
#      Tue Jan 15 16:39:21 2019 +0300
# Node ID 7d052f39bf8c8fb028569e290f67edf4bacb3252
# Parent  6d15e452fa2eaf19408e24a0d0fcc3a31344a289
Mail: Auth-Bind header.

diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -400,7 +400,8 @@ char *ngx_mail_capabilities(ngx_conf_t *
 
 
 /* STUB */
-void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer);
+void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer,
+    ngx_addr_t *local);
 void ngx_mail_auth_http_init(ngx_mail_session_t *s);
 /**/
 
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -53,6 +53,7 @@ struct ngx_mail_auth_http_ctx_s {
     ngx_str_t                       err;
     ngx_str_t                       errmsg;
     ngx_str_t                       errcode;
+    ngx_str_t                       bind;
 
     time_t                          sleep;
 
@@ -467,7 +468,7 @@ ngx_mail_auth_http_process_headers(ngx_m
     time_t       timer;
     size_t       len, size;
     ngx_int_t    rc, port, n;
-    ngx_addr_t  *peer;
+    ngx_addr_t  *peer, *local;
 
     ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
                    "mail auth http process headers");
@@ -677,6 +678,18 @@ ngx_mail_auth_http_process_headers(ngx_m
                 continue;
             }
 
+            if (len == sizeof("Auth-Bind") - 1
+                && ngx_strncasecmp(ctx->header_name_start,
+                                   (u_char *) "Auth-Bind",
+                                   sizeof("Auth-Bind") - 1)
+                    == 0)
+            {
+                ctx->bind.len = ctx->header_end - ctx->header_start;
+                ctx->bind.data = ctx->header_start;
+
+                continue;
+            }
+
             /* ignore other headers */
 
             continue;
@@ -772,6 +785,52 @@ ngx_mail_auth_http_process_headers(ngx_m
                 return;
             }
 
+            if (ctx->bind.len) {
+
+                local = ngx_palloc(s->connection->pool, sizeof(ngx_addr_t));
+                if (local == NULL) {
+                    ngx_close_connection(ctx->peer.connection);
+                    ngx_destroy_pool(ctx->pool);
+                    ngx_mail_session_internal_server_error(s);
+                    return;
+                }
+
+                rc = ngx_parse_addr_port(s->connection->pool, local,
+                                         ctx->bind.data, ctx->bind.len);
+
+                switch (rc) {
+                case NGX_OK:
+                    break;
+
+                case NGX_DECLINED:
+                    ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+                                  "auth http server %V sent invalid bind "
+                                  "address:\"%V\"",
+                                  ctx->peer.name, &ctx->bind);
+                    /* fall through */
+
+                default:
+                    ngx_destroy_pool(ctx->pool);
+                    ngx_mail_session_internal_server_error(s);
+                    return;
+                }
+
+                local->name.len = ctx->bind.len;
+
+                local->name.data = ngx_pnalloc(s->connection->pool,
+                                               local->name.len);
+                if (local->name.data == NULL) {
+                    ngx_destroy_pool(ctx->pool);
+                    ngx_mail_session_internal_server_error(s);
+                    return;
+                }
+
+                ngx_memcpy(local->name.data, ctx->bind.data, ctx->bind.len);
+
+            } else {
+                local = NULL;
+            }
+
             peer = ngx_pcalloc(s->connection->pool, sizeof(ngx_addr_t));
             if (peer == NULL) {
                 ngx_destroy_pool(ctx->pool);
@@ -832,7 +891,7 @@ ngx_mail_auth_http_process_headers(ngx_m
             ngx_memcpy(peer->name.data + len, ctx->port.data, ctx->port.len);
 
             ngx_destroy_pool(ctx->pool);
-            ngx_mail_proxy_init(s, peer);
+            ngx_mail_proxy_init(s, peer, local);
 
             return;
         }
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -109,7 +109,7 @@ static u_char  smtp_auth_ok[] = "235 2.0
 
 
 void
-ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer)
+ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t *peer, ngx_addr_t *local)
 {
     ngx_int_t                  rc;
     ngx_mail_proxy_ctx_t      *p;
@@ -134,6 +134,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *
     p->upstream.get = ngx_event_get_peer;
     p->upstream.log = s->connection->log;
     p->upstream.log_error = NGX_ERROR_ERR;
+    p->upstream.local = local;
 
     rc = ngx_event_connect_peer(&p->upstream);
 

-- 
Maxim Dounin
http://mdounin.ru/


Подробная информация о списке рассылки nginx-ru