mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
resolver in smtp proxy module
This commit is contained in:
parent
04610ead82
commit
45450461b6
@ -81,6 +81,7 @@ typedef struct {
|
||||
ngx_mail_protocol_t *protocol;
|
||||
|
||||
ngx_msec_t timeout;
|
||||
ngx_msec_t resolver_timeout;
|
||||
|
||||
ngx_flag_t so_keepalive;
|
||||
|
||||
@ -89,6 +90,8 @@ typedef struct {
|
||||
u_char *file_name;
|
||||
ngx_int_t line;
|
||||
|
||||
ngx_resolver_t *resolver;
|
||||
|
||||
/* server ctx */
|
||||
ngx_mail_conf_ctx_t *ctx;
|
||||
} ngx_mail_core_srv_conf_t;
|
||||
@ -147,6 +150,8 @@ typedef struct {
|
||||
void **main_conf;
|
||||
void **srv_conf;
|
||||
|
||||
ngx_resolver_ctx_t *resolver_ctx;
|
||||
|
||||
ngx_mail_proxy_ctx_t *proxy;
|
||||
|
||||
ngx_uint_t mail_state;
|
||||
@ -171,6 +176,7 @@ typedef struct {
|
||||
ngx_str_t text;
|
||||
|
||||
ngx_str_t *addr_text;
|
||||
ngx_str_t host;
|
||||
ngx_str_t smtp_helo;
|
||||
|
||||
ngx_uint_t command;
|
||||
|
@ -20,6 +20,8 @@ static char *ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
||||
static ngx_command_t ngx_mail_core_commands[] = {
|
||||
@ -66,6 +68,20 @@ static ngx_command_t ngx_mail_core_commands[] = {
|
||||
offsetof(ngx_mail_core_srv_conf_t, server_name),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("resolver"),
|
||||
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
|
||||
ngx_mail_core_resolver,
|
||||
NGX_MAIL_SRV_CONF_OFFSET,
|
||||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("resolver_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_core_srv_conf_t, resolver_timeout),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
@ -138,11 +154,16 @@ ngx_mail_core_create_srv_conf(ngx_conf_t *cf)
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* cscf->protocol = NULL;
|
||||
* cscf->resolver = NULL;
|
||||
*/
|
||||
|
||||
cscf->timeout = NGX_CONF_UNSET_MSEC;
|
||||
cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
|
||||
cscf->so_keepalive = NGX_CONF_UNSET;
|
||||
|
||||
cscf->file_name = cf->conf_file->file.name.data;
|
||||
cscf->line = cf->conf_file->line;
|
||||
|
||||
return cscf;
|
||||
}
|
||||
|
||||
@ -154,6 +175,8 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_mail_core_srv_conf_t *conf = child;
|
||||
|
||||
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);
|
||||
ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout,
|
||||
30000);
|
||||
|
||||
ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0);
|
||||
|
||||
@ -184,6 +207,10 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (conf->resolver == NULL) {
|
||||
conf->resolver = prev->resolver;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
@ -237,9 +264,6 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index];
|
||||
cscf->ctx = ctx;
|
||||
|
||||
cscf->file_name = cf->conf_file->file.name.data;
|
||||
cscf->line = cf->conf_file->line;
|
||||
|
||||
cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index];
|
||||
|
||||
cscfp = ngx_array_push(&cmcf->servers);
|
||||
@ -389,6 +413,35 @@ ngx_mail_core_protocol(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_mail_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_mail_core_srv_conf_t *cscf = conf;
|
||||
|
||||
ngx_url_t u;
|
||||
ngx_str_t *value;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||
|
||||
u.host = value[1];
|
||||
u.port = 53;
|
||||
|
||||
if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
cscf->resolver = ngx_resolver_create(&u.addrs[0], cf->cycle->new_log);
|
||||
if (cscf->resolver == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
|
@ -528,10 +528,10 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
|
||||
|
||||
s->connection->log->action = "sending XCLIENT to upstream";
|
||||
|
||||
line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= "
|
||||
"NAME=[UNAVAILABLE]" CRLF) - 1
|
||||
line.len = sizeof("XCLIENT PROTO=SMTP HELO= ADDR= LOGIN= NAME="
|
||||
CRLF) - 1
|
||||
+ s->esmtp + s->smtp_helo.len
|
||||
+ s->connection->addr_text.len + s->login.len;
|
||||
+ s->connection->addr_text.len + s->login.len + s->host.len;
|
||||
|
||||
line.data = ngx_palloc(c->pool, line.len);
|
||||
if (line.data == NULL) {
|
||||
@ -542,15 +542,14 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
|
||||
if (s->smtp_helo.len) {
|
||||
line.len = ngx_sprintf(line.data,
|
||||
"XCLIENT PROTO=%sSMTP HELO=%V ADDR=%V LOGIN=%V "
|
||||
"NAME=[UNAVAILABLE]" CRLF,
|
||||
"NAME=%V" CRLF,
|
||||
(s->esmtp ? "E" : ""), &s->smtp_helo,
|
||||
&s->connection->addr_text, &s->login)
|
||||
&s->connection->addr_text, &s->login, &s->host)
|
||||
- line.data;
|
||||
} else {
|
||||
line.len = ngx_sprintf(line.data,
|
||||
"XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V "
|
||||
"NAME=[UNAVAILABLE]" CRLF,
|
||||
&s->connection->addr_text, &s->login)
|
||||
"XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V NAME=%V" CRLF,
|
||||
&s->connection->addr_text, &s->login, &s->host)
|
||||
- line.data;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include <ngx_mail_smtp_module.h>
|
||||
|
||||
|
||||
static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
|
||||
static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
|
||||
static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
|
||||
static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
|
||||
static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
|
||||
ngx_connection_t *c);
|
||||
@ -40,13 +43,176 @@ static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;
|
||||
static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
|
||||
|
||||
|
||||
static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]");
|
||||
static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
|
||||
|
||||
|
||||
void
|
||||
ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
{
|
||||
struct sockaddr_in *sin;
|
||||
ngx_resolver_ctx_t *ctx;
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
|
||||
c->log->action = "in resolving client address";
|
||||
|
||||
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
|
||||
|
||||
ctx = ngx_resolve_start(cscf->resolver, NULL);
|
||||
if (ctx == NULL) {
|
||||
ngx_mail_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* AF_INET only */
|
||||
|
||||
sin = (struct sockaddr_in *) c->sockaddr;
|
||||
|
||||
ctx->addr = sin->sin_addr.s_addr;
|
||||
ctx->handler = ngx_mail_smtp_resolve_addr_handler;
|
||||
ctx->data = s;
|
||||
ctx->timeout = cscf->resolver_timeout;
|
||||
|
||||
if (ngx_resolve_addr(ctx) != NGX_OK) {
|
||||
ngx_mail_close_connection(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
ngx_mail_session_t *s;
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
|
||||
s = ctx->data;
|
||||
c = s->connection;
|
||||
|
||||
if (ctx->state) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"%V could not be resolved (%i: %s)",
|
||||
&c->addr_text, ctx->state,
|
||||
ngx_resolver_strerror(ctx->state));
|
||||
|
||||
if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
|
||||
s->host = smtp_unavailable;
|
||||
|
||||
} else {
|
||||
s->host = smtp_tempunavail;
|
||||
}
|
||||
|
||||
ngx_resolve_addr_done(ctx);
|
||||
|
||||
ngx_mail_smtp_greeting(s, s->connection);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
c->log->action = "in resolving client hostname";
|
||||
|
||||
s->host.data = ngx_pstrdup(c->pool, &ctx->name);
|
||||
if (s->host.data == NULL) {
|
||||
ngx_resolve_addr_done(ctx);
|
||||
ngx_mail_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
s->host.len = ctx->name.len;
|
||||
|
||||
ngx_resolve_addr_done(ctx);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"address resolved: %V", &s->host);
|
||||
|
||||
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
|
||||
|
||||
ctx = ngx_resolve_start(cscf->resolver, NULL);
|
||||
if (ctx == NULL) {
|
||||
ngx_mail_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->name = s->host;
|
||||
ctx->type = NGX_RESOLVE_A;
|
||||
ctx->handler = ngx_mail_smtp_resolve_name_handler;
|
||||
ctx->data = s;
|
||||
ctx->timeout = cscf->resolver_timeout;
|
||||
|
||||
if (ngx_resolve_name(ctx) != NGX_OK) {
|
||||
ngx_mail_close_connection(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
|
||||
{
|
||||
in_addr_t addr;
|
||||
ngx_uint_t i;
|
||||
ngx_connection_t *c;
|
||||
struct sockaddr_in *sin;
|
||||
ngx_mail_session_t *s;
|
||||
|
||||
s = ctx->data;
|
||||
c = s->connection;
|
||||
|
||||
if (ctx->state) {
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||
"%V could not be resolved (%i: %s)",
|
||||
&ctx->name, ctx->state,
|
||||
ngx_resolver_strerror(ctx->state));
|
||||
|
||||
if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
|
||||
s->host = smtp_unavailable;
|
||||
|
||||
} else {
|
||||
s->host = smtp_tempunavail;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* AF_INET only */
|
||||
|
||||
sin = (struct sockaddr_in *) c->sockaddr;
|
||||
|
||||
for (i = 0; i < ctx->naddrs; i++) {
|
||||
|
||||
addr = ctx->addrs[i];
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"name was resolved to %ud.%ud.%ud.%ud",
|
||||
(ntohl(addr) >> 24) & 0xff,
|
||||
(ntohl(addr) >> 16) & 0xff,
|
||||
(ntohl(addr) >> 8) & 0xff,
|
||||
ntohl(addr) & 0xff);
|
||||
|
||||
if (addr == sin->sin_addr.s_addr) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
s->host = smtp_unavailable;
|
||||
}
|
||||
|
||||
found:
|
||||
|
||||
ngx_resolve_name_done(ctx);
|
||||
|
||||
ngx_mail_smtp_greeting(s, c);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||
{
|
||||
ngx_msec_t timeout;
|
||||
ngx_mail_core_srv_conf_t *cscf;
|
||||
ngx_mail_smtp_srv_conf_t *sscf;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||
"smtp greeting for \"%V\"", &s->host);
|
||||
|
||||
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
|
||||
sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
|
||||
|
||||
|
@ -158,6 +158,15 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
cscf = ngx_mail_conf_get_module_srv_conf(cf, ngx_mail_core_module);
|
||||
|
||||
if (cscf->protocol->type == NGX_MAIL_SMTP_PROTOCOL
|
||||
&& cscf->resolver == NULL)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||
"undefined resolver for server in %s:%ui",
|
||||
cscf->file_name, cscf->line);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof("220 ESMTP ready" CRLF) - 1 + cscf->server_name.len;
|
||||
|
||||
p = ngx_palloc(cf->pool, size);
|
||||
|
Loading…
Reference in New Issue
Block a user