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

Maxim Dounin mdounin на mdounin.ru
Пн Янв 14 19:50:56 UTC 2019


Hello!

On Mon, Jan 14, 2019 at 06:02:46PM +0200, Dmitriy M. wrote:

> Возможно, не нашел в документации, но есть ли возможность указать от какого
> исходящего (локального) IP будет сделать запрос, если это запрос от mail
> модуля?

Нет, сейчас mail-модуль bind не умеет.

> Речь идет об аналоге proxy_bind из модулей http_proxy/stream_proxy
> http://nginx.org/ru/docs/http/ngx_http_proxy_module.html#proxy_bind . С их
> помощью мы успешно решаем проблему нехватки локальных портов при большом
> кол-ве исходящих соединений работая с HTTP.
> Хотелось бы найти аналог и в mail модуле, т.к. похоже начинает проявляться
> та же проблема нехватки локальных портов на почтовом прокси-сервере с
> установленным тут nginx и модулем mail, но как обойти её без создания
> дополнительных контейнеров (что бы исходящие IP были разные), пока не
> придумал (тюнинги системы выполнены, расширен диапазон разрешенных портов и
> пр.).

Кажется, в случае mail могут иметь смысл два возможных подхода: 
явная директива proxy_bind (со статически заданным значением, ибо 
переменных в mail нет), либо же заголовок ответа от auth-скрипта 
Auth-Bind (аналогично Auth-Server/Auth-Port, задающих собственно 
адрес проксирования).

Патч, добавляющий директиву proxy_bind:

# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1547495341 -10800
#      Mon Jan 14 22:49:01 2019 +0300
# Node ID 271bd1fa164251de128cdc35dc1295ceaaa06a30
# Parent  6d15e452fa2eaf19408e24a0d0fcc3a31344a289
Mail: proxy_bind.

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
@@ -13,11 +13,12 @@
 
 
 typedef struct {
-    ngx_flag_t  enable;
-    ngx_flag_t  pass_error_message;
-    ngx_flag_t  xclient;
-    size_t      buffer_size;
-    ngx_msec_t  timeout;
+    ngx_flag_t   enable;
+    ngx_flag_t   pass_error_message;
+    ngx_flag_t   xclient;
+    size_t       buffer_size;
+    ngx_msec_t   timeout;
+    ngx_addr_t  *local;
 } ngx_mail_proxy_conf_t;
 
 
@@ -35,6 +36,8 @@ static void ngx_mail_proxy_close_session
 static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf);
 static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent,
     void *child);
+static char *ngx_mail_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 
 
 static ngx_command_t  ngx_mail_proxy_commands[] = {
@@ -60,6 +63,13 @@ static ngx_command_t  ngx_mail_proxy_com
       offsetof(ngx_mail_proxy_conf_t, timeout),
       NULL },
 
+    { ngx_string("proxy_bind"),
+      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_mail_proxy_bind,
+      NGX_MAIL_SRV_CONF_OFFSET,
+      0,
+      NULL },
+
     { ngx_string("proxy_pass_error_message"),
       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -118,6 +128,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *
 
     s->connection->log->action = "connecting to upstream";
 
+    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
 
     p = ngx_pcalloc(s->connection->pool, sizeof(ngx_mail_proxy_ctx_t));
@@ -134,6 +145,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 = pcf->local;
 
     rc = ngx_event_connect_peer(&p->upstream);
 
@@ -150,8 +162,6 @@ ngx_mail_proxy_init(ngx_mail_session_t *
     s->connection->read->handler = ngx_mail_proxy_block_read;
     p->upstream.connection->write->handler = ngx_mail_proxy_dummy_handler;
 
-    pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
-
     s->proxy->buffer = ngx_create_temp_buf(s->connection->pool,
                                            pcf->buffer_size);
     if (s->proxy->buffer == NULL) {
@@ -1104,6 +1114,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c
     pcf->xclient = NGX_CONF_UNSET;
     pcf->buffer_size = NGX_CONF_UNSET_SIZE;
     pcf->timeout = NGX_CONF_UNSET_MSEC;
+    pcf->local = NGX_CONF_UNSET_PTR;
 
     return pcf;
 }
@@ -1121,6 +1132,52 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf
     ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
                               (size_t) ngx_pagesize);
     ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000);
+    ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);
 
     return NGX_CONF_OK;
 }
+
+
+static char *
+ngx_mail_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_mail_proxy_conf_t  *pcf = conf;
+
+    ngx_int_t   rc;
+    ngx_str_t  *value;
+
+    if (pcf->local != NGX_CONF_UNSET_PTR) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off") == 0) {
+        pcf->local = NULL;
+        return NGX_CONF_OK;
+    }
+
+    pcf->local = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
+    if (pcf->local == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    rc = ngx_parse_addr_port(cf->pool, pcf->local, value[1].data,
+                             value[1].len);
+
+    switch (rc) {
+    case NGX_OK:
+        pcf->local->name = value[1];
+        break;
+
+    case NGX_DECLINED:
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid address \"%V\"", &value[1]);
+        /* fall through */
+
+    default:
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}


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


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