mdewitt11 2 days ago committed by GitHub
commit 41fe79f5fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      src/core/ngx_connection.h
  2. 117
      src/core/ngx_proxy_protocol.c
  3. 42
      src/core/ngx_proxy_protocol.h
  4. 101
      src/stream/ngx_stream_proxy_module.c

@ -9,6 +9,7 @@
#define _NGX_CONNECTION_H_INCLUDED_
#include "ngx_proxy_protocol.h"
#include <ngx_config.h>
#include <ngx_core.h>
@ -148,6 +149,7 @@ struct ngx_connection_s {
ngx_str_t addr_text;
ngx_proxy_protocol_t *proxy_protocol;
ngx_proxy_protocol_tlv_buf_t ppv2_tlv;
#if (NGX_QUIC || NGX_COMPAT)
ngx_quic_stream_t *quic;

@ -3,15 +3,13 @@
* Copyright (C) Roman Arutyunyan
* Copyright (C) Nginx, Inc.
*/
#include <ngx_config.h>
#include <ngx_core.h>
#define NGX_PROXY_PROTOCOL_AF_INET 1
#define NGX_PROXY_PROTOCOL_AF_INET6 2
#define NGX_PROXY_PROTOCOL_V2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
#define ngx_proxy_protocol_parse_uint16(p) \
( ((uint16_t) (p)[0] << 8) \
@ -321,6 +319,119 @@ ngx_proxy_protocol_write(ngx_connection_t *c, u_char *buf, u_char *last)
return ngx_slprintf(buf, last, " %ui %ui" CRLF, port, lport);
}
ngx_int_t
ngx_proxy_protocol_v2_build_tlv(ngx_connection_t *c,
ngx_proxy_v2_tlv *tlvs,
ngx_uint_t n)
{
size_t size = 0;
u_char *p;
ngx_uint_t i;
for (i = 0; i < n; i++) {
size += 3 + tlvs[i].length; /* type + length(2) + value */
}
p = ngx_palloc(c->pool, size);
if (p == NULL) {
return NGX_ERROR;
}
c->ppv2_tlv.pos = p;
c->ppv2_tlv.len = size;
for (i = 0; i < n; i++) {
*p++ = tlvs[i].type;
*p++ = (u_char) (tlvs[i].length >> 8);
*p++ = (u_char) (tlvs[i].length);
p = ngx_cpymem(p, tlvs[i].value.data, tlvs[i].length);
}
return NGX_OK;
}
u_char *
ngx_proxy_protocol_v2_write(ngx_connection_t *c, u_char *buf, u_char *last) {
u_char *buf_ptr = buf;
ngx_uint_t port, lport;
if (last - buf < NGX_PROXY_PROTOCOL_V2_MAX_HEADER) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "the buffer is too small for proxy protocol v2");
return NULL;
}
buf_ptr = ngx_cpymem(buf_ptr, NGX_PROXY_PROTOCOL_V2_SIG, 12);
*buf_ptr++ = 0x21;
port = ngx_inet_get_port(c->sockaddr);
lport = ngx_inet_get_port(c->local_sockaddr);
switch (c->sockaddr->sa_family) {
case AF_INET: {
*buf_ptr++ = 0x11;
*buf_ptr++ = 0x00;
*buf_ptr++ = 0x0C;
struct sockaddr_in *sin;
sin = (struct sockaddr_in *) c->sockaddr;
struct sockaddr_in *lsin;
lsin = (struct sockaddr_in *) c->local_sockaddr;
buf_ptr = ngx_cpymem(buf_ptr, &sin->sin_addr.s_addr, 4);
buf_ptr = ngx_cpymem(buf_ptr, &lsin->sin_addr.s_addr, 4);
*buf_ptr++ = (u_char) (port >> 8);
*buf_ptr++ = (u_char) port;
*buf_ptr++ = (u_char) (lport >> 8);
*buf_ptr++ = (u_char) lport;
break;
}
#if (NGX_HAVE_INET6)
case AF_INET6: {
*buf_ptr++ = 0x00;
*buf_ptr++ = 0x24;
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *) c->sockaddr;
struct sockaddr_in6 *lsin6;
lsin6 = (struct sockaddr_in6 *) c->local_sockaddr;
buf_ptr = ngx_cpymem(buf_ptr, &sin6->sin6_addr, 16);
buf_ptr = ngx_cpymem(buf_ptr, &lsin6->sin6_addr, 16);
*buf_ptr++ = (u_char)(port >> 8);
*buf_ptr++ = (u_char) port;
*buf_ptr++ = (u_char)(lport >> 8);
*buf_ptr++ = (u_char) lport;
break;
}
#endif
default: {
*buf_ptr++ = 0x00;
*buf_ptr++ = 0x00;
*buf_ptr++ = 0x00;
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "unsupported address family");
return NULL;
}
}
if (c->ppv2_tlv.len) {
buf_ptr = ngx_cpymem(buf_ptr,
c->ppv2_tlv.pos,
c->ppv2_tlv.len);
}
return buf_ptr;
}
static u_char *
ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)

@ -4,34 +4,46 @@
* Copyright (C) Nginx, Inc.
*/
#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
#define _NGX_PROXY_PROTOCOL_H_INCLUDED_
#include "ngx_string.h"
#include <stdint.h>
#include <ngx_config.h>
#include <ngx_core.h>
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_MAX_HEADER 4096
#define NGX_PROXY_PROTOCOL_V1_MAX_HEADER 107
#define NGX_PROXY_PROTOCOL_V2_MAX_HEADER 64
#define NGX_PROXY_PROTOCOL_MAX_HEADER 4096
struct ngx_proxy_protocol_s {
ngx_str_t src_addr;
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
ngx_str_t tlvs;
ngx_str_t src_addr;
ngx_str_t dst_addr;
in_port_t src_port;
in_port_t dst_port;
ngx_str_t tlvs;
};
typedef struct {
u_char *pos;
u_char len;
} ngx_proxy_protocol_tlv_buf_t;
typedef struct {
uint8_t type;
uint16_t length;
ngx_str_t value;
} ngx_proxy_v2_tlv;
u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
u_char *last);
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,
u_char *last);
u_char *last);
u_char *ngx_proxy_protocol_v2_write(ngx_connection_t *c, u_char *buf,
u_char *last);
ngx_int_t ngx_proxy_protocol_v2_build_tlv(ngx_connection_t *c, ngx_proxy_v2_tlv *tlvs,
ngx_uint_t n);
ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
ngx_str_t *value);
ngx_str_t *value);
#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */

@ -9,7 +9,6 @@
#include <ngx_core.h>
#include <ngx_stream.h>
typedef struct {
ngx_addr_t *addr;
ngx_stream_complex_value_t *value;
@ -31,9 +30,11 @@ typedef struct {
ngx_uint_t next_upstream_tries;
ngx_flag_t next_upstream;
ngx_flag_t proxy_protocol;
ngx_flag_t protocol_version;
ngx_flag_t half_close;
ngx_stream_upstream_local_t *local;
ngx_flag_t socket_keepalive;
ngx_array_t *pp2_tlvs;
#if (NGX_STREAM_SSL)
ngx_flag_t ssl_enable;
@ -91,6 +92,8 @@ static char *ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_stream_proxy_bind(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_stream_proxy_protocol_tlv(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#if (NGX_STREAM_SSL)
@ -253,12 +256,26 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
offsetof(ngx_stream_proxy_srv_conf_t, proxy_protocol),
NULL },
{ ngx_string("proxy_protocol_version"),
NGX_STREAM_MAIN_CONF | NGX_STREAM_SRV_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_STREAM_SRV_CONF_OFFSET,
offsetof(ngx_stream_proxy_srv_conf_t, protocol_version),
NULL},
{ ngx_string("proxy_half_close"),
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_STREAM_SRV_CONF_OFFSET,
offsetof(ngx_stream_proxy_srv_conf_t, half_close),
NULL },
{ ngx_string("proxy_protocol_tlv"),
NGX_STREAM_SRV_CONF | NGX_CONF_TAKE2,
ngx_stream_proxy_protocol_tlv,
NGX_STREAM_SRV_CONF_OFFSET,
0,
NULL },
#if (NGX_STREAM_SSL)
@ -400,6 +417,46 @@ ngx_module_t ngx_stream_proxy_module = {
NGX_MODULE_V1_PADDING
};
static char *
ngx_stream_proxy_protocol_tlv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_stream_proxy_srv_conf_t *pscf = conf;
ngx_proxy_v2_tlv *tlv;
ngx_str_t *value;
if (pscf->pp2_tlvs == NULL) {
pscf->pp2_tlvs = ngx_array_create(cf->pool, 2,
sizeof(ngx_proxy_v2_tlv));
if (pscf->pp2_tlvs == NULL) {
return NGX_CONF_ERROR;
}
}
tlv = ngx_array_push(pscf->pp2_tlvs);
if (tlv == NULL) {
return NGX_CONF_ERROR;
}
value = cf->args->elts;
if (value[1].len > 2
&& value[1].data[0] == '0'
&& value[1].data[1] == 'x')
{
tlv->type = (uint8_t) ngx_hextoi(value[1].data + 2,
value[1].len - 2);
} else if (ngx_strcmp(value[1].data, "alpn") == 0) {
tlv->type = 0x01;
} else {
return "unknown proxy protocol v2 TLV type";
}
tlv->value = value[2];
tlv->length = (uint16_t) value[2].len;
return NGX_CONF_OK;
}
static void
ngx_stream_proxy_handler(ngx_stream_session_t *s)
@ -834,6 +891,15 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
if (pscf->pp2_tlvs && pscf->pp2_tlvs->nelts) {
ngx_proxy_protocol_v2_build_tlv(
s->connection,
pscf->pp2_tlvs->elts,
pscf->pp2_tlvs->nelts
);
}
#if (NGX_STREAM_SSL)
if (pc->type == SOCK_STREAM && pscf->ssl_enable) {
@ -927,7 +993,11 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
return;
}
p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (pscf->proxy_protocol == 2){
p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_V2_MAX_HEADER);
} else{
p = ngx_pnalloc(c->pool, NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
}
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
@ -935,8 +1005,13 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
cl->buf->pos = p;
p = ngx_proxy_protocol_write(c, p,
p + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (pscf->protocol_version == 2) {
p = ngx_proxy_protocol_v2_write(c, p,
p + NGX_PROXY_PROTOCOL_V2_MAX_HEADER);
} else {
p = ngx_proxy_protocol_write(c, p,
p + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
}
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
@ -969,7 +1044,6 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
ngx_stream_proxy_process(s, 0, 1);
}
#if (NGX_STREAM_SSL)
static ngx_int_t
@ -986,9 +1060,16 @@ ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream proxy send PROXY protocol header");
pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
p = ngx_proxy_protocol_write(c, buf,
buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (pscf->protocol_version == 2) {
p = ngx_proxy_protocol_v2_write(c, buf,
buf + NGX_PROXY_PROTOCOL_V2_MAX_HEADER);
} else {
p = ngx_proxy_protocol_write(c, buf,
buf + NGX_PROXY_PROTOCOL_V1_MAX_HEADER);
if (p == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
@ -2216,9 +2297,11 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
conf->next_upstream_tries = NGX_CONF_UNSET_UINT;
conf->next_upstream = NGX_CONF_UNSET;
conf->proxy_protocol = NGX_CONF_UNSET;
conf->protocol_version = NGX_CONF_UNSET_UINT;
conf->local = NGX_CONF_UNSET_PTR;
conf->socket_keepalive = NGX_CONF_UNSET;
conf->half_close = NGX_CONF_UNSET;
conf->pp2_tlvs = NULL;
#if (NGX_STREAM_SSL)
conf->ssl_enable = NGX_CONF_UNSET;
@ -2243,6 +2326,10 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_stream_proxy_srv_conf_t *prev = parent;
ngx_stream_proxy_srv_conf_t *conf = child;
if (conf->pp2_tlvs == NULL) {
conf->pp2_tlvs = prev->pp2_tlvs;
}
ngx_conf_merge_msec_value(conf->connect_timeout,
prev->connect_timeout, 60000);

Loading…
Cancel
Save