[PATCH] proxy protocol proxified client port

Tony Fouchard tony.fouchard at blablacar.com
Tue Apr 5 07:55:53 UTC 2016


Hi guys,

I need to log the user remote port at nginx level when requests are passed
through proxy protocol (legal requirement), but looking at implementation I
saw that all of the work stopped after reading source IP.

In my setup, I have bgp sessions mounted on haproxy instances, but the
haproxy acts at level 4 and only route traffic to different nginx farms
depending of TLS extension value provided by client : it permits to serve
for example both spdy and h2 over alpn.

I have tried to implement what I needed and update the test case.

Regards.



# HG changeset patch
# User Tony Fouchard <tony.fouchard at blablacar.com>
# Date 1459438244 -7200
#      Thu Mar 31 17:30:44 2016 +0200
# Node ID 708e5e9873798be8786aa0234c9712ef94b5a1e2
# Parent  5debefd670bcbc1d4344913bd4754452892f4cb2
Retrieve the proxy protocol client port provided

diff -r 5debefd670bc -r 708e5e987379 proxy_protocol.t
--- a/proxy_protocol.t  Mon Mar 28 19:47:38 2016 +0300
+++ b/proxy_protocol.t  Thu Mar 31 17:30:44 2016 +0200
@@ -26,7 +26,7 @@

 my $t = Test::Nginx->new()->has(qw/http access ipv6 realip/);

-$t->write_file_expand('nginx.conf', <<'EOF')->plan(18);
+$t->write_file_expand('nginx.conf', <<'EOF')->plan(22);

 %%TEST_GLOBALS%%

@@ -38,7 +38,7 @@
 http {
     %%TEST_GLOBALS_HTTP%%

-    log_format pp '$remote_addr $request';
+    log_format pp '$remote_addr $request $proxy_protocol_port';

     server {
         listen       127.0.0.1:8080 proxy_protocol;
@@ -47,6 +47,7 @@
         set_real_ip_from  127.0.0.1/32;
         add_header X-IP $remote_addr;
         add_header X-PP $proxy_protocol_addr;
+        add_header X-PORT $proxy_protocol_port;

         location /pp {
             real_ip_header proxy_protocol;
@@ -81,11 +82,14 @@
 $r = pp_get('/t1', $tcp4);
 like($r, qr/SEE-THIS/, 'tcp4 request');
 like($r, qr/X-PP: 192.0.2.1/, 'tcp4 proxy');
+like($r, qr/X-PORT: 1234/, 'tcp4 proxy port');
 unlike($r, qr/X-IP: 192.0.2.1/, 'tcp4 client');

 $r = pp_get('/t1', $tcp6);
 like($r, qr/SEE-THIS/, 'tcp6 request');
+like($r, qr/X-PORT: 1234/, 'tcp6 proxy port');
 like($r, qr/X-PP: 2001:DB8::1/i, 'tcp6 proxy');
+
 unlike($r, qr/X-IP: 2001:DB8::1/i, 'tcp6 client');

 like(pp_get('/t1', $unk1), qr/SEE-THIS/, 'unknown request 1');
@@ -96,11 +100,13 @@
 $r = pp_get('/pp', $tcp4);
 like($r, qr/SEE-THIS/, 'tcp4 request realip');
 like($r, qr/X-PP: 192.0.2.1/, 'tcp4 proxy realip');
+like($r, qr/X-PORT: 1234/, 'tcp4 proxy port realip');
 like($r, qr/X-IP: 192.0.2.1/, 'tcp4 client realip');

 $r = pp_get('/pp', $tcp6);
 like($r, qr/SEE-THIS/, 'tcp6 request realip');
 like($r, qr/X-PP: 2001:DB8::1/i, 'tcp6 proxy realip');
+like($r, qr/X-PORT: 1234/, 'tcp6 proxy port realip');
 like($r, qr/X-IP: 2001:DB8::1/i, 'tcp6 client realip');

 # access
@@ -125,8 +131,8 @@
        close LOG;
 }

-like($log, qr!^192\.0\.2\.1 GET /pp_4!m, 'tcp4 access log');
-like($log, qr!^2001:DB8::1 GET /pp_6!mi, 'tcp6 access log');
+like($log, qr!^192\.0\.2\.1 GET /pp_4 HTTP/1.0 1234!m, 'tcp4 access log');
+like($log, qr!^2001:DB8::1 GET /pp_6 HTTP/1.0 1234!mi, 'tcp6 access log');

 ###############################################################################




# HG changeset patch
# User Tony Fouchard <tony.fouchard at blablacar.com>
# Date 1459438562 -7200
#      Thu Mar 31 17:36:02 2016 +0200
# Branch feat-proxy-protocol-port
# Node ID 6cd4f889089344db865cd07400c15e4d5966aa01
# Parent  2b7dacb381ed1c4583aa048f1b22bdc141259407
Retrieve the proxy protocol client port provided

diff -r 2b7dacb381ed -r 6cd4f8890893 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h Thu Mar 31 02:34:04 2016 +0300
+++ b/src/core/ngx_connection.h Thu Mar 31 17:36:02 2016 +0200
@@ -149,6 +149,7 @@
     ngx_str_t           addr_text;

     ngx_str_t           proxy_protocol_addr;
+    ngx_str_t           proxy_protocol_port;

 #if (NGX_SSL)
     ngx_ssl_connection_t  *ssl;
diff -r 2b7dacb381ed -r 6cd4f8890893 src/core/ngx_proxy_protocol.c
--- a/src/core/ngx_proxy_protocol.c     Thu Mar 31 02:34:04 2016 +0300
+++ b/src/core/ngx_proxy_protocol.c     Thu Mar 31 17:36:02 2016 +0200
@@ -12,8 +12,8 @@
 u_char *
 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
 {
-    size_t  len;
-    u_char  ch, *p, *addr;
+    size_t  len, plen;
+    u_char  ch, *p, *addr, *paddr;

     p = buf;
     len = last - buf;
@@ -74,6 +74,57 @@
     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;
+        }
+
+        if (ch != ':' && ch != '.'
+            && (ch < 'a' || ch > 'f')
+            && (ch < 'A' || ch > 'F')
+            && (ch < '0' || ch > '9'))
+        {
+            goto invalid;
+        }
+    }
+
+    paddr = p;
+
+    for ( ;; ) {
+        if (p == last) {
+            goto invalid;
+        }
+
+        ch = *p++;
+
+        if (ch == ' ') {
+            break;
+        }
+
+        if (ch < '0' || ch > '9') {
+            goto invalid;
+        }
+    }
+
+    plen = p - paddr - 1;
+    c->proxy_protocol_port.data = ngx_pnalloc(c->pool, plen);
+
+    if (c->proxy_protocol_port.data == NULL) {
+        return NULL;
+    }
+
+    ngx_memcpy(c->proxy_protocol_port.data, paddr, plen);
+    c->proxy_protocol_port.len = plen;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+                   "PROXY protocol port: \"%V\"", &c->proxy_protocol_port);
+
 skip:

     for ( /* void */ ; p < last - 1; p++) {
diff -r 2b7dacb381ed -r 6cd4f8890893 src/http/ngx_http_variables.c
--- a/src/http/ngx_http_variables.c     Thu Mar 31 02:34:04 2016 +0300
+++ b/src/http/ngx_http_variables.c     Thu Mar 31 17:36:02 2016 +0200
@@ -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 },
@@ -1250,6 +1255,20 @@


 static ngx_int_t
+ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    v->len = r->connection->proxy_protocol_port.len;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+    v->data = r->connection->proxy_protocol_port.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)
 {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20160405/68ed0e8d/attachment.html>


More information about the nginx-devel mailing list