mirror of
https://github.com/nginx/nginx.git
synced 2026-05-13 17:46:53 +00:00
Merge 7045de7e69 into 319b4ea63f
This commit is contained in:
commit
7acb101fc4
4 changed files with 237 additions and 25 deletions
|
|
@ -9,6 +9,7 @@
|
|||
#define _NGX_CONNECTION_H_INCLUDED_
|
||||
|
||||
|
||||
#include "ngx_proxy_protocol.h"
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
|
@ -151,6 +152,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;
|
||||
|
||||
u_char *ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf,
|
||||
u_char *last);
|
||||
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_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;
|
||||
|
|
@ -92,6 +93,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)
|
||||
|
||||
|
|
@ -257,12 +260,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)
|
||||
|
||||
|
|
@ -411,6 +428,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)
|
||||
|
|
@ -845,6 +902,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) {
|
||||
|
|
@ -938,7 +1004,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;
|
||||
|
|
@ -946,8 +1016,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;
|
||||
|
|
@ -980,7 +1055,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
|
||||
|
|
@ -997,9 +1071,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;
|
||||
|
|
@ -2379,9 +2460,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;
|
||||
|
|
@ -2407,6 +2490,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…
Add table
Add a link
Reference in a new issue