<div dir="ltr"><div dir="ltr"><div>diff -r 82e174e47663 src/core/ngx_proxy_protocol.c</div><div>--- a/src/core/ngx_proxy_protocol.c<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Thu Apr 08 00:16:30 2021 +0300</div><div>+++ b/src/core/ngx_proxy_protocol.c<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Fri Apr 09 16:10:29 2021 +0300</div><div>@@ -13,6 +13,34 @@</div><div> #define NGX_PROXY_PROTOCOL_AF_INET6         2</div><div> </div><div> </div><div>+#define NGX_PROXY_PROTOCOL_V2_SIG              "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"</div><div>+#define NGX_PROXY_PROTOCOL_V2_SIG_LEN          12</div><div>+#define NGX_PROXY_PROTOCOL_V2_HDR_LEN          16</div><div>+#define NGX_PROXY_PROTOCOL_V2_HDR_LEN_INET \</div><div>+                (NGX_PROXY_PROTOCOL_V2_HDR_LEN + (4 + 4 + 2 + 2))</div><div>+#define NGX_PROXY_PROTOCOL_V2_HDR_LEN_INET6 \</div><div>+                (NGX_PROXY_PROTOCOL_V2_HDR_LEN + (16 + 16 + 2 + 2))</div><div>+</div><div>+#define NGX_PROXY_PROTOCOL_V2_CMD_PROXY        (0x20 | 0x01)</div><div>+</div><div>+#define NGX_PROXY_PROTOCOL_V2_TRANS_STREAM     0x01</div><div>+</div><div>+#define NGX_PROXY_PROTOCOL_V2_FAM_UNSPEC       0x00</div><div>+#define NGX_PROXY_PROTOCOL_V2_FAM_INET         0x10</div><div>+#define NGX_PROXY_PROTOCOL_V2_FAM_INET6        0x20</div><div>+</div><div>+#define NGX_PROXY_PROTOCOL_V2_TYPE_ALPN             0x01</div><div>+#define NGX_PROXY_PROTOCOL_V2_TYPE_SSL              0x20</div><div>+#define NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_VERSION   0x21</div><div>+#define NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_CIPHER    0x23</div><div>+#define NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_SIG_ALG   0x24</div><div>+#define NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_KEY_ALG   0x25</div><div>+</div><div>+#define NGX_PROXY_PROTOCOL_V2_CLIENT_SSL            0x01</div><div>+#define NGX_PROXY_PROTOCOL_V2_CLIENT_CERT_CONN      0x02</div><div>+#define NGX_PROXY_PROTOCOL_V2_CLIENT_CERT_SESS      0x04</div><div>+</div><div>+</div><div> #define ngx_proxy_protocol_parse_uint16(p)  ((p)[0] << 8 | (p)[1])</div><div> </div><div> </div><div>@@ -40,12 +68,68 @@</div><div> } ngx_proxy_protocol_inet6_addrs_t;</div><div> </div><div> </div><div>+typedef union {</div><div>+    struct {</div><div>+        uint32_t          src_addr;</div><div>+        uint32_t          dst_addr;</div><div>+        uint16_t          src_port;</div><div>+        uint16_t          dst_port;</div><div>+    } ip4;</div><div>+    struct {</div><div>+        uint8_t           src_addr[16];</div><div>+        uint8_t           dst_addr[16];</div><div>+        uint16_t          src_port;</div><div>+        uint16_t          dst_port;</div><div>+    } ip6;</div><div>+} ngx_proxy_protocol_addrs_t;</div><div>+</div><div>+</div><div>+typedef struct {</div><div>+    u_char                        signature[12];</div><div>+    uint8_t                       version_command;</div><div>+    uint8_t                       family_transport;</div><div>+    uint16_t                      len;</div><div>+    ngx_proxy_protocol_addrs_t    addr;</div><div>+} ngx_proxy_protocol_v2_header_t;</div><div>+</div><div>+</div><div>+struct ngx_tlv_s {</div><div>+    uint8_t     type;</div><div>+    uint8_t     length_hi;</div><div>+    uint8_t     length_lo;</div><div>+    uint8_t     value[0];</div><div>+} __attribute__((packed));</div><div>+</div><div>+typedef struct ngx_tlv_s ngx_tlv_t;</div><div>+</div><div>+</div><div>+#if (NGX_STREAM_SSL)</div><div>+struct ngx_tlv_ssl_s {</div><div>+    ngx_tlv_t   tlv;</div><div>+    uint8_t     client;</div><div>+    uint32_t    verify;</div><div>+    uint8_t     sub_tlv[];</div><div>+} __attribute__((packed));</div><div>+</div><div>+typedef struct ngx_tlv_ssl_s ngx_tlv_ssl_t;</div><div>+#endif</div><div>+</div><div>+</div><div> static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,</div><div>     u_char *last, ngx_str_t *addr);</div><div> static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,</div><div>     in_port_t *port, u_char sep);</div><div> static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,</div><div>     u_char *last);</div><div>+static u_char *ngx_proxy_protocol_v2_write(ngx_connection_t *c, u_char *buf,</div><div>+    u_char *last);</div><div>+#if (NGX_HAVE_INET6)</div><div>+static void ngx_v4tov6(struct in6_addr *sin6_addr, struct sockaddr *addr);</div><div>+#endif</div><div>+#if (NGX_STREAM_SSL)</div><div>+static u_char *ngx_copy_tlv(u_char *pos, u_char *last, u_char type,</div><div>+        u_char *value, uint16_t value_len);</div><div>+#endif</div><div> </div><div> </div><div> u_char *</div><div>@@ -223,7 +307,8 @@</div><div> </div><div> </div><div> u_char *</div><div>-ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)</div><div>+ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last,</div><div>+        ngx_uint_t pp_version)</div><div> {</div><div>     ngx_uint_t  port, lport;</div><div> </div><div>@@ -235,6 +320,10 @@</div><div>         return NULL;</div><div>     }</div><div> </div><div>+    if (pp_version == 2) {</div><div>+        return ngx_proxy_protocol_v2_write(c, buf, last);</div><div>+    }</div><div>+</div><div>     switch (c->sockaddr->sa_family) {</div><div> </div><div>     case AF_INET:</div><div>@@ -420,3 +509,344 @@</div><div> </div><div>     return end;</div><div> }</div><div>+</div><div>+</div><div>+static u_char *</div><div>+ngx_proxy_protocol_v2_write(ngx_connection_t *c, u_char *buf, u_char *last)</div><div>+{</div><div>+    struct sockaddr                 *src, *dst;</div><div>+    ngx_proxy_protocol_v2_header_t  *header;</div><div>+#if (NGX_HAVE_INET6)</div><div>+    struct in6_addr                  v6_tmp;</div><div>+    ngx_int_t                        v6_used;</div><div>+#endif</div><div>+#if (NGX_STREAM_SSL)</div><div>+    ngx_tlv_ssl_t                   *tlv;</div><div>+    u_char                          *value, *pos;</div><div>+    u_char                           kbuf[100];</div><div>+    const unsigned char             *data;</div><div>+    unsigned int                     data_len;</div><div>+</div><div>+    X509                            *crt;</div><div>+    EVP_PKEY                        *key;</div><div>+    const ASN1_OBJECT               *algorithm;</div><div>+    const char                      *s;</div><div>+</div><div>+    long                             rc;</div><div>+    size_t                           tlv_len;</div><div>+#endif</div><div>+    size_t                           len;</div><div>+</div><div>+    header = (ngx_proxy_protocol_v2_header_t *) buf;</div><div>+</div><div>+    header->len = 0;</div><div>+</div><div>+    src = c->sockaddr;</div><div>+    dst = c->local_sockaddr;</div><div>+</div><div>+    len = 0;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    v6_used = 0;</div><div>+#endif</div><div>+</div><div>+    ngx_memcpy(header->signature, NGX_PROXY_PROTOCOL_V2_SIG,</div><div>+            NGX_PROXY_PROTOCOL_V2_SIG_LEN);</div><div>+</div><div>+    header->version_command = NGX_PROXY_PROTOCOL_V2_CMD_PROXY;</div><div>+    header->family_transport = NGX_PROXY_PROTOCOL_V2_TRANS_STREAM;</div><div>+</div><div>+    /** Addrs */</div><div>+</div><div>+    switch (src->sa_family) {</div><div>+</div><div>+    case AF_INET:</div><div>+</div><div>+        if (dst->sa_family == AF_INET) {</div><div>+</div><div>+            header->addr.ip4.src_addr =</div><div>+                    ((struct sockaddr_in *) src)->sin_addr.s_addr;</div><div>+            header->addr.ip4.src_port = ((struct sockaddr_in *) src)->sin_port;</div><div>+        }</div><div>+#if (NGX_HAVE_INET6)</div><div>+        else /** dst == AF_INET6 */{</div><div>+</div><div>+            ngx_v4tov6(&v6_tmp, src);</div><div>+            ngx_memcpy(header->addr.ip6.src_addr, &v6_tmp, 16);</div><div>+            header->addr.ip6.src_port = ((struct sockaddr_in *) src)->sin_port;</div><div>+        }</div><div>+#endif</div><div>+        break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case AF_INET6:</div><div>+        v6_used = 1;</div><div>+</div><div>+        ngx_memcpy(header->addr.ip6.src_addr,</div><div>+                &((struct sockaddr_in6 *) src)->sin6_addr, 16);</div><div>+        header->addr.ip6.src_port = ((struct sockaddr_in6 *) src)->sin6_port;</div><div>+</div><div>+        break;</div><div>+#endif</div><div>+</div><div>+    default:</div><div>+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,</div><div>+                    "PROXY protocol v2 unsupported src address family %ui",</div><div>+                    src->sa_family);</div><div>+        goto unspec;</div><div>+    };</div><div>+</div><div>+    switch (dst->sa_family) {</div><div>+    case AF_INET:</div><div>+</div><div>+        if (src->sa_family == AF_INET) {</div><div>+</div><div>+            header->addr.ip4.dst_addr =</div><div>+                ((struct sockaddr_in *) dst)->sin_addr.s_addr;</div><div>+            header->addr.ip4.dst_port = ((struct sockaddr_in *) dst)->sin_port;</div><div>+        }</div><div>+#if (NGX_HAVE_INET6)</div><div>+        else /** src == AF_INET6 */{</div><div>+</div><div>+            ngx_v4tov6(&v6_tmp, dst);</div><div>+            ngx_memcpy(header->addr.ip6.dst_addr, &v6_tmp, 16);</div><div>+            header->addr.ip6.dst_port = ((struct sockaddr_in *) dst)->sin_port;</div><div>+</div><div>+        }</div><div>+#endif</div><div>+        break;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    case AF_INET6:</div><div>+        v6_used = 1;</div><div>+</div><div>+        ngx_memcpy(header->addr.ip6.dst_addr,</div><div>+                &((struct sockaddr_in6 *) dst)->sin6_addr, 16);</div><div>+        header->addr.ip6.dst_port = ((struct sockaddr_in6 *) dst)->sin6_port;</div><div>+</div><div>+        break;</div><div>+#endif</div><div>+</div><div>+    default:</div><div>+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,</div><div>+                    "PROXY protocol v2 unsupported dest address family %ui",</div><div>+                    dst->sa_family);</div><div>+        goto unspec;</div><div>+    }</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+    if (!v6_used) {</div><div>+        header->family_transport |= NGX_PROXY_PROTOCOL_V2_FAM_INET;</div><div>+        len = NGX_PROXY_PROTOCOL_V2_HDR_LEN_INET;</div><div>+</div><div>+    } else {</div><div>+        header->family_transport |= NGX_PROXY_PROTOCOL_V2_FAM_INET6;</div><div>+        len = NGX_PROXY_PROTOCOL_V2_HDR_LEN_INET6;</div><div>+</div><div>+    }</div><div>+#else</div><div>+    header->family_transport |= NGX_PROXY_PROTOCOL_V2_FAM_INET;</div><div>+    len = NGX_PROXY_PROTOCOL_V2_HDR_LEN_INET;</div><div>+#endif</div><div>+</div><div>+    /** SSL TLVs */</div><div>+</div><div>+#if (NGX_STREAM_SSL)</div><div>+</div><div>+    data = NULL;</div><div>+    data_len = 0;</div><div>+</div><div>+    tlv = (ngx_tlv_ssl_t *) (buf + len);</div><div>+    ngx_memzero(tlv, sizeof(ngx_tlv_ssl_t));</div><div>+</div><div>+    tlv->tlv.type = NGX_PROXY_PROTOCOL_V2_TYPE_SSL;</div><div>+    pos = buf + len + sizeof(ngx_tlv_ssl_t);</div><div>+</div><div>+    tlv->client |= NGX_PROXY_PROTOCOL_V2_CLIENT_SSL;</div><div>+</div><div>+    if (c->ssl != NULL) {</div><div>+</div><div>+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation</div><div>+        SSL_get0_alpn_selected(c->ssl->connection, &data, &data_len);</div><div>+</div><div>+#ifdef TLSEXT_TYPE_next_proto_neg</div><div>+        if (data_len == 0) {</div><div>+            SSL_get0_next_proto_negotiated(c->ssl->connection,</div><div>+                    &data, &data_len);</div><div>+        }</div><div>+#endif</div><div>+</div><div>+#else /* TLSEXT_TYPE_next_proto_neg */</div><div>+        SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &data_len);</div><div>+#endif</div><div>+</div><div>+        if (data_len) {</div><div>+</div><div>+            pos = ngx_copy_tlv(pos, last,</div><div>+                        NGX_PROXY_PROTOCOL_V2_TYPE_ALPN,</div><div>+                        (u_char *) data, (uint16_t) data_len);</div><div>+            if (pos == NULL) {</div><div>+                return NULL;</div><div>+            }</div><div>+        }</div><div>+</div><div>+        value = (u_char *) SSL_get_version(c->ssl->connection);</div><div>+        if (value != NULL) {</div><div>+</div><div>+            pos = ngx_copy_tlv(pos, last,</div><div>+                    NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_VERSION,</div><div>+                    value, ngx_strlen(value));</div><div>+            if (pos == NULL) {</div><div>+                return NULL;</div><div>+            }</div><div>+        }</div><div>+</div><div>+        crt = SSL_get_peer_certificate(c->ssl->connection);</div><div>+        if (crt != NULL) {</div><div>+</div><div>+            tlv->client |= NGX_PROXY_PROTOCOL_V2_CLIENT_CERT_SESS;</div><div>+</div><div>+            rc = SSL_get_verify_result(c->ssl->connection);</div><div>+            tlv->verify = htonl(rc);</div><div>+</div><div>+            if (rc == X509_V_OK) {</div><div>+</div><div>+                if (ngx_ssl_ocsp_get_status(c, &s) == NGX_OK) {</div><div>+                    tlv->client |= NGX_PROXY_PROTOCOL_V2_CLIENT_CERT_CONN;</div><div>+                }</div><div>+            }</div><div>+</div><div>+            X509_free(crt);</div><div>+        }</div><div>+</div><div>+        crt = SSL_get_certificate(c->ssl->connection);</div><div>+        if (crt != NULL) {</div><div>+</div><div>+            key = X509_get_pubkey(crt);</div><div>+</div><div>+            /** Key */</div><div>+            if (key != NULL) {</div><div>+</div><div>+                switch (EVP_PKEY_base_id(key)) {</div><div>+                case EVP_PKEY_RSA:</div><div>+                    value = (u_char *) "RSA";</div><div>+                    break;</div><div>+                case EVP_PKEY_EC:</div><div>+                    value = (u_char *) "EC";</div><div>+                    break;</div><div>+                case EVP_PKEY_DSA:</div><div>+                    value = (u_char *) "DSA";</div><div>+                    break;</div><div>+                default:</div><div>+                    value = NULL;</div><div>+                    break;</div><div>+                }</div><div>+</div><div>+                if (value != NULL) {</div><div>+</div><div>+                    value = ngx_snprintf(kbuf, sizeof(kbuf) - 1, "%s%d%Z",</div><div>+                            value, EVP_PKEY_bits(key));</div><div>+</div><div>+                    pos = ngx_copy_tlv(pos, last,</div><div>+                                NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_KEY_ALG,</div><div>+                                kbuf, ngx_strlen(kbuf));</div><div>+                }</div><div>+</div><div>+                EVP_PKEY_free(key);</div><div>+</div><div>+                if (pos == NULL) {</div><div>+                    return NULL;</div><div>+                }</div><div>+            }</div><div>+</div><div>+            /* ALG */</div><div>+            X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));</div><div>+            value = (u_char *) OBJ_nid2sn(OBJ_obj2nid(algorithm));</div><div>+</div><div>+            if (value != NULL) {</div><div>+</div><div>+                pos = ngx_copy_tlv(pos, last,</div><div>+                            NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_SIG_ALG,</div><div>+                            value, ngx_strlen(value));</div><div>+                if (pos == NULL) {</div><div>+                    return NULL;</div><div>+                }</div><div>+            }</div><div>+        }</div><div>+</div><div>+        value = (u_char *) SSL_get_cipher_name(c->ssl->connection);</div><div>+        if (value != NULL) {</div><div>+</div><div>+            pos = ngx_copy_tlv(pos, last,</div><div>+                    NGX_PROXY_PROTOCOL_V2_SUBTYPE_SSL_CIPHER,</div><div>+                    value, ngx_strlen(value));</div><div>+            if (pos == NULL) {</div><div>+                return NULL;</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+</div><div>+    tlv_len = pos - (buf + len);</div><div>+</div><div>+    tlv->tlv.length_hi = (uint16_t) (tlv_len - sizeof(ngx_tlv_t)) >> 8;</div><div>+    tlv->tlv.length_lo = (uint16_t) (tlv_len - sizeof(ngx_tlv_t)) & 0x00ff;</div><div>+</div><div>+    len = len + tlv_len;</div><div>+</div><div>+#endif</div><div>+</div><div>+    header->len = htons(len - NGX_PROXY_PROTOCOL_V2_HDR_LEN);</div><div>+    return buf + len;</div><div>+</div><div>+unspec:</div><div>+    header->family_transport |= NGX_PROXY_PROTOCOL_V2_FAM_UNSPEC;</div><div>+    header->len = 0;</div><div>+</div><div>+    return buf + NGX_PROXY_PROTOCOL_V2_HDR_LEN;</div><div>+}</div><div>+</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+static void</div><div>+ngx_v4tov6(struct in6_addr *sin6_addr, struct sockaddr *addr)</div><div>+{</div><div>+    static const char rfc4291[] = { 0x00, 0x00, 0x00, 0x00,</div><div>+                                    0x00, 0x00, 0x00, 0x00,</div><div>+                                    0x00, 0x00, 0xFF, 0xFF };</div><div>+</div><div>+    struct in_addr tmp_addr, *sin_addr;</div><div>+</div><div>+    sin_addr = &((struct sockaddr_in *) addr)->sin_addr;</div><div>+</div><div>+    tmp_addr.s_addr = sin_addr->s_addr;</div><div>+    ngx_memcpy(sin6_addr->s6_addr, rfc4291, sizeof(rfc4291));</div><div>+    ngx_memcpy(sin6_addr->s6_addr + 12, &tmp_addr.s_addr, 4);</div><div>+}</div><div>+#endif</div><div>+</div><div>+</div><div>+#if (NGX_STREAM_SSL)</div><div>+</div><div>+static u_char *</div><div>+ngx_copy_tlv(u_char *pos, u_char *last, u_char type,</div><div>+        u_char *value, uint16_t value_len)</div><div>+{</div><div>+    ngx_tlv_t   *tlv;</div><div>+</div><div>+    if (last - pos < (long) sizeof(*tlv)) {</div><div>+        return NULL;</div><div>+    }</div><div>+</div><div>+    tlv = (ngx_tlv_t *) pos;</div><div>+</div><div>+    tlv->type = type;</div><div>+    tlv->length_hi = (uint16_t) value_len >> 8;</div><div>+    tlv->length_lo = (uint16_t) value_len & 0x00ff;</div><div>+    ngx_memcpy(tlv->value, value, value_len);</div><div>+</div><div>+    return pos + (value_len + sizeof(*tlv));</div><div>+}</div><div>+</div><div>+#endif</div><div>+</div><div>+</div><div>diff -r 82e174e47663 src/core/ngx_proxy_protocol.h</div><div>--- a/src/core/ngx_proxy_protocol.h<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Thu Apr 08 00:16:30 2021 +0300</div><div>+++ b/src/core/ngx_proxy_protocol.h<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Fri Apr 09 16:10:29 2021 +0300</div><div>@@ -13,7 +13,7 @@</div><div> #include <ngx_core.h></div><div> </div><div> </div><div>-#define NGX_PROXY_PROTOCOL_MAX_HEADER  107</div><div>+#define NGX_PROXY_PROTOCOL_MAX_HEADER  214</div><div> </div><div> </div><div> struct ngx_proxy_protocol_s {</div><div>@@ -27,7 +27,7 @@</div><div> u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,</div><div>     u_char *last);</div><div> u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf,</div><div>-    u_char *last);</div><div>+    u_char *last, ngx_uint_t pp_version);</div><div> </div><div> </div><div> #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */</div><div>diff -r 82e174e47663 src/stream/ngx_stream_proxy_module.c</div><div>--- a/src/stream/ngx_stream_proxy_module.c<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Thu Apr 08 00:16:30 2021 +0300</div><div>+++ b/src/stream/ngx_stream_proxy_module.c<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>Fri Apr 09 16:10:29 2021 +0300</div><div>@@ -30,7 +30,7 @@</div><div>     ngx_uint_t                       responses;</div><div>     ngx_uint_t                       next_upstream_tries;</div><div>     ngx_flag_t                       next_upstream;</div><div>-    ngx_flag_t                       proxy_protocol;</div><div>+    ngx_uint_t                       proxy_protocol;</div><div>     ngx_stream_upstream_local_t     *local;</div><div>     ngx_flag_t                       socket_keepalive;</div><div> </div><div>@@ -121,6 +121,14 @@</div><div> #endif</div><div> </div><div> </div><div>+static ngx_conf_enum_t  ngx_stream_proxy_protocol[] = {</div><div>+    { ngx_string("off"), 0 },</div><div>+    { ngx_string("on"), 1 },</div><div>+    { ngx_string("v2"), 2 },</div><div>+    { ngx_null_string, 0 }</div><div>+};</div><div>+</div><div>+</div><div> static ngx_conf_deprecated_t  ngx_conf_deprecated_proxy_downstream_buffer = {</div><div>     ngx_conf_deprecated, "proxy_downstream_buffer", "proxy_buffer_size"</div><div> };</div><div>@@ -239,10 +247,10 @@</div><div> </div><div>     { ngx_string("proxy_protocol"),</div><div>       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,</div><div>-      ngx_conf_set_flag_slot,</div><div>+      ngx_conf_set_enum_slot,</div><div>       NGX_STREAM_SRV_CONF_OFFSET,</div><div>       offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),</div><div>-      NULL },</div><div>+      &ngx_stream_proxy_protocol },</div><div> </div><div> #if (NGX_STREAM_SSL)</div><div> </div><div>@@ -891,7 +899,8 @@</div><div> </div><div>         cl->buf->pos = p;</div><div> </div><div>-        p = ngx_proxy_protocol_write(c, p, p + NGX_PROXY_PROTOCOL_MAX_HEADER);</div><div>+        p = ngx_proxy_protocol_write(c, p, p + NGX_PROXY_PROTOCOL_MAX_HEADER,</div><div>+                u->proxy_protocol);</div><div>         if (p == NULL) {</div><div>             ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);</div><div>             return;</div><div>@@ -942,14 +951,15 @@</div><div>     ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,</div><div>                    "stream proxy send PROXY protocol header");</div><div> </div><div>-    p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER);</div><div>+    u = s->upstream;</div><div>+</div><div>+    p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER,</div><div>+            u->proxy_protocol);</div><div>     if (p == NULL) {</div><div>         ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);</div><div>         return NGX_ERROR;</div><div>     }</div><div> </div><div>-    u = s->upstream;</div><div>-</div><div>     pc = u->peer.connection;</div><div> </div><div>     size = p - buf;</div><div>@@ -1998,7 +2008,7 @@</div><div>     conf->responses = NGX_CONF_UNSET_UINT;</div><div>     conf->next_upstream_tries = NGX_CONF_UNSET_UINT;</div><div>     conf->next_upstream = NGX_CONF_UNSET;</div><div>-    conf->proxy_protocol = NGX_CONF_UNSET;</div><div>+    conf->proxy_protocol = NGX_CONF_UNSET_UINT;</div><div>     conf->local = NGX_CONF_UNSET_PTR;</div><div>     conf->socket_keepalive = NGX_CONF_UNSET;</div><div> </div><div>@@ -2053,7 +2063,7 @@</div><div> </div><div>     ngx_conf_merge_value(conf->next_upstream, prev->next_upstream, 1);</div><div> </div><div>-    ngx_conf_merge_value(conf->proxy_protocol, prev->proxy_protocol, 0);</div><div>+    ngx_conf_merge_uint_value(conf->proxy_protocol, prev->proxy_protocol, 0);</div><div> </div><div>     ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);</div><div> </div><div>diff -r 82e174e47663 src/stream/ngx_stream_upstream.h</div><div>--- a/src/stream/ngx_stream_upstream.h<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Thu Apr 08 00:16:30 2021 +0300</div><div>+++ b/src/stream/ngx_stream_upstream.h<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Fri Apr 09 16:10:29 2021 +0300</div><div>@@ -141,7 +141,7 @@</div><div>     ngx_stream_upstream_resolved_t    *resolved;</div><div>     ngx_stream_upstream_state_t       *state;</div><div>     unsigned                           connected:1;</div><div>-    unsigned                           proxy_protocol:1;</div><div>+    unsigned                           proxy_protocol:2;</div><div> } ngx_stream_upstream_t;</div><div> </div></div></div>