diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/ngx_connection.h | 2 | ||||
-rw-r--r-- | src/core/ngx_core.h | 1 | ||||
-rw-r--r-- | src/core/ngx_proxy_protocol.c | 91 | ||||
-rw-r--r-- | src/core/ngx_proxy_protocol.h | 23 |
4 files changed, 117 insertions, 0 deletions
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index d9bc60a77..ed14e6023 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -139,6 +139,8 @@ struct ngx_connection_s { socklen_t socklen; ngx_str_t addr_text; + ngx_str_t proxy_protocol_addr; + #if (NGX_SSL) ngx_ssl_connection_t *ssl; #endif diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index dfcf2d56c..a2d417e8d 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -77,6 +77,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #include <ngx_open_file_cache.h> #include <ngx_os.h> #include <ngx_connection.h> +#include <ngx_proxy_protocol.h> #define LF (u_char) 10 diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c new file mode 100644 index 000000000..59ef010fc --- /dev/null +++ b/src/core/ngx_proxy_protocol.c @@ -0,0 +1,91 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include <ngx_config.h> +#include <ngx_core.h> + + +u_char * +ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last) +{ + size_t len; + u_char ch, *p, *addr; + + p = buf; + len = last - buf; + + if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) { + goto invalid; + } + + p += 6; + len -= 6; + + if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) { + ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol unknown protocol"); + p += 7; + goto skip; + } + + if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0 + || (p[3] != '4' && p[3] != '6') || p[4] != ' ') + { + goto invalid; + } + + p += 5; + addr = p; + + for ( ;; ) { + if (p == last) { + goto invalid; + } + + ch = *p++; + + if (ch == ' ') { + break; + } + + if (ch != ':' && ch != '.' + && (ch < 'a' || ch > 'f') + && (ch < 'A' || ch > 'F') + && (ch < '0' || ch > '9')) + { + goto invalid; + } + } + + len = p - addr - 1; + c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len); + + if (c->proxy_protocol_addr.data == NULL) { + return NULL; + } + + ngx_memcpy(c->proxy_protocol_addr.data, addr, len); + c->proxy_protocol_addr.len = len; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr); + +skip: + + for ( /* void */ ; p < last - 1; p++) { + if (p[0] == CR && p[1] == LF) { + return p + 2; + } + } + +invalid: + + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "broken header: \"%*s\"", (size_t) (last - buf), buf); + + return NULL; +} diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h new file mode 100644 index 000000000..4f3912512 --- /dev/null +++ b/src/core/ngx_proxy_protocol.h @@ -0,0 +1,23 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_ +#define _NGX_PROXY_PROTOCOL_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> + + +#define NGX_PROXY_PROTOCOL_MAX_HEADER 107 + + +u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, + u_char *last); + + +#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */ |