changeset 7795:ef4bdbbce57e

Mail: realip module. When configured with the "set_real_ip_from", it can set client's IP address as visible in logs to the one obtained via the PROXY protocol.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 05 Mar 2021 17:16:29 +0300
parents 12ea1de7d87c
children 4b8f23a36ebf
files auto/modules src/mail/ngx_mail.h src/mail/ngx_mail_handler.c src/mail/ngx_mail_realip_module.c
diffstat 4 files changed, 56 insertions(+), 176 deletions(-) [+]
line wrap: on
line diff
--- a/auto/modules
+++ b/auto/modules
@@ -985,6 +985,12 @@ if [ $MAIL != NO ]; then
     ngx_module_srcs=src/mail/ngx_mail_proxy_module.c
 
     . auto/module
+
+    ngx_module_name=ngx_mail_realip_module
+    ngx_module_deps=
+    ngx_module_srcs=src/mail/ngx_mail_realip_module.c
+
+    . auto/module
 fi
 
 
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -408,6 +408,7 @@ 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_auth_http_init(ngx_mail_session_t *s);
+ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s);
 /**/
 
 
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -260,6 +260,11 @@ ngx_mail_proxy_protocol_handler(ngx_even
         return;
     }
 
+    if (ngx_mail_realip_handler(s) != NGX_OK) {
+        ngx_mail_close_connection(c);
+        return;
+    }
+
     ngx_mail_init_session_handler(rev);
 }
 
copy from src/stream/ngx_stream_realip_module.c
copy to src/mail/ngx_mail_realip_module.c
--- a/src/stream/ngx_stream_realip_module.c
+++ b/src/mail/ngx_mail_realip_module.c
@@ -7,45 +7,29 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_stream.h>
+#include <ngx_mail.h>
 
 
 typedef struct {
     ngx_array_t       *from;     /* array of ngx_cidr_t */
-} ngx_stream_realip_srv_conf_t;
-
-
-typedef struct {
-    struct sockaddr   *sockaddr;
-    socklen_t          socklen;
-    ngx_str_t          addr_text;
-} ngx_stream_realip_ctx_t;
+} ngx_mail_realip_srv_conf_t;
 
 
-static ngx_int_t ngx_stream_realip_handler(ngx_stream_session_t *s);
-static ngx_int_t ngx_stream_realip_set_addr(ngx_stream_session_t *s,
+static ngx_int_t ngx_mail_realip_set_addr(ngx_mail_session_t *s,
     ngx_addr_t *addr);
-static char *ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
+static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
-static void *ngx_stream_realip_create_srv_conf(ngx_conf_t *cf);
-static char *ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent,
+static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf);
+static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent,
     void *child);
-static ngx_int_t ngx_stream_realip_add_variables(ngx_conf_t *cf);
-static ngx_int_t ngx_stream_realip_init(ngx_conf_t *cf);
 
 
-static ngx_int_t ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s,
-    ngx_stream_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s,
-    ngx_stream_variable_value_t *v, uintptr_t data);
-
-
-static ngx_command_t  ngx_stream_realip_commands[] = {
+static ngx_command_t  ngx_mail_realip_commands[] = {
 
     { ngx_string("set_real_ip_from"),
-      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
-      ngx_stream_realip_from,
-      NGX_STREAM_SRV_CONF_OFFSET,
+      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_mail_realip_from,
+      NGX_MAIL_SRV_CONF_OFFSET,
       0,
       NULL },
 
@@ -53,23 +37,22 @@ static ngx_command_t  ngx_stream_realip_
 };
 
 
-static ngx_stream_module_t  ngx_stream_realip_module_ctx = {
-    ngx_stream_realip_add_variables,       /* preconfiguration */
-    ngx_stream_realip_init,                /* postconfiguration */
+static ngx_mail_module_t  ngx_mail_realip_module_ctx = {
+    NULL,                                  /* protocol */
 
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
-    ngx_stream_realip_create_srv_conf,     /* create server configuration */
-    ngx_stream_realip_merge_srv_conf       /* merge server configuration */
+    ngx_mail_realip_create_srv_conf,       /* create server configuration */
+    ngx_mail_realip_merge_srv_conf         /* merge server configuration */
 };
 
 
-ngx_module_t  ngx_stream_realip_module = {
+ngx_module_t  ngx_mail_realip_module = {
     NGX_MODULE_V1,
-    &ngx_stream_realip_module_ctx,         /* module context */
-    ngx_stream_realip_commands,            /* module directives */
-    NGX_STREAM_MODULE,                     /* module type */
+    &ngx_mail_realip_module_ctx,           /* module context */
+    ngx_mail_realip_commands,              /* module directives */
+    NGX_MAIL_MODULE,                       /* module type */
     NULL,                                  /* init master */
     NULL,                                  /* init module */
     NULL,                                  /* init process */
@@ -81,70 +64,52 @@ ngx_module_t  ngx_stream_realip_module =
 };
 
 
-static ngx_stream_variable_t  ngx_stream_realip_vars[] = {
-
-    { ngx_string("realip_remote_addr"), NULL,
-      ngx_stream_realip_remote_addr_variable, 0, 0, 0 },
-
-    { ngx_string("realip_remote_port"), NULL,
-      ngx_stream_realip_remote_port_variable, 0, 0, 0 },
+ngx_int_t
+ngx_mail_realip_handler(ngx_mail_session_t *s)
+{
+    ngx_addr_t                   addr;
+    ngx_connection_t            *c;
+    ngx_mail_realip_srv_conf_t  *rscf;
 
-      ngx_stream_null_variable
-};
-
-
-static ngx_int_t
-ngx_stream_realip_handler(ngx_stream_session_t *s)
-{
-    ngx_addr_t                     addr;
-    ngx_connection_t              *c;
-    ngx_stream_realip_srv_conf_t  *rscf;
-
-    rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_realip_module);
+    rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module);
 
     if (rscf->from == NULL) {
-        return NGX_DECLINED;
+        return NGX_OK;
     }
 
     c = s->connection;
 
     if (c->proxy_protocol == NULL) {
-        return NGX_DECLINED;
+        return NGX_OK;
     }
 
     if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) {
-        return NGX_DECLINED;
+        return NGX_OK;
     }
 
     if (ngx_parse_addr(c->pool, &addr, c->proxy_protocol->src_addr.data,
                        c->proxy_protocol->src_addr.len)
         != NGX_OK)
     {
-        return NGX_DECLINED;
+        return NGX_OK;
     }
 
     ngx_inet_set_port(addr.sockaddr, c->proxy_protocol->src_port);
 
-    return ngx_stream_realip_set_addr(s, &addr);
+    return ngx_mail_realip_set_addr(s, &addr);
 }
 
 
 static ngx_int_t
-ngx_stream_realip_set_addr(ngx_stream_session_t *s, ngx_addr_t *addr)
+ngx_mail_realip_set_addr(ngx_mail_session_t *s, ngx_addr_t *addr)
 {
-    size_t                    len;
-    u_char                   *p;
-    u_char                    text[NGX_SOCKADDR_STRLEN];
-    ngx_connection_t         *c;
-    ngx_stream_realip_ctx_t  *ctx;
+    size_t             len;
+    u_char            *p;
+    u_char             text[NGX_SOCKADDR_STRLEN];
+    ngx_connection_t  *c;
 
     c = s->connection;
 
-    ctx = ngx_palloc(c->pool, sizeof(ngx_stream_realip_ctx_t));
-    if (ctx == NULL) {
-        return NGX_ERROR;
-    }
-
     len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
                         NGX_SOCKADDR_STRLEN, 0);
     if (len == 0) {
@@ -158,25 +123,19 @@ ngx_stream_realip_set_addr(ngx_stream_se
 
     ngx_memcpy(p, text, len);
 
-    ngx_stream_set_ctx(s, ctx, ngx_stream_realip_module);
-
-    ctx->sockaddr = c->sockaddr;
-    ctx->socklen = c->socklen;
-    ctx->addr_text = c->addr_text;
-
     c->sockaddr = addr->sockaddr;
     c->socklen = addr->socklen;
     c->addr_text.len = len;
     c->addr_text.data = p;
 
-    return NGX_DECLINED;
+    return NGX_OK;
 }
 
 
 static char *
-ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_stream_realip_srv_conf_t *rscf = conf;
+    ngx_mail_realip_srv_conf_t *rscf = conf;
 
     ngx_int_t             rc;
     ngx_str_t            *value;
@@ -277,11 +236,11 @@ ngx_stream_realip_from(ngx_conf_t *cf, n
 
 
 static void *
-ngx_stream_realip_create_srv_conf(ngx_conf_t *cf)
+ngx_mail_realip_create_srv_conf(ngx_conf_t *cf)
 {
-    ngx_stream_realip_srv_conf_t  *conf;
+    ngx_mail_realip_srv_conf_t  *conf;
 
-    conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_realip_srv_conf_t));
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t));
     if (conf == NULL) {
         return NULL;
     }
@@ -297,10 +256,10 @@ ngx_stream_realip_create_srv_conf(ngx_co
 
 
 static char *
-ngx_stream_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
+ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
 {
-    ngx_stream_realip_srv_conf_t *prev = parent;
-    ngx_stream_realip_srv_conf_t *conf = child;
+    ngx_mail_realip_srv_conf_t *prev = parent;
+    ngx_mail_realip_srv_conf_t *conf = child;
 
     if (conf->from == NULL) {
         conf->from = prev->from;
@@ -308,94 +267,3 @@ ngx_stream_realip_merge_srv_conf(ngx_con
 
     return NGX_CONF_OK;
 }
-
-
-static ngx_int_t
-ngx_stream_realip_add_variables(ngx_conf_t *cf)
-{
-    ngx_stream_variable_t  *var, *v;
-
-    for (v = ngx_stream_realip_vars; v->name.len; v++) {
-        var = ngx_stream_add_variable(cf, &v->name, v->flags);
-        if (var == NULL) {
-            return NGX_ERROR;
-        }
-
-        var->get_handler = v->get_handler;
-        var->data = v->data;
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_stream_realip_init(ngx_conf_t *cf)
-{
-    ngx_stream_handler_pt        *h;
-    ngx_stream_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
-
-    h = ngx_array_push(&cmcf->phases[NGX_STREAM_POST_ACCEPT_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_stream_realip_handler;
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_stream_realip_remote_addr_variable(ngx_stream_session_t *s,
-    ngx_stream_variable_value_t *v, uintptr_t data)
-{
-    ngx_str_t                *addr_text;
-    ngx_stream_realip_ctx_t  *ctx;
-
-    ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module);
-
-    addr_text = ctx ? &ctx->addr_text : &s->connection->addr_text;
-
-    v->len = addr_text->len;
-    v->valid = 1;
-    v->no_cacheable = 0;
-    v->not_found = 0;
-    v->data = addr_text->data;
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_stream_realip_remote_port_variable(ngx_stream_session_t *s,
-    ngx_stream_variable_value_t *v, uintptr_t data)
-{
-    ngx_uint_t                port;
-    struct sockaddr          *sa;
-    ngx_stream_realip_ctx_t  *ctx;
-
-    ctx = ngx_stream_get_module_ctx(s, ngx_stream_realip_module);
-
-    sa = ctx ? ctx->sockaddr : s->connection->sockaddr;
-
-    v->len = 0;
-    v->valid = 1;
-    v->no_cacheable = 0;
-    v->not_found = 0;
-
-    v->data = ngx_pnalloc(s->connection->pool, sizeof("65535") - 1);
-    if (v->data == NULL) {
-        return NGX_ERROR;
-    }
-
-    port = ngx_inet_get_port(sa);
-
-    if (port > 0 && port < 65536) {
-        v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
-    }
-
-    return NGX_OK;
-}