mirror of
https://github.com/nginx/nginx.git
synced 2026-05-13 09:36:42 +00:00
Stream: proxy_protocol_crc32c directive for PROXY protocol v2.
Add a proxy_protocol_crc32c on|off directive to the stream proxy module. When enabled, a CRC32c checksum TLV (type 0x03, length 4) is appended to the PROXY protocol v2 header before sending it upstream. The checksum is computed over the entire assembled header with the four-byte CRC32c value field zeroed, then written in network byte order, as required by the PROXY protocol spec. Core: add ngx_proxy_protocol_v2_write_crc32c(c, buf, p, last) which appends the zeroed CRC TLV to the buffer at p, updates header->len, computes the CRC32c from buf through the end of the TLV, and fills in the result.
This commit is contained in:
parent
f78f953a56
commit
dd7da8fb7c
3 changed files with 90 additions and 0 deletions
|
|
@ -502,6 +502,54 @@ ngx_proxy_protocol_v2_write_tlvs(ngx_connection_t *c, u_char *buf,
|
|||
}
|
||||
|
||||
|
||||
u_char *
|
||||
ngx_proxy_protocol_v2_write_crc32c(ngx_connection_t *c, u_char *buf,
|
||||
u_char *p, u_char *last)
|
||||
{
|
||||
uint16_t len;
|
||||
uint32_t crc;
|
||||
ngx_proxy_protocol_header_t *header;
|
||||
ngx_proxy_protocol_tlv_t *wire;
|
||||
|
||||
/* type(1) + len(2) + crc32c_value(4) = 7 bytes */
|
||||
if (p + 7 > last) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, 0,
|
||||
"too small buffer for PROXY protocol v2 CRC32c TLV");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Append CRC32c TLV with zeroed value field */
|
||||
wire = (ngx_proxy_protocol_tlv_t *) p;
|
||||
wire->type = 0x03;
|
||||
wire->len[0] = 0;
|
||||
wire->len[1] = 4;
|
||||
p += sizeof(ngx_proxy_protocol_tlv_t);
|
||||
|
||||
p[0] = 0;
|
||||
p[1] = 0;
|
||||
p[2] = 0;
|
||||
p[3] = 0;
|
||||
p += 4;
|
||||
|
||||
/* Update the PPv2 length field to include this TLV */
|
||||
header = (ngx_proxy_protocol_header_t *) buf;
|
||||
len = ngx_proxy_protocol_parse_uint16(header->len) + 7;
|
||||
header->len[0] = (u_char) (len >> 8);
|
||||
header->len[1] = (u_char) len;
|
||||
|
||||
/* Compute CRC32c over the entire assembled header (zeroed value included) */
|
||||
crc = ngx_crc32c(buf, p - buf);
|
||||
|
||||
/* Write the checksum in network byte order */
|
||||
p[-4] = (u_char) (crc >> 24);
|
||||
p[-3] = (u_char) (crc >> 16);
|
||||
p[-2] = (u_char) (crc >> 8);
|
||||
p[-1] = (u_char) crc;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, u_char *last)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ u_char *ngx_proxy_protocol_v2_write(ngx_connection_t *c, u_char *buf,
|
|||
u_char *last);
|
||||
u_char *ngx_proxy_protocol_v2_write_tlvs(ngx_connection_t *c, u_char *buf,
|
||||
u_char *last, ngx_array_t *tlvs);
|
||||
u_char *ngx_proxy_protocol_v2_write_crc32c(ngx_connection_t *c, u_char *buf,
|
||||
u_char *p, u_char *last);
|
||||
ngx_int_t ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
|
||||
ngx_str_t *value);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ typedef struct {
|
|||
ngx_flag_t proxy_protocol;
|
||||
ngx_uint_t proxy_protocol_version;
|
||||
ngx_array_t *proxy_protocol_tlvs;
|
||||
ngx_flag_t proxy_protocol_crc32c;
|
||||
ngx_flag_t half_close;
|
||||
ngx_stream_upstream_local_t *local;
|
||||
ngx_flag_t socket_keepalive;
|
||||
|
|
@ -288,6 +289,13 @@ static ngx_command_t ngx_stream_proxy_commands[] = {
|
|||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_protocol_crc32c"),
|
||||
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, proxy_protocol_crc32c),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_half_close"),
|
||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
|
|
@ -1026,6 +1034,10 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
|
|||
buf_size += tlv_size;
|
||||
}
|
||||
|
||||
if (pscf->proxy_protocol_version == 2 && pscf->proxy_protocol_crc32c) {
|
||||
buf_size += 7; /* CRC32c TLV: type(1) + len(2) + value(4) */
|
||||
}
|
||||
|
||||
p = ngx_pnalloc(c->pool, buf_size);
|
||||
if (p == NULL) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
|
|
@ -1046,6 +1058,15 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s)
|
|||
return;
|
||||
}
|
||||
|
||||
if (pscf->proxy_protocol_version == 2 && pscf->proxy_protocol_crc32c) {
|
||||
p = ngx_proxy_protocol_v2_write_crc32c(c, cl->buf->pos, p,
|
||||
cl->buf->pos + buf_size);
|
||||
if (p == NULL) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cl->buf->last = p;
|
||||
cl->buf->temporary = 1;
|
||||
cl->buf->flush = 0;
|
||||
|
|
@ -1110,6 +1131,13 @@ ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
|
|||
}
|
||||
|
||||
buf_size += tlv_size;
|
||||
}
|
||||
|
||||
if (pscf->proxy_protocol_version == 2 && pscf->proxy_protocol_crc32c) {
|
||||
buf_size += 7; /* CRC32c TLV: type(1) + len(2) + value(4) */
|
||||
}
|
||||
|
||||
if (buf_size > NGX_PROXY_PROTOCOL_V2_MAX_HEADER) {
|
||||
buf = ngx_pnalloc(c->pool, buf_size);
|
||||
if (buf == NULL) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
|
|
@ -1129,6 +1157,14 @@ ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s)
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (pscf->proxy_protocol_version == 2 && pscf->proxy_protocol_crc32c) {
|
||||
p = ngx_proxy_protocol_v2_write_crc32c(c, buf, p, buf + buf_size);
|
||||
if (p == NULL) {
|
||||
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
u = s->upstream;
|
||||
|
||||
pc = u->peer.connection;
|
||||
|
|
@ -2489,6 +2525,7 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
|
|||
conf->proxy_protocol = NGX_CONF_UNSET;
|
||||
conf->proxy_protocol_version = NGX_CONF_UNSET_UINT;
|
||||
conf->proxy_protocol_tlvs = NGX_CONF_UNSET_PTR;
|
||||
conf->proxy_protocol_crc32c = NGX_CONF_UNSET;
|
||||
conf->local = NGX_CONF_UNSET_PTR;
|
||||
conf->socket_keepalive = NGX_CONF_UNSET;
|
||||
conf->half_close = NGX_CONF_UNSET;
|
||||
|
|
@ -2553,6 +2590,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||
ngx_conf_merge_ptr_value(conf->proxy_protocol_tlvs,
|
||||
prev->proxy_protocol_tlvs, NULL);
|
||||
|
||||
ngx_conf_merge_value(conf->proxy_protocol_crc32c,
|
||||
prev->proxy_protocol_crc32c, 0);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->local, prev->local, NULL);
|
||||
|
||||
ngx_conf_merge_value(conf->socket_keepalive,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue