[PATCH] Mail: added PROXY PROTOCOL support
muradm
mail at muradm.net
Tue Jan 19 15:38:05 UTC 2021
Sorry, my mercurial skills sucks. Last patch includes "set_real_ip_from"
support in the same way it is supported by "ngx_streams" without
variables implementation, i.e. it just configures the "real_ip thing",
but addresses cannot be used as variables else where in configuration.
On 2021.01.19 18:34, muradm wrote:
># HG changeset patch
># User muradm <mail at muradm.net>
># Date 1611069863 -10800
># Tue Jan 19 18:24:23 2021 +0300
># Node ID 4618e767b84c5b3a7712466edb5bf37e3f0294ed
># Parent 83c4622053b02821a12d522d08eaff3ac27e65e3
>Mail: added PROXY PROTOCOL support.
>
>This implements propxy protocol support for both upstream and downstream.
>
>Downstream proxy protocol support:
>
>mail {
> server {
> listen <port> [ssl] proxy_protocol;
> protocol <imap|pop3|smtp>;
> }
>}
>
>This will properly handle incoming connections from load balancer sending
>PROXY protocol header. Without this, it is impossible to run nginx mail
>proxy behind such balancer. Header reading is done with existing function
>"ngx_proxy_protocol_read", so it should support both v1 and v2 headers.
>This will also set "sockaddr" and "local_sockaddr" addresses from received
>header, mimicing "set_realip". While "realip_module" deals with variables
>etc., which is necessary for HTTP protocol, mail protocols are pretty
>strict, so there is no need for flexible handling of real addresses
>received.
>
>Upstream proxy protocol support:
>
>mail {
> server {
> listen <port> [ssl];
> protocol <imap|pop3|smtp>;
> proxy_protocol on;
> }
>}
>
>With this, upstream server (like Postfix, Exim, Dovecot) will have PROXY
>protocol header. Mentioned programs do support proxy protocol out of the
>box. Header is written with existing function "ngx_proxy_protocol_write"
>which supports only v1 header writing. Contents of header are written
>from "sockaddr" and "local_sockaddr".
>
>Downstream and upstream proxy protocol support:
>
>mail {
> server {
> listen <port> [ssl] proxy_protocol;
> protocol <imap|pop3|smtp>;
> proxy_protocol on;
> }
>}
>
>This will combine both receiving PROXY header and sending PROXY header. With
>this, upstream server (like Postfix, Exim, Dovecot) will receive the same
>header as was sent by downstream load balancer.
>
>Above configurations work for SSL as well and should be transparent to other
>mail related configurations.
>
>Added upstream server "connect_timeout" which defaults to 1 second.
>
>Server configurations enabling proxy_protocol in listen directive, require
>"set_real_ip_from" configuration. Like the following:
>
>mail {
> # ...
> server {
> listen 587 proxy_protocol;
> set_real_ip_from "192.168.1.1";
> set_real_ip_from "10.10.0.0/16";
> set_real_ip_from "0.0.0.0/0";
> }
>}
>
>With enabled "proxy_protocol" and missing at least one "set_real_ip_from",
>all connections will be dropped and at startup user will see in error_log:
>
> using PROXY protocol without set_real_ip_from \
> while reading PROXY protocol header
>
>When "set_real_ip_from" is provided, but remote address on physical connection
>does not satisfy any address criteria, at "notice" level, in error_log, user
>will see:
>
> UNTRUSTED PROXY protocol provider: 127.0.0.1 \
> while reading PROXY protocol header, \
> client: 127.0.0.1, server: 127.0.0.1:8143
>
>diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail.c
>--- a/src/mail/ngx_mail.c Tue Jan 12 16:59:31 2021 +0300
>+++ b/src/mail/ngx_mail.c Tue Jan 19 18:24:23 2021 +0300
>@@ -402,6 +402,7 @@
> addrs[i].addr = sin->sin_addr.s_addr;
>
> addrs[i].conf.ctx = addr[i].opt.ctx;
>+ addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
> #if (NGX_MAIL_SSL)
> addrs[i].conf.ssl = addr[i].opt.ssl;
> #endif
>@@ -436,6 +437,7 @@
> addrs6[i].addr6 = sin6->sin6_addr;
>
> addrs6[i].conf.ctx = addr[i].opt.ctx;
>+ addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
> #if (NGX_MAIL_SSL)
> addrs6[i].conf.ssl = addr[i].opt.ssl;
> #endif
>diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail.h
>--- a/src/mail/ngx_mail.h Tue Jan 12 16:59:31 2021 +0300
>+++ b/src/mail/ngx_mail.h Tue Jan 19 18:24:23 2021 +0300
>@@ -37,6 +37,7 @@
> unsigned bind:1;
> unsigned wildcard:1;
> unsigned ssl:1;
>+ unsigned proxy_protocol:1;
> #if (NGX_HAVE_INET6)
> unsigned ipv6only:1;
> #endif
>@@ -56,6 +57,7 @@
> ngx_mail_conf_ctx_t *ctx;
> ngx_str_t addr_text;
> ngx_uint_t ssl; /* unsigned ssl:1; */
>+ unsigned proxy_protocol:1;
> } ngx_mail_addr_conf_t;
>
> typedef struct {
>@@ -125,6 +127,8 @@
> ngx_mail_conf_ctx_t *ctx;
>
> ngx_uint_t listen; /* unsigned listen:1; */
>+
>+ ngx_array_t *realip_from; /* array of ngx_cidr_t */
> } ngx_mail_core_srv_conf_t;
>
>
>@@ -190,6 +194,7 @@
> void **ctx;
> void **main_conf;
> void **srv_conf;
>+ ngx_mail_addr_conf_t *addr_conf;
>
> ngx_resolver_ctx_t *resolver_ctx;
>
>@@ -197,6 +202,7 @@
>
> ngx_uint_t mail_state;
>
>+ unsigned proxy_protocol:1;
> unsigned protocol:3;
> unsigned blocked:1;
> unsigned quit:1;
>diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_core_module.c
>--- a/src/mail/ngx_mail_core_module.c Tue Jan 12 16:59:31 2021 +0300
>+++ b/src/mail/ngx_mail_core_module.c Tue Jan 19 18:24:23 2021 +0300
>@@ -25,7 +25,7 @@
> void *conf);
> static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
> void *conf);
>-
>+static char *ngx_mail_core_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
>
> static ngx_command_t ngx_mail_core_commands[] = {
>
>@@ -85,6 +85,13 @@
> offsetof(ngx_mail_core_srv_conf_t, resolver_timeout),
> NULL },
>
>+ { ngx_string("set_real_ip_from"),
>+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
>+ ngx_mail_core_realip_from,
>+ NGX_MAIL_SRV_CONF_OFFSET,
>+ offsetof(ngx_mail_core_srv_conf_t, realip_from),
>+ NULL },
>+
> ngx_null_command
> };
>
>@@ -165,6 +172,8 @@
>
> cscf->resolver = NGX_CONF_UNSET_PTR;
>
>+ cscf->realip_from = NGX_CONF_UNSET_PTR;
>+
> cscf->file_name = cf->conf_file->file.name.data;
> cscf->line = cf->conf_file->line;
>
>@@ -206,6 +215,10 @@
>
> ngx_conf_merge_ptr_value(conf->resolver, prev->resolver, NULL);
>
>+ ngx_conf_merge_ptr_value(conf->realip_from,
>+ prev->realip_from,
>+ NGX_CONF_UNSET_PTR);
>+
> return NGX_CONF_OK;
> }
>
>@@ -548,6 +561,11 @@
> #endif
> }
>
>+ if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
>+ ls->proxy_protocol = 1;
>+ continue;
>+ }
>+
> ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
> "the invalid \"%V\" parameter", &value[i]);
> return NGX_CONF_ERROR;
>@@ -676,3 +694,104 @@
>
> return NGX_CONF_OK;
> }
>+
>+char *
>+ngx_mail_core_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
>+{
>+ ngx_mail_core_srv_conf_t *cscf = conf;
>+
>+ ngx_int_t rc;
>+ ngx_str_t *value;
>+ ngx_url_t u;
>+ ngx_cidr_t c, *cidr;
>+ ngx_uint_t i;
>+ struct sockaddr_in *sin;
>+#if (NGX_HAVE_INET6)
>+ struct sockaddr_in6 *sin6;
>+#endif
>+
>+ value = cf->args->elts;
>+
>+ if (cscf->realip_from == NGX_CONF_UNSET_PTR) {
>+ cscf->realip_from = ngx_array_create(cf->pool, 2, sizeof(ngx_cidr_t));
>+ if (cscf->realip_from == NULL) {
>+ return NGX_CONF_ERROR;
>+ }
>+ }
>+
>+#if (NGX_HAVE_UNIX_DOMAIN)
>+
>+ if (ngx_strcmp(value[1].data, "unix:") == 0) {
>+ cidr = ngx_array_push(cscf->realip_from);
>+ if (cidr == NULL) {
>+ return NGX_CONF_ERROR;
>+ }
>+
>+ cidr->family = AF_UNIX;
>+ return NGX_CONF_OK;
>+ }
>+
>+#endif
>+
>+ rc = ngx_ptocidr(&value[1], &c);
>+
>+ if (rc != NGX_ERROR) {
>+ if (rc == NGX_DONE) {
>+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
>+ "low address bits of %V are meaningless",
>+ &value[1]);
>+ }
>+
>+ cidr = ngx_array_push(cscf->realip_from);
>+ if (cidr == NULL) {
>+ return NGX_CONF_ERROR;
>+ }
>+
>+ *cidr = c;
>+
>+ return NGX_CONF_OK;
>+ }
>+
>+ ngx_memzero(&u, sizeof(ngx_url_t));
>+ u.host = value[1];
>+
>+ if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
>+ if (u.err) {
>+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
>+ "%s in set_real_ip_from \"%V\"",
>+ u.err, &u.host);
>+ }
>+
>+ return NGX_CONF_ERROR;
>+ }
>+
>+ cidr = ngx_array_push_n(cscf->realip_from, u.naddrs);
>+ if (cidr == NULL) {
>+ return NGX_CONF_ERROR;
>+ }
>+
>+ ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
>+
>+ for (i = 0; i < u.naddrs; i++) {
>+ cidr[i].family = u.addrs[i].sockaddr->sa_family;
>+
>+ switch (cidr[i].family) {
>+
>+#if (NGX_HAVE_INET6)
>+ case AF_INET6:
>+ sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
>+ cidr[i].u.in6.addr = sin6->sin6_addr;
>+ ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
>+ break;
>+#endif
>+
>+ default: /* AF_INET */
>+ sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
>+ cidr[i].u.in.addr = sin->sin_addr.s_addr;
>+ cidr[i].u.in.mask = 0xffffffff;
>+ break;
>+ }
>+ }
>+
>+ return NGX_CONF_OK;
>+}
>diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_handler.c
>--- a/src/mail/ngx_mail_handler.c Tue Jan 12 16:59:31 2021 +0300
>+++ b/src/mail/ngx_mail_handler.c Tue Jan 19 18:24:23 2021 +0300
>@@ -12,6 +12,8 @@
>
>
> static void ngx_mail_init_session(ngx_connection_t *c);
>+static void ngx_mail_init_connection_complete(ngx_connection_t *c);
>+static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev);
>
> #if (NGX_MAIL_SSL)
> static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
>@@ -128,6 +130,7 @@
>
> s->main_conf = addr_conf->ctx->main_conf;
> s->srv_conf = addr_conf->ctx->srv_conf;
>+ s->addr_conf = addr_conf;
>
> s->addr_text = &addr_conf->addr_text;
>
>@@ -159,13 +162,181 @@
>
> c->log_error = NGX_ERROR_INFO;
>
>+ /*
>+ * Before all process proxy protocol
>+ */
>+
>+ if (addr_conf->proxy_protocol) {
>+ s->proxy_protocol = 1;
>+ c->log->action = "reading PROXY protocol header";
>+ c->read->handler = ngx_mail_proxy_protocol_handler;
>+
>+ ngx_add_timer(c->read, cscf->timeout);
>+
>+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
>+ ngx_mail_close_connection(c);
>+ }
>+
>+ return;
>+ }
>+
>+ ngx_mail_init_connection_complete(c);
>+}
>+
>+
>+ngx_int_t
>+ngx_mail_proxy_protoco_set_addrs(ngx_connection_t *c)
>+{
>+ ngx_addr_t addr_peer, addr_local;
>+ u_char *p, text[NGX_SOCKADDR_STRLEN];
>+ size_t len;
>+
>+ if (ngx_parse_addr(c->pool, &addr_peer,
>+ c->proxy_protocol->src_addr.data,
>+ c->proxy_protocol->src_addr.len) != NGX_OK)
>+ {
>+ return NGX_ERROR;
>+ }
>+
>+ ngx_inet_set_port(addr_peer.sockaddr, c->proxy_protocol->src_port);
>+
>+ if (ngx_parse_addr(c->pool, &addr_local,
>+ c->proxy_protocol->dst_addr.data,
>+ c->proxy_protocol->dst_addr.len) != NGX_OK)
>+ {
>+ return NGX_ERROR;
>+ }
>+
>+ ngx_inet_set_port(addr_local.sockaddr, c->proxy_protocol->dst_port);
>+
>+ len = ngx_sock_ntop(addr_peer.sockaddr, addr_peer.socklen, text,
>+ NGX_SOCKADDR_STRLEN, 0);
>+ if (len == 0) {
>+ return NGX_ERROR;
>+ }
>+
>+ p = ngx_pnalloc(c->pool, len);
>+ if (p == NULL) {
>+ return NGX_ERROR;
>+ }
>+
>+ ngx_memcpy(p, text, len);
>+
>+ c->sockaddr = addr_peer.sockaddr;
>+ c->socklen = addr_peer.socklen;
>+ c->addr_text.len = len;
>+ c->addr_text.data = p;
>+
>+ len = ngx_sock_ntop(addr_local.sockaddr, addr_local.socklen, text,
>+ NGX_SOCKADDR_STRLEN, 0);
>+ if (len == 0) {
>+ return NGX_ERROR;
>+ }
>+
>+ p = ngx_pnalloc(c->pool, len);
>+ if (p == NULL) {
>+ return NGX_ERROR;
>+ }
>+
>+ ngx_memcpy(p, text, len);
>+
>+ c->local_sockaddr = addr_local.sockaddr;
>+ c->local_socklen = addr_local.socklen;
>+
>+ return NGX_OK;
>+}
>+
>+
>+void
>+ngx_mail_proxy_protocol_handler(ngx_event_t *rev)
>+{
>+ ngx_mail_core_srv_conf_t *cscf;
>+ ngx_mail_session_t *s;
>+ ngx_connection_t *c;
>+ u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
>+ size_t size;
>+ ssize_t n;
>+
>+ c = rev->data;
>+ s = c->data;
>+
>+ if (rev->timedout) {
>+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
>+ "mail PROXY protocol header timed out");
>+ c->timedout = 1;
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0,
>+ "mail PROXY protocol handler");
>+
>+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
>+
>+ if (cscf->realip_from == NGX_CONF_UNSET_PTR) {
>+ ngx_log_error(NGX_LOG_WARN, c->log, 0,
>+ "using PROXY protocol without set_real_ip_from");
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ if (ngx_cidr_match(c->sockaddr, cscf->realip_from) != NGX_OK) {
>+ ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
>+ "UNTRUSTED PROXY protocol provider: %V",
>+ &c->addr_text);
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ size = NGX_PROXY_PROTOCOL_MAX_HEADER;
>+
>+ n = recv(c->fd, (char *) buf, size, MSG_PEEK);
>+
>+ ngx_log_debug1(NGX_LOG_DEBUG, c->log, 0, "mail recv(): %z", n);
>+
>+ p = ngx_proxy_protocol_read(c, buf, buf + n);
>+
>+ if (p == NULL) {
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ ngx_log_error(NGX_LOG_NOTICE, c->log, 0,
>+ "PROXY protocol %V:%d => %V:%d",
>+ &c->proxy_protocol->src_addr,
>+ c->proxy_protocol->src_port,
>+ &c->proxy_protocol->dst_addr,
>+ c->proxy_protocol->dst_port);
>+
>+ size = p - buf;
>+
>+ if (c->recv(c, buf, size) != (ssize_t) size) {
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ if (ngx_mail_proxy_protoco_set_addrs(c) != NGX_OK) {
>+ ngx_mail_close_connection(c);
>+ return;
>+ }
>+
>+ ngx_mail_init_connection_complete(c);
>+}
>+
>+
>+void
>+ngx_mail_init_connection_complete(ngx_connection_t *c)
>+{
> #if (NGX_MAIL_SSL)
> {
>- ngx_mail_ssl_conf_t *sslcf;
>+ ngx_mail_session_t *s;
>+ ngx_mail_ssl_conf_t *sslcf;
>+
>+ s = c->data;
>
> sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
>
>- if (sslcf->enable || addr_conf->ssl) {
>+ if (sslcf->enable || s->addr_conf->ssl) {
> c->log->action = "SSL handshaking";
>
> ngx_mail_ssl_init_connection(&sslcf->ssl, c);
>@@ -348,6 +519,7 @@
> return;
> }
>
>+ c->log->action = "sending client greeting line";
> c->write->handler = ngx_mail_send;
>
> cscf->protocol->init_session(s, c);
>diff -r 83c4622053b0 -r 4618e767b84c src/mail/ngx_mail_proxy_module.c
>--- a/src/mail/ngx_mail_proxy_module.c Tue Jan 12 16:59:31 2021 +0300
>+++ b/src/mail/ngx_mail_proxy_module.c Tue Jan 19 18:24:23 2021 +0300
>@@ -19,6 +19,8 @@
> ngx_flag_t smtp_auth;
> size_t buffer_size;
> ngx_msec_t timeout;
>+ ngx_msec_t connect_timeout;
>+ ngx_flag_t proxy_protocol;
> } ngx_mail_proxy_conf_t;
>
>
>@@ -36,7 +38,9 @@
> 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 void ngx_mail_proxy_connect_handler(ngx_event_t *ev);
>+static void ngx_mail_proxy_start(ngx_mail_session_t *s);
>+static void ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s);
>
> static ngx_command_t ngx_mail_proxy_commands[] = {
>
>@@ -61,6 +65,13 @@
> offsetof(ngx_mail_proxy_conf_t, timeout),
> NULL },
>
>+ { ngx_string("connect_timeout"),
>+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
>+ ngx_conf_set_msec_slot,
>+ NGX_MAIL_SRV_CONF_OFFSET,
>+ offsetof(ngx_mail_proxy_conf_t, connect_timeout),
>+ NULL },
>+
> { ngx_string("proxy_pass_error_message"),
> NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
> ngx_conf_set_flag_slot,
>@@ -82,6 +93,13 @@
> offsetof(ngx_mail_proxy_conf_t, smtp_auth),
> NULL },
>
>+ { ngx_string("proxy_protocol"),
>+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
>+ ngx_conf_set_flag_slot,
>+ NGX_MAIL_SRV_CONF_OFFSET,
>+ offsetof(ngx_mail_proxy_conf_t, proxy_protocol),
>+ NULL },
>+
> ngx_null_command
> };
>
>@@ -156,7 +174,6 @@
> p->upstream.connection->pool = s->connection->pool;
>
> 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);
>
>@@ -169,23 +186,139 @@
>
> s->out.len = 0;
>
>+ if (rc == NGX_AGAIN) {
>+ p->upstream.connection->write->handler = ngx_mail_proxy_connect_handler;
>+ p->upstream.connection->read->handler = ngx_mail_proxy_connect_handler;
>+
>+ ngx_add_timer(p->upstream.connection->write, pcf->connect_timeout);
>+
>+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, "mail proxy delay connect");
>+ return;
>+ }
>+
>+ if (pcf->proxy_protocol) {
>+ ngx_mail_proxy_send_proxy_protocol(s);
>+ return;
>+ }
>+
>+ ngx_mail_proxy_start(s);
>+}
>+
>+
>+void
>+ngx_mail_proxy_connect_handler(ngx_event_t *ev)
>+{
>+ ngx_connection_t *c;
>+ ngx_mail_session_t *s;
>+ ngx_mail_proxy_conf_t *pcf;
>+
>+ c = ev->data;
>+ s = c->data;
>+
>+ if (ev->timedout) {
>+ ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "upstream timed out");
>+ ngx_mail_session_internal_server_error(s);
>+ return;
>+ }
>+
>+ ngx_del_timer(c->write);
>+
>+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0,
>+ "mail proxy connect upstream");
>+
>+ pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
>+
>+ if (pcf->proxy_protocol) {
>+ ngx_mail_proxy_send_proxy_protocol(s);
>+ return;
>+ }
>+
>+ ngx_mail_proxy_start(s);
>+}
>+
>+
>+void
>+ngx_mail_proxy_start(ngx_mail_session_t *s)
>+{
>+ ngx_connection_t *pc;
>+
>+ pc = s->proxy->upstream.connection;
>+
>+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, s->connection->log, 0,
>+ "mail proxy starting");
>+
>+ pc->write->handler = ngx_mail_proxy_dummy_handler;
>+
> switch (s->protocol) {
>
> case NGX_MAIL_POP3_PROTOCOL:
>- p->upstream.connection->read->handler = ngx_mail_proxy_pop3_handler;
>+ pc->read->handler = ngx_mail_proxy_pop3_handler;
> s->mail_state = ngx_pop3_start;
> break;
>
> case NGX_MAIL_IMAP_PROTOCOL:
>- p->upstream.connection->read->handler = ngx_mail_proxy_imap_handler;
>+ pc->read->handler = ngx_mail_proxy_imap_handler;
> s->mail_state = ngx_imap_start;
> break;
>
> default: /* NGX_MAIL_SMTP_PROTOCOL */
>- p->upstream.connection->read->handler = ngx_mail_proxy_smtp_handler;
>+ pc->read->handler = ngx_mail_proxy_smtp_handler;
> s->mail_state = ngx_smtp_start;
> break;
> }
>+
>+ if (pc->read->ready) {
>+ ngx_post_event(pc->read, &ngx_posted_events);
>+ }
>+}
>+
>+
>+void
>+ngx_mail_proxy_send_proxy_protocol(ngx_mail_session_t *s)
>+{
>+ u_char *p;
>+ ssize_t n, size;
>+ ngx_connection_t *c, *pc;
>+ ngx_peer_connection_t *u;
>+ u_char buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
>+
>+ c = s->connection;
>+
>+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0,
>+ "mail proxy send PROXY protocol header");
>+
>+ p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER);
>+ if (p == NULL) {
>+ ngx_mail_proxy_internal_server_error(s);
>+ return;
>+ }
>+
>+ u = &s->proxy->upstream;
>+
>+ pc = u->connection;
>+
>+ size = p - buf;
>+
>+ n = pc->send(pc, buf, size);
>+
>+ if (n != size) {
>+
>+ /*
>+ * PROXY protocol specification:
>+ * The sender must always ensure that the header
>+ * is sent at once, so that the transport layer
>+ * maintains atomicity along the path to the receiver.
>+ */
>+
>+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
>+ "could not send PROXY protocol header at once (%z)", n);
>+
>+ ngx_mail_proxy_internal_server_error(s);
>+
>+ return;
>+ }
>+
>+ ngx_mail_proxy_start(s);
> }
>
>
>@@ -1184,6 +1317,8 @@
> pcf->smtp_auth = NGX_CONF_UNSET;
> pcf->buffer_size = NGX_CONF_UNSET_SIZE;
> pcf->timeout = NGX_CONF_UNSET_MSEC;
>+ pcf->connect_timeout = NGX_CONF_UNSET_MSEC;
>+ pcf->proxy_protocol = NGX_CONF_UNSET;
>
> return pcf;
> }
>@@ -1202,6 +1337,8 @@
> 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_msec_value(conf->connect_timeout, prev->connect_timeout, 1000);
>+ ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);
>
> return NGX_CONF_OK;
> }
--
Murad
M(tr): +90 (533) 4874329
M(az): +994 (50) 2219909
More information about the nginx-devel
mailing list