[PATCH]add proxy_protocol_port variable for rfc6302
junpei yoshino
junpei.yoshino at gmail.com
Tue Apr 5 00:50:59 UTC 2016
Hello!
Thank you for your comment.
I rewrote patch in way 3.
Best Regards,
Junpei Yoshino
# HG changeset patch
# User Junpei Yoshino <junpei.yoshino at gmail.com>
# Date 1459816952 -32400
# Tue Apr 05 09:42:32 2016 +0900
# Node ID cdaf19070ed1687a4f942936a0e7339355b98bfa
# Parent 8426275a13fdfac6dfe6955b7b3e999430eb373d
Http: add proxy_protocol_port variable for rfc6302 & support in realip module
real_port_header is not needed if "real_ip_header proxy_protocol" configured.
replace remote_port with request header if you set real_port_header.
diff -r 8426275a13fd -r cdaf19070ed1 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h Fri Apr 01 16:38:31 2016 +0300
+++ b/src/core/ngx_connection.h Tue Apr 05 09:42:32 2016 +0900
@@ -147,8 +147,10 @@
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t addr_text;
+ ngx_uint_t port;
ngx_str_t proxy_protocol_addr;
+ ngx_int_t proxy_protocol_port;
#if (NGX_SSL)
ngx_ssl_connection_t *ssl;
diff -r 8426275a13fd -r cdaf19070ed1 src/core/ngx_inet.c
--- a/src/core/ngx_inet.c Fri Apr 01 16:38:31 2016 +0300
+++ b/src/core/ngx_inet.c Tue Apr 05 09:42:32 2016 +0900
@@ -256,6 +256,38 @@
}
+ngx_uint_t
+ngx_sock_get_port(struct sockaddr *sa, socklen_t socklen)
+{
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (sa->sa_family) {
+
+ case AF_INET:
+ sin = (struct sockaddr_in *) sa;
+ return ntohs(sin->sin_port);
+ break;
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+ sin6 = (struct sockaddr_in6 *) sa;
+
+ return ntohs(sin6->sin6_port);
+
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+}
+
+
size_t
ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
{
diff -r 8426275a13fd -r cdaf19070ed1 src/core/ngx_inet.h
--- a/src/core/ngx_inet.h Fri Apr 01 16:38:31 2016 +0300
+++ b/src/core/ngx_inet.h Tue Apr 05 09:42:32 2016 +0900
@@ -109,6 +109,7 @@
#endif
size_t ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text,
size_t len, ngx_uint_t port);
+ngx_uint_t ngx_sock_get_port(struct sockaddr *sa, socklen_t socklen);
size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
diff -r 8426275a13fd -r cdaf19070ed1 src/core/ngx_proxy_protocol.c
--- a/src/core/ngx_proxy_protocol.c Fri Apr 01 16:38:31 2016 +0300
+++ b/src/core/ngx_proxy_protocol.c Tue Apr 05 09:42:32 2016 +0900
@@ -13,7 +13,7 @@
ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
{
size_t len;
- u_char ch, *p, *addr;
+ u_char ch, *p, *addr, *port;
p = buf;
len = last - buf;
@@ -71,8 +71,40 @@
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);
+ for ( ;; ) {
+ if (p == last) {
+ goto invalid;
+ }
+
+ ch = *p++;
+
+ if (ch == ' ') {
+ break;
+ }
+ }
+ port = p;
+ for ( ;; ) {
+ if (p == last) {
+ goto invalid;
+ }
+
+ ch = *p++;
+
+ if (ch == ' ') {
+ break;
+ }
+
+ if (ch < '0' || ch > '9')
+ {
+ goto invalid;
+ }
+ }
+ len = p - port - 1;
+ c->proxy_protocol_port = ngx_atoi(port,len);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "PROXY protocol address: \"%V\", PROXY protocol
port: \"%d\"",
+ &c->proxy_protocol_addr, c->proxy_protocol_port);
skip:
diff -r 8426275a13fd -r cdaf19070ed1 src/event/ngx_event_accept.c
--- a/src/event/ngx_event_accept.c Fri Apr 01 16:38:31 2016 +0300
+++ b/src/event/ngx_event_accept.c Tue Apr 05 09:42:32 2016 +0900
@@ -278,6 +278,7 @@
ngx_close_accepted_connection(c);
return;
}
+ c->port = ngx_sock_get_port(c->sockaddr, c->socklen);
}
#if (NGX_DEBUG)
diff -r 8426275a13fd -r cdaf19070ed1 src/http/modules/ngx_http_realip_module.c
--- a/src/http/modules/ngx_http_realip_module.c Fri Apr 01 16:38:31 2016 +0300
+++ b/src/http/modules/ngx_http_realip_module.c Tue Apr 05 09:42:32 2016 +0900
@@ -15,6 +15,8 @@
#define NGX_HTTP_REALIP_HEADER 2
#define NGX_HTTP_REALIP_PROXY 3
+#define NGX_HTTP_REALPORT_PROXY 1
+#define NGX_HTTP_REALPORT_HEADER 2
typedef struct {
ngx_array_t *from; /* array of ngx_cidr_t */
@@ -22,6 +24,9 @@
ngx_uint_t hash;
ngx_str_t header;
ngx_flag_t recursive;
+ ngx_uint_t porttype;
+ ngx_uint_t porthash;
+ ngx_str_t portheader;
} ngx_http_realip_loc_conf_t;
@@ -30,16 +35,18 @@
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t addr_text;
+ ngx_uint_t port;
} ngx_http_realip_ctx_t;
static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
- ngx_addr_t *addr);
+ ngx_addr_t *addr, ngx_uint_t port);
static void ngx_http_realip_cleanup(void *data);
static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_http_real_port(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -49,6 +56,8 @@
static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_realip_remote_port_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_command_t ngx_http_realip_commands[] = {
@@ -67,6 +76,13 @@
0,
NULL },
+ { ngx_string("real_port_header"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_real_port,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("real_ip_recursive"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -115,6 +131,9 @@
{ ngx_string("realip_remote_addr"), NULL,
ngx_http_realip_remote_addr_variable, 0, 0, 0 },
+ { ngx_string("realip_remote_port"), NULL,
+ ngx_http_realip_remote_port_variable, 0, 0, 0 },
+
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -127,6 +146,7 @@
ngx_str_t *value;
ngx_uint_t i, hash;
ngx_addr_t addr;
+ ngx_uint_t port;
ngx_array_t *xfwd;
ngx_list_part_t *part;
ngx_table_elt_t *header;
@@ -146,6 +166,8 @@
return NGX_DECLINED;
}
+ port = r->connection->port;
+
switch (rlcf->type) {
case NGX_HTTP_REALIP_XREALIP:
@@ -172,8 +194,8 @@
break;
case NGX_HTTP_REALIP_PROXY:
-
value = &r->connection->proxy_protocol_addr;
+ port = r->connection->proxy_protocol_port;
if (value->len == 0) {
return NGX_DECLINED;
@@ -211,14 +233,52 @@
value = &header[i].value;
xfwd = NULL;
- goto found;
+ goto portphase;
}
}
return NGX_DECLINED;
}
-found:
+portphase:
+
+
+ switch (rlcf->porttype) {
+
+ case NGX_CONF_UNSET_UINT:
+ break;
+
+ default: /* NGX_HTTP_REALPORT_HEADER */
+
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ hash = rlcf->porthash;
+ len = rlcf->portheader.len;
+ p = rlcf->portheader.data;
+
+ for (i = 0; /* void */ ; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ if (hash == header[i].hash
+ && len == header[i].key.len
+ && ngx_strncmp(p, header[i].lowcase_key, len) == 0)
+ {
+ port=ngx_atoi(header[i].value.data, header[i].value.len);
+
+ break;
+ }
+ }
+ }
c = r->connection;
@@ -230,7 +290,7 @@
rlcf->recursive)
!= NGX_DECLINED)
{
- return ngx_http_realip_set_addr(r, &addr);
+ return ngx_http_realip_set_addr(r, &addr, port);
}
return NGX_DECLINED;
@@ -238,7 +298,7 @@
static ngx_int_t
-ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
+ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr,
ngx_uint_t port)
{
size_t len;
u_char *p;
@@ -276,11 +336,13 @@
ctx->sockaddr = c->sockaddr;
ctx->socklen = c->socklen;
ctx->addr_text = c->addr_text;
+ ctx->port = c->port;
c->sockaddr = addr->sockaddr;
c->socklen = addr->socklen;
c->addr_text.len = len;
c->addr_text.data = p;
+ c->port = port;
return NGX_DECLINED;
}
@@ -298,6 +360,7 @@
c->sockaddr = ctx->sockaddr;
c->socklen = ctx->socklen;
c->addr_text = ctx->addr_text;
+ c->port = ctx->port;
}
@@ -383,6 +446,28 @@
}
+static char *
+ngx_http_real_port(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_realip_loc_conf_t *rlcf = conf;
+
+ ngx_str_t *value;
+
+ value = cf->args->elts;
+
+ if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) {
+ rlcf->porttype = NGX_HTTP_REALPORT_PROXY;
+ return NGX_CONF_OK;
+ }
+
+ rlcf->porttype = NGX_HTTP_REALPORT_HEADER;
+ rlcf->porthash = ngx_hash_strlow(value[1].data, value[1].data,
value[1].len);
+ rlcf->portheader = value[1];
+
+ return NGX_CONF_OK;
+}
+
+
static void *
ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
{
@@ -399,9 +484,12 @@
* conf->from = NULL;
* conf->hash = 0;
* conf->header = { 0, NULL };
+ * conf->porthash = 0
+ * conf->portheader = { 0, NULL };
*/
conf->type = NGX_CONF_UNSET_UINT;
+ conf->porttype = NGX_CONF_UNSET_UINT;
conf->recursive = NGX_CONF_UNSET;
return conf;
@@ -510,3 +598,50 @@
return NGX_OK;
}
+
+
+static ngx_int_t
+ngx_http_realip_remote_port_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_uint_t port;
+ ngx_pool_cleanup_t *cln;
+ ngx_http_realip_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
+
+ if (ctx == NULL && (r->internal || r->filter_finalize)) {
+
+ /*
+ * if module context was reset, the original port
+ * can still be found in the cleanup handler
+ */
+
+ for (cln = r->pool->cleanup; cln; cln = cln->next) {
+ if (cln->handler == ngx_http_realip_cleanup) {
+ ctx = cln->data;
+ break;
+ }
+ }
+ }
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "piyo %ui %ui",ctx->port,r->connection->port);
+
+
+ port = ctx ? ctx->port : r->connection->port;
+
+ v->len = 0;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
+
+ if (v->data == NULL) {
+ return NGX_ERROR;
+ }
+ if (port > 0 && port < 65536) {
+ v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
+ }
+
+ return NGX_OK;
+}
diff -r 8426275a13fd -r cdaf19070ed1 src/http/ngx_http_variables.c
--- a/src/http/ngx_http_variables.c Fri Apr 01 16:38:31 2016 +0300
+++ b/src/http/ngx_http_variables.c Tue Apr 05 09:42:32 2016 +0900
@@ -58,6 +58,8 @@
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
@@ -192,6 +194,9 @@
{ ngx_string("proxy_protocol_addr"), NULL,
ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
+ { ngx_string("proxy_protocol_port"), NULL,
+ ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
+
{ ngx_string("server_addr"), NULL, ngx_http_variable_server_addr,
0, 0, 0 },
{ ngx_string("server_port"), NULL, ngx_http_variable_server_port,
0, 0, 0 },
@@ -1190,12 +1195,7 @@
ngx_http_variable_remote_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- ngx_uint_t port;
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
-#endif
-
+ ngx_uint_t port;
v->len = 0;
v->valid = 1;
v->no_cacheable = 0;
@@ -1205,27 +1205,8 @@
if (v->data == NULL) {
return NGX_ERROR;
}
-
- switch (r->connection->sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
- port = ntohs(sin6->sin6_port);
- break;
-#endif
-
-#if (NGX_HAVE_UNIX_DOMAIN)
- case AF_UNIX:
- port = 0;
- break;
-#endif
-
- default: /* AF_INET */
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- port = ntohs(sin->sin_port);
- break;
- }
+
+ port = r->connection->port;
if (port > 0 && port < 65536) {
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
@@ -1250,6 +1231,29 @@
static ngx_int_t
+ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_int_t port = r->connection->proxy_protocol_port;
+
+ v->len = 0;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
+
+ if (v->data == NULL) {
+ return NGX_ERROR;
+ }
+ if (port > 0 && port < 65536) {
+ v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
On Tue, Apr 5, 2016 at 2:56 AM, Maxim Dounin <mdounin at mdounin.ru> wrote:
> Hello!
>
> On Tue, Apr 05, 2016 at 02:12:21AM +0900, junpei yoshino wrote:
>
>> which is better way ?
>> 1.
>> "real_ip_from Forwarded" replace remote_addr and remote_port.
>> And proxy_protocol also replace remote_addr and remote_port, too.
>
> While support for Forwarded is a good thing to have, it looks like
> a separate and big work, so I wouldn't recommend trying to do this
> now.
>
>> 2.
>> "real_port_from Forwarded" replace port only.
>> ip and port is independent.
>> Also proxy protocol must configure real_ip_from and real_port_from.
>
> This approach looks wrong. If we know client port it should be
> used. But see above about Forwarded.
>
>> 3.
>> At first, not care Forwarded header.
>> delete code related x-forwarded-port.
>> support only custom http header including port number.
>
> This option looks most appropriate for now.
>
> (Assuming this also includes "proxy_protocol also replace
> remote_addr and remote_port" as in 1.)
>
> --
> Maxim Dounin
> http://nginx.org/
>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
--
junpei.yoshino at gmail.com
More information about the nginx-devel
mailing list