Hi, On Mon, Sep 05, 2022 at 06:58:38PM +0300, Maxim Dounin wrote: > Hello! > > On Mon, Sep 05, 2022 at 05:23:18PM +0400, Roman Arutyunyan wrote: > > > Hi, > > > > On Mon, Sep 05, 2022 at 03:52:49AM +0300, Maxim Dounin wrote: > > > Hello! > > > > > > On Wed, Aug 31, 2022 at 07:52:15PM +0400, Roman Arutyunyan wrote: > > > > > > > # HG changeset patch > > > > # User Roman Arutyunyan <a...@nginx.com> > > > > # Date 1661436099 -14400 > > > > # Thu Aug 25 18:01:39 2022 +0400 > > > > # Node ID 4b856f1dff939e4eb9c131e17af061cf2c38cfac > > > > # Parent 069a4813e8d6d7ec662d282a10f5f7062ebd817f > > > > Core: support for reading PROXY protocol v2 TLVs. > > > > > > First of all, could you please provide details on the use case? > > > I've seen requests for writing proxy protocol TLVs to upstream > > > servers (see ticket #1639), but not yet seen any meaningful > > > reading requests. > > > > The known cases are these: > > > > - > > https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#proxy-protocol > > - > > https://docs.microsoft.com/en-us/azure/private-link/private-link-service-overview#getting-connection-information-using-tcp-proxy-v2 > > - > > https://cloud.google.com/vpc/docs/configure-private-service-connect-producer#proxy-protocol > > > > The data may need further parsing, but it can be done in njs or perl. > > Thanks for the details. So, basically, it's about vendor-specific > endpoint IDs. > > > > > The TLV values are available in HTTP and Stream variables > > > > $proxy_protocol_tlv_0xN, where N is a hexadecimal TLV type number with > > > > no > > > > leading zeroes. > > > > > > I can't say I like the "hexadecimal TLV type number with no > > > leading zeroes" approach, especially given that the specification > > > uses leading zeroes in TLV types. With leading zeros might be > > > better, to match specification.
With on-demand approach this is no longer an issue. > > > Also, it might worth the effort to actually add names for known > > > types instead or in addition to numbers. > > > > This is indeed a good idea and we have such plans as a further extenion of > > this > > work. One of the problems is however that the abovementioned TLV variables > > are specified in internal documents of AWS/Azure/GCP which are not > > standards. > > They can be changed anytime, while we have to maintain those variables in > > nginx. Also, raw variables give more flexibility in supporting less known > > TLVs. > > Of course I'm not suggesting to ditch raw variables, at least not > for unknown/non-standard values. But for known/standard values it > should be easy enough to provide alternative names for easier use, > probably with type-specific parsing. > > With on-demand parsing it would be trivial to support both > $proxy_protocol_tlv_alpn and $proxy_protocol_tlv_0x01. Further, > it will be trivial to support $proxy_protocol_tlv_aws_vpc_id while > still providing $proxy_protocol_tlv_0xea for raw data. > > > > Another question is PP2_TYPE_SSL, which is itself a complex > > > structure and a list of multiple subtypes. > > > > This is an obvious one. However we had exactly zero requests for this. > > See the ticket mentioned above, it seems to be the main reason why > people want to see proxy protocol v2 to backends. > > > > Provided > > > Given the above, not sure if the approach with early parsing and > > > header-like list as in the patch is the good idea. Just > > > preserving TLVs as is and parsing them all during variable > > > evaluation might be easier and more efficient. > > > > In this case, if we have two variables, say $proxy_protocol_tlv_ssl_{sni, > > alpn}, > > we'll parse the entire TLV block twice - once per variable evaluation. > > Assuming you mean $proxy_protocol_{authority, alpn} (as these > aren't SSL subtypes), I actually see no difference in on-demand > parsing of the TLV block and looking for a header in the > pre-created list of headers. Further, parsing the block for each > variable evaluation might be actually faster due to better > locality, and should simplify adding alternative names. > > And a single TLV block certainly will be more optimal in terms of > memory usage due to no additional allocations. Not to mention the > typical case when TLV variables aren't used at all. Indeed on-demand parsing is quite easy and does not seems to be less efficient. > > > Also, the idea of merging TLV values with identical types looks > > > wrong to me, especially given that many TLSs are binary. > > > Specification does not seem to define the behaviour here, > > > unfortunately. As far as I understand, HAProxy itself still > > > doesn't implement PPv2 parsing, so there is not reference > > > implementation either. On the other hand, it should be easy > > > enough to check all TLVs for duplicate by using a 256-bit bitmask > > > and reject connections if there are any duplicates. > > > > This can be added, thanks. > > Not sure it's actually needed though, especially given that proxy > protocol is only expected to be accepted from trusted sources > anyway. It might be good enough to just assume there is only one > value with a given type. Two patches attached: - TLV on-demand parsing + raw variables - standard named variables -- Roman Arutyunyan
# HG changeset patch # User Roman Arutyunyan <a...@nginx.com> # Date 1662729947 -14400 # Fri Sep 09 17:25:47 2022 +0400 # Node ID 80714f1b0f597ce5e530e7274457450db4587fc9 # Parent 069a4813e8d6d7ec662d282a10f5f7062ebd817f Core: support for reading PROXY protocol v2 TLVs. The TLV values are available in HTTP and Stream variables $proxy_protocol_tlv_0xN, where N is a hexadecimal TLV type number. diff --git a/src/core/ngx_proxy_protocol.c b/src/core/ngx_proxy_protocol.c --- a/src/core/ngx_proxy_protocol.c +++ b/src/core/ngx_proxy_protocol.c @@ -40,6 +40,12 @@ typedef struct { } ngx_proxy_protocol_inet6_addrs_t; +typedef struct { + u_char type; + u_char len[2]; +} ngx_proxy_protocol_tlv_t; + + static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, u_char *last, ngx_str_t *addr); static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last, @@ -412,11 +418,73 @@ ngx_proxy_protocol_v2_read(ngx_connectio &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port); if (buf < end) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol v2 %z bytes of tlv ignored", end - buf); + pp->tlvs.data = ngx_pnalloc(c->pool, end - buf); + if (pp->tlvs.data == NULL) { + return NULL; + } + + ngx_memcpy(pp->tlvs.data, buf, end - buf); + pp->tlvs.len = end - buf; } c->proxy_protocol = pp; return end; } + + +ngx_int_t +ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs, + ngx_uint_t type, ngx_str_t *value) +{ + u_char *p; + size_t n, len; + ngx_proxy_protocol_tlv_t *tlv; + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol v2 lookup tlv:%02xd", type); + + if (tlvs == NULL) { + if (c->proxy_protocol == NULL) { + return NGX_DECLINED; + } + + tlvs = &c->proxy_protocol->tlvs; + } + + p = tlvs->data; + n = tlvs->len; + + while (n) { + if (n < sizeof(ngx_proxy_protocol_tlv_t)) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV"); + return NGX_ERROR; + } + + tlv = (ngx_proxy_protocol_tlv_t *) p; + len = ngx_proxy_protocol_parse_uint16(tlv->len); + + p += sizeof(ngx_proxy_protocol_tlv_t); + n -= sizeof(ngx_proxy_protocol_tlv_t); + + if (n < len) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV"); + return NGX_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol v2 tlv:0x%02xd len:%uz", + tlv->type, len); + + if (tlv->type == type) { + value->data = p; + value->len = len; + return NGX_OK; + } + + p += len; + n -= len; + } + + return NGX_DECLINED; +} diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h --- a/src/core/ngx_proxy_protocol.h +++ b/src/core/ngx_proxy_protocol.h @@ -21,6 +21,7 @@ struct ngx_proxy_protocol_s { ngx_str_t dst_addr; in_port_t src_port; in_port_t dst_port; + ngx_str_t tlvs; }; @@ -28,6 +29,8 @@ u_char *ngx_proxy_protocol_read(ngx_conn u_char *last); u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last); +ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs, + ngx_uint_t type, ngx_str_t *value); #endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */ diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -61,6 +61,8 @@ static ngx_int_t ngx_http_variable_proxy 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_proxy_protocol_tlv_0x(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, @@ -214,6 +216,10 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_proxy_protocol_port, offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, + { ngx_string("proxy_protocol_tlv_0x"), NULL, + ngx_http_variable_proxy_protocol_tlv_0x, + 0, NGX_HTTP_VAR_PREFIX, 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 }, @@ -1387,6 +1393,46 @@ ngx_http_variable_proxy_protocol_port(ng static ngx_int_t +ngx_http_variable_proxy_protocol_tlv_0x(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + size_t n; + u_char *p; + ngx_str_t s; + ngx_int_t rc, type; + + n = name->len - (sizeof("proxy_protocol_tlv_0x") - 1); + p = name->data + sizeof("proxy_protocol_tlv_0x") - 1; + + type = ngx_hextoi(p, n); + if (type == NGX_ERROR) { + return NGX_ERROR; + } + + rc = ngx_proxy_protocol_lookup_tlv(r->connection, NULL, type, &s); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = s.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s.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) { diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -23,6 +23,8 @@ static ngx_int_t ngx_stream_variable_pro ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_proxy_protocol_port( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_proxy_protocol_tlv_0x( + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s, @@ -79,6 +81,10 @@ static ngx_stream_variable_t ngx_stream ngx_stream_variable_proxy_protocol_port, offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 }, + { ngx_string("proxy_protocol_tlv_0x"), NULL, + ngx_stream_variable_proxy_protocol_tlv_0x, + 0, NGX_STREAM_VAR_PREFIX, 0 }, + { ngx_string("server_addr"), NULL, ngx_stream_variable_server_addr, 0, 0, 0 }, @@ -622,6 +628,46 @@ ngx_stream_variable_proxy_protocol_port( static ngx_int_t +ngx_stream_variable_proxy_protocol_tlv_0x(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + size_t n; + u_char *p; + ngx_str_t str; + ngx_int_t rc, type; + + n = name->len - (sizeof("proxy_protocol_tlv_0x") - 1); + p = name->data + sizeof("proxy_protocol_tlv_0x") - 1; + + type = ngx_hextoi(p, n); + if (type == NGX_ERROR) { + return NGX_ERROR; + } + + rc = ngx_proxy_protocol_lookup_tlv(s->connection, NULL, type, &str); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = str.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = str.data; + + return NGX_OK; +} + + +static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) {
# HG changeset patch # User Roman Arutyunyan <a...@nginx.com> # Date 1662718130 -14400 # Fri Sep 09 14:08:50 2022 +0400 # Node ID 832f6c96b26c3009640072e3f4b1f0bf43e644d0 # Parent 80714f1b0f597ce5e530e7274457450db4587fc9 Standard PROXY protocol v2 TLV variables. diff --git a/src/core/ngx_proxy_protocol.h b/src/core/ngx_proxy_protocol.h --- a/src/core/ngx_proxy_protocol.h +++ b/src/core/ngx_proxy_protocol.h @@ -13,7 +13,18 @@ #include <ngx_core.h> -#define NGX_PROXY_PROTOCOL_MAX_HEADER 107 +#define NGX_PROXY_PROTOCOL_MAX_HEADER 107 + +#define NGX_PROXY_PROTOCOL_TLV_ALPN 0x01 +#define NGX_PROXY_PROTOCOL_TLV_AUTHORITY 0x02 +#define NGX_PROXY_PROTOCOL_TLV_UNIQUE_ID 0x05 +#define NGX_PROXY_PROTOCOL_TLV_SSL 0x20 +#define NGX_PROXY_PROTOCOL_TLV_SSL_VERSION 0x21 +#define NGX_PROXY_PROTOCOL_TLV_SSL_CN 0x22 +#define NGX_PROXY_PROTOCOL_TLV_SSL_CIPHER 0x23 +#define NGX_PROXY_PROTOCOL_TLV_SSL_SIG_ALG 0x24 +#define NGX_PROXY_PROTOCOL_TLV_SSL_KEY_ALG 0x25 +#define NGX_PROXY_PROTOCOL_TLV_NETNS 0x30 struct ngx_proxy_protocol_s { @@ -25,6 +36,12 @@ struct ngx_proxy_protocol_s { }; +typedef struct { + u_char client; + u_char verify[4]; +} ngx_proxy_protocol_tlv_ssl_t; + + u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last); u_char *ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -63,6 +63,10 @@ static ngx_int_t ngx_http_variable_proxy ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_proxy_protocol_tlv_0x(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_tlv_ssl( + 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, @@ -220,6 +224,42 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_proxy_protocol_tlv_0x, 0, NGX_HTTP_VAR_PREFIX, 0 }, + { ngx_string("proxy_protocol_tlv_alpn"), NULL, + ngx_http_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_ALPN, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_authority"), NULL, + ngx_http_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_AUTHORITY, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_unique_id"), NULL, + ngx_http_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_UNIQUE_ID, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_version"), NULL, + ngx_http_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_VERSION, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_cn"), NULL, + ngx_http_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_CN, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_cipher"), NULL, + ngx_http_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_CIPHER, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_sig_alg"), NULL, + ngx_http_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_SIG_ALG, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_key_alg"), NULL, + ngx_http_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_KEY_ALG, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_netns"), NULL, + ngx_http_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_NETNS, 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 }, @@ -1400,8 +1440,7 @@ ngx_http_variable_proxy_protocol_tlv_0x( size_t n; u_char *p; - ngx_str_t s; - ngx_int_t rc, type; + ngx_int_t type; n = name->len - (sizeof("proxy_protocol_tlv_0x") - 1); p = name->data + sizeof("proxy_protocol_tlv_0x") - 1; @@ -1411,7 +1450,58 @@ ngx_http_variable_proxy_protocol_tlv_0x( return NGX_ERROR; } - rc = ngx_proxy_protocol_lookup_tlv(r->connection, NULL, type, &s); + return ngx_http_variable_proxy_protocol_tlv(r, v, type); +} + + +static ngx_int_t +ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t s; + ngx_int_t rc; + + rc = ngx_proxy_protocol_lookup_tlv(r->connection, NULL, data, &s); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = s.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_proxy_protocol_tlv_ssl(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t s, ssl; + ngx_int_t rc; + + rc = ngx_proxy_protocol_lookup_tlv(r->connection, NULL, + NGX_PROXY_PROTOCOL_TLV_SSL, &ssl); + + if (rc == NGX_OK) { + if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) { + return NGX_ERROR; + } + + ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t); + ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t); + + rc = ngx_proxy_protocol_lookup_tlv(r->connection, &ssl, data, &s); + } if (rc == NGX_ERROR) { return NGX_ERROR; diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -25,6 +25,10 @@ static ngx_int_t ngx_stream_variable_pro ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_proxy_protocol_tlv_0x( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_proxy_protocol_tlv( + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_proxy_protocol_tlv_ssl( + ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_server_port(ngx_stream_session_t *s, @@ -85,6 +89,42 @@ static ngx_stream_variable_t ngx_stream ngx_stream_variable_proxy_protocol_tlv_0x, 0, NGX_STREAM_VAR_PREFIX, 0 }, + { ngx_string("proxy_protocol_tlv_alpn"), NULL, + ngx_stream_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_ALPN, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_authority"), NULL, + ngx_stream_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_AUTHORITY, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_unique_id"), NULL, + ngx_stream_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_UNIQUE_ID, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_version"), NULL, + ngx_stream_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_VERSION, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_cn"), NULL, + ngx_stream_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_CN, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_cipher"), NULL, + ngx_stream_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_CIPHER, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_sig_alg"), NULL, + ngx_stream_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_SIG_ALG, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_ssl_key_alg"), NULL, + ngx_stream_variable_proxy_protocol_tlv_ssl, + NGX_PROXY_PROTOCOL_TLV_SSL_KEY_ALG, 0, 0 }, + + { ngx_string("proxy_protocol_tlv_netns"), NULL, + ngx_stream_variable_proxy_protocol_tlv, + NGX_PROXY_PROTOCOL_TLV_NETNS, 0, 0 }, + { ngx_string("server_addr"), NULL, ngx_stream_variable_server_addr, 0, 0, 0 }, @@ -635,8 +675,7 @@ ngx_stream_variable_proxy_protocol_tlv_0 size_t n; u_char *p; - ngx_str_t str; - ngx_int_t rc, type; + ngx_int_t type; n = name->len - (sizeof("proxy_protocol_tlv_0x") - 1); p = name->data + sizeof("proxy_protocol_tlv_0x") - 1; @@ -646,7 +685,58 @@ ngx_stream_variable_proxy_protocol_tlv_0 return NGX_ERROR; } - rc = ngx_proxy_protocol_lookup_tlv(s->connection, NULL, type, &str); + return ngx_stream_variable_proxy_protocol_tlv(s, v, type); +} + + +static ngx_int_t +ngx_stream_variable_proxy_protocol_tlv(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_str_t str; + ngx_int_t rc; + + rc = ngx_proxy_protocol_lookup_tlv(s->connection, NULL, data, &str); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (rc == NGX_DECLINED) { + v->not_found = 1; + return NGX_OK; + } + + v->len = str.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = str.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_stream_variable_proxy_protocol_tlv_ssl(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + ngx_str_t str, ssl; + ngx_int_t rc; + + rc = ngx_proxy_protocol_lookup_tlv(s->connection, NULL, + NGX_PROXY_PROTOCOL_TLV_SSL, &ssl); + + if (rc == NGX_OK) { + if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) { + return NGX_ERROR; + } + + ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t); + ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t); + + rc = ngx_proxy_protocol_lookup_tlv(s->connection, &ssl, data, &str); + } if (rc == NGX_ERROR) { return NGX_ERROR;
_______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org