Welcome! Log In Create A New Profile

Advanced

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

Dmitriy M.
January 15, 2019 06:30AM
Спасибо за развернутый ответ и патч.

Мы модифицировали патч, добавив логику перебора IP исходящих соединений. В
нашем случае нам достаточно 4х IP, т.е.:

proxy_bind 10.10.0.1 10.10.0.2 10.10.0.3 10.10.0.4;

Вроде работает пока, балансируя соединения с 4 IP поровну.

Патч с модификацией:

diff --git a/src/mail/ngx_mail_proxy_module.c
b/src/mail/ngx_mail_proxy_module.c
index 1c86e54..da55a11 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -13,11 +13,14 @@


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;
+ size_t local_size;
+ size_t local_index;
} ngx_mail_proxy_conf_t;


@@ -35,6 +38,8 @@ static void
ngx_mail_proxy_close_session(ngx_mail_session_t *s);
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 +65,13 @@ static ngx_command_t ngx_mail_proxy_commands[] = {
offsetof(ngx_mail_proxy_conf_t, timeout),
NULL },

+ { ngx_string("proxy_bind"),
+
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1234|NGX_CONF_TAKE5|NGX_CONF_TAKE6|NGX_CONF_TAKE7,
+ 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 +130,7 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t
*peer)

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));
@@ -135,6 +148,16 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t
*peer)
p->upstream.log = s->connection->log;
p->upstream.log_error = NGX_ERROR_ERR;

+ if (pcf->local) {
+ p->upstream.local = pcf->local + pcf->local_index;
+
+ if (pcf->local_size > 1
+ && ++pcf->local_index >= pcf->local_size) {
+ /* wrap around */
+ pcf->local_index = 0;
+ }
+ }
+
rc = ngx_event_connect_peer(&p->upstream);

if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
@@ -150,8 +173,6 @@ ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_addr_t
*peer)
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 +1125,9 @@ ngx_mail_proxy_create_conf(ngx_conf_t *cf)
pcf->xclient = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
+ pcf->local = NGX_CONF_UNSET_PTR;
+ pcf->local_size = NGX_CONF_UNSET_SIZE;
+ pcf->local_index = NGX_CONF_UNSET_SIZE;

return pcf;
}
@@ -1121,6 +1145,57 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void
*parent, void *child)
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);
+ ngx_conf_merge_size_value(conf->local_size, prev->local_size, 0);
+ ngx_conf_merge_size_value(conf->local_index, prev->local_index, 0);
+
+ 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;
+ size_t i;
+
+ 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, (cf->args->nelts - 1) *
sizeof(ngx_addr_t));
+ if (pcf->local == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; i < (cf->args->nelts - 1); ++i) {
+ rc = ngx_parse_addr_port(cf->pool, pcf->local + i, value[i +
1].data,
+ value[i + 1].len);
+
+ switch (rc) {
+ case NGX_OK:
+ pcf->local[i].name = value[i + 1];
+ break;
+
+ case NGX_DECLINED:
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid address \"%V\"", &value[1 + 1]);
+ /* fall through */
+
+ default:
+ return NGX_CONF_ERROR;
+ }
+ }

+ pcf->local_size = (cf->args->nelts - 1);
return NGX_CONF_OK;
}


пн, 14 янв. 2019 г. в 21:51, Maxim Dounin <mdounin@mdounin.ru>:

> 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@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 mailing list
> nginx-ru@nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-ru
_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru
Subject Author Posted

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

Dmitriy M. January 14, 2019 11:04AM

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

Maxim Dounin January 14, 2019 02:52PM

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

Dmitriy M. January 15, 2019 06:30AM

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

Maxim Dounin January 15, 2019 08:44AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 148
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready