]> git.kaiwu.me - nginx.git/commitdiff
Realip: port support in X-Real-IP and X-Forwarded-For.
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 23 May 2016 15:44:23 +0000 (18:44 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 23 May 2016 15:44:23 +0000 (18:44 +0300)
Now, the module extracts optional port which may accompany an
IP address.  This custom extension is introduced, among other
things, in order to facilitate logging of original client ports.
Addresses with ports are expected to be in the RFC 3986 format,
that is, with IPv6 addresses in square brackets.  E.g.,
"X-Real-IP: [2001:0db8::1]:12345" sets client port ($remote_port)
to 12345.

src/core/ngx_inet.c
src/core/ngx_inet.h
src/http/ngx_http_core_module.c

index 12bf9f81ac93adc40ef28ccc27d41d5e9435770f..b5c57b7a45a5c04a3d2d7ec0db11f137e2578308 100644 (file)
@@ -525,6 +525,85 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
 }
 
 
+ngx_int_t
+ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
+    size_t len)
+{
+    u_char               *p, *last;
+    size_t                plen;
+    ngx_int_t             rc, port;
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6  *sin6;
+#endif
+
+    rc = ngx_parse_addr(pool, addr, text, len);
+
+    if (rc != NGX_DECLINED) {
+        return rc;
+    }
+
+    last = text + len;
+
+#if (NGX_HAVE_INET6)
+    if (len && text[0] == '[') {
+
+        p = ngx_strlchr(text, last, ']');
+
+        if (p == NULL || p == last - 1 || *++p != ':') {
+            return NGX_DECLINED;
+        }
+
+        text++;
+        len -= 2;
+
+    } else
+#endif
+
+    {
+        p = ngx_strlchr(text, last, ':');
+
+        if (p == NULL) {
+            return NGX_DECLINED;
+        }
+    }
+
+    p++;
+    plen = last - p;
+
+    port = ngx_atoi(p, plen);
+
+    if (port < 1 || port > 65535) {
+        return NGX_DECLINED;
+    }
+
+    len -= plen + 1;
+
+    rc = ngx_parse_addr(pool, addr, text, len);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
+    switch (addr->sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) addr->sockaddr;
+        sin6->sin6_port = htons(port);
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) addr->sockaddr;
+        sin->sin_port = htons(port);
+        break;
+    }
+
+    return NGX_OK;
+}
+
+
 ngx_int_t
 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
 {
index 422aabec4ece11e533fb959e3631c09e38b0965a..531d2640c31ff141836c4be784e2b3e66e8d1be1 100644 (file)
@@ -115,6 +115,8 @@ 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,
     size_t len);
+ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr,
+    u_char *text, size_t len);
 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
index f22448464673c39c0b00380c1156d6a222097719..76917bbb01bae44900dd8746ebadda3d41b10db6 100644 (file)
@@ -2910,7 +2910,9 @@ ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
             }
         }
 
-        if (ngx_parse_addr(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
+        if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff))
+            != NGX_OK)
+        {
             return NGX_DECLINED;
         }