]> git.kaiwu.me - nginx.git/commitdiff
Stream: PROXY protocol v2 support to backends
authorSergey Kandaurov <pluknet@nginx.com>
Mon, 10 Aug 2026 16:53:44 +0000 (20:53 +0400)
committerSergey Kandaurov <s.kandaurov@f5.com>
Tue, 11 Aug 2026 19:39:53 +0000 (23:39 +0400)
Version 1 remains the default.  This may be changed with the
"proxy_protocol v2;" directive.

src/stream/ngx_stream_proxy_module.c
src/stream/ngx_stream_upstream.h

index 38c2b248950d9c7547b883f8a1dbeba833b61827..3f896a116c443aeb5da2141b07f7913e4ce9ea9b 100644 (file)
@@ -30,7 +30,7 @@ typedef struct {
     ngx_uint_t                       responses;
     ngx_uint_t                       next_upstream_tries;
     ngx_flag_t                       next_upstream;
-    ngx_flag_t                       proxy_protocol;
+    ngx_uint_t                       proxy_protocol;
     ngx_flag_t                       half_close;
     ngx_stream_upstream_local_t     *local;
     ngx_flag_t                       socket_keepalive;
@@ -145,6 +145,14 @@ static ngx_conf_deprecated_t  ngx_conf_deprecated_proxy_upstream_buffer = {
 };
 
 
+static ngx_conf_enum_t  ngx_stream_proxy_protocol_versions[] = {
+    { ngx_string("off"), 0 },
+    { ngx_string("on"), 1 },
+    { ngx_string("v2"), 2 },
+    { ngx_null_string, 0 }
+};
+
+
 static ngx_command_t  ngx_stream_proxy_commands[] = {
 
     { ngx_string("proxy_pass"),
@@ -267,11 +275,11 @@ static ngx_command_t  ngx_stream_proxy_commands[] = {
       NULL },
 
     { ngx_string("proxy_protocol"),
-      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
+      NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
       NGX_STREAM_SRV_CONF_OFFSET,
       offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
-      NULL },
+      &ngx_stream_proxy_protocol_versions },
 
     { ngx_string("proxy_half_close"),
       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
@@ -847,12 +855,14 @@ static void
 ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
 {
     u_char                       *p;
+    size_t                        size;
     ngx_chain_t                  *cl;
     ngx_connection_t             *c, *pc;
     ngx_log_handler_pt            handler;
     ngx_stream_upstream_t        *u;
     ngx_stream_core_srv_conf_t   *cscf;
     ngx_stream_proxy_srv_conf_t  *pscf;
+    static u_char                 buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
 
     u = s->upstream;
     pc = u->peer.connection;
@@ -956,28 +966,37 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
                        "stream proxy add PROXY protocol header");
 
-        cl = ngx_chain_get_free_buf(c->pool, &u->free);
-        if (cl == NULL) {
+        if (u->proxy_protocol == 2) {
+            p = ngx_proxy_protocol_v2_write(c, buf, buf + sizeof(buf), NULL);
+
+        } else {
+            p = ngx_proxy_protocol_write(c, buf, buf + sizeof(buf));
+        }
+
+        if (p == NULL) {
             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
             return;
         }
 
-        p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
+        size = p - buf;
+
+        p = ngx_pnalloc(c->pool, size);
         if (p == NULL) {
             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
             return;
         }
 
-        cl->buf->pos = p;
+        ngx_memcpy(p, buf, size);
 
-        p = ngx_proxy_protocol_write(c, p,
-                                     p + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
-        if (p == NULL) {
+        cl = ngx_chain_get_free_buf(c->pool, &u->free);
+        if (cl == NULL) {
             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
             return;
         }
 
-        cl->buf->last = p;
+        cl->buf->pos = p;
+        cl->buf->last = p + size;
+
         cl->buf->temporary = 1;
         cl->buf->flush = 0;
         cl->buf->last_buf = 0;
@@ -1011,26 +1030,32 @@ static ngx_int_t
 ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
 {
     u_char                       *p;
-    ssize_t                       n, size;
+    size_t                        size;
+    ssize_t                       n;
     ngx_connection_t             *c, *pc;
     ngx_stream_upstream_t        *u;
     ngx_stream_proxy_srv_conf_t  *pscf;
-    u_char                        buf[NGX_PROXY_PROTOCOL_V1_MAX_HEADER];
+    static u_char                 buf[NGX_PROXY_PROTOCOL_MAX_HEADER];
 
     c = s->connection;
 
     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
                    "stream proxy send PROXY protocol header");
 
-    p = ngx_proxy_protocol_write(c, buf,
-                                 buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
+    u = s->upstream;
+
+    if (u->proxy_protocol == 2) {
+        p = ngx_proxy_protocol_v2_write(c, buf, buf + sizeof(buf), NULL);
+
+    } else {
+        p = ngx_proxy_protocol_write(c, buf, buf + sizeof(buf));
+    }
+
     if (p == NULL) {
         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
         return NGX_ERROR;
     }
 
-    u = s->upstream;
-
     pc = u->peer.connection;
 
     size = p - buf;
@@ -1057,7 +1082,7 @@ ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
         return NGX_ERROR;
     }
 
-    if (n != size) {
+    if (n != (ssize_t) size) {
 
         /*
          * PROXY protocol specification:
@@ -2402,7 +2427,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
     conf->responses = NGX_CONF_UNSET_UINT;
     conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
     conf->next_upstream = NGX_CONF_UNSET;
-    conf->proxy_protocol = NGX_CONF_UNSET;
+    conf->proxy_protocol = NGX_CONF_UNSET_UINT;
     conf->local = NGX_CONF_UNSET_PTR;
     conf->socket_keepalive = NGX_CONF_UNSET;
     conf->socket_rcvbuf = NGX_CONF_UNSET_SIZE;
@@ -2461,7 +2486,7 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
 
     ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1);
 
-    ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);
+    ngx_conf_merge_uint_value(conf->proxy_protocol, prev->proxy_protocol, 0);
 
     ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);
 
index 0e6aad62367f27d9b53e7f56515ecc8a008d96d4..bb0ca4fc342b4d198634e1ba6577d9a7b2405e2f 100644 (file)
@@ -150,7 +150,7 @@ typedef struct {
     ngx_stream_upstream_resolved_t    *resolved;
     ngx_stream_upstream_state_t       *state;
     unsigned                           connected:1;
-    unsigned                           proxy_protocol:1;
+    unsigned                           proxy_protocol:2;
     unsigned                           half_closed:1;
 } ngx_stream_upstream_t;