diff src/core/ngx_proxy_protocol.c @ 5605:3a72b1805c52

Added server-side support for PROXY protocol v1 (ticket #355). Client address specified in the PROXY protocol header is now saved in the $proxy_protocol_addr variable and can be used in the realip module. This is currently not implemented for mail.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 17 Mar 2014 17:41:24 +0400
parents
children fa663739e115
line wrap: on
line diff
new file mode 100644
--- /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;
+}