comparison src/core/ngx_proxy_protocol.c @ 8072:cca4c8a715de

PROXY protocol v2 TLV variables. The variables have prefix $proxy_protocol_tlv_ and are accessible by name and by type. Examples are: $proxy_protocol_tlv_0x01, $proxy_protocol_tlv_alpn.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 12 Oct 2022 16:58:16 +0400
parents 017fd847f4f7
children aa663cc2a77d
comparison
equal deleted inserted replaced
8071:017fd847f4f7 8072:cca4c8a715de
12 #define NGX_PROXY_PROTOCOL_AF_INET 1 12 #define NGX_PROXY_PROTOCOL_AF_INET 1
13 #define NGX_PROXY_PROTOCOL_AF_INET6 2 13 #define NGX_PROXY_PROTOCOL_AF_INET6 2
14 14
15 15
16 #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1]) 16 #define ngx_proxy_protocol_parse_uint16(p) ((p)[0] << 8 | (p)[1])
17
18 #define ngx_proxy_protocol_parse_uint32(p) \
19 ( ((uint32_t) (p)[0] << 24) \
20 + ( (p)[1] << 16) \
21 + ( (p)[2] << 8) \
22 + ( (p)[3]) )
17 23
18 24
19 typedef struct { 25 typedef struct {
20 u_char signature[12]; 26 u_char signature[12];
21 u_char version_command; 27 u_char version_command;
38 u_char src_port[2]; 44 u_char src_port[2];
39 u_char dst_port[2]; 45 u_char dst_port[2];
40 } ngx_proxy_protocol_inet6_addrs_t; 46 } ngx_proxy_protocol_inet6_addrs_t;
41 47
42 48
49 typedef struct {
50 u_char type;
51 u_char len[2];
52 } ngx_proxy_protocol_tlv_t;
53
54
55 typedef struct {
56 u_char client;
57 u_char verify[4];
58 } ngx_proxy_protocol_tlv_ssl_t;
59
60
61 typedef struct {
62 ngx_str_t name;
63 ngx_uint_t type;
64 } ngx_proxy_protocol_tlv_entry_t;
65
66
43 static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p, 67 static u_char *ngx_proxy_protocol_read_addr(ngx_connection_t *c, u_char *p,
44 u_char *last, ngx_str_t *addr); 68 u_char *last, ngx_str_t *addr);
45 static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last, 69 static u_char *ngx_proxy_protocol_read_port(u_char *p, u_char *last,
46 in_port_t *port, u_char sep); 70 in_port_t *port, u_char sep);
47 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf, 71 static u_char *ngx_proxy_protocol_v2_read(ngx_connection_t *c, u_char *buf,
48 u_char *last); 72 u_char *last);
73 static ngx_int_t ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c,
74 ngx_str_t *tlvs, ngx_uint_t type, ngx_str_t *value);
75
76
77 static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_entries[] = {
78 { ngx_string("alpn"), 0x01 },
79 { ngx_string("authority"), 0x02 },
80 { ngx_string("unique_id"), 0x05 },
81 { ngx_string("ssl"), 0x20 },
82 { ngx_string("netns"), 0x30 },
83 { ngx_null_string, 0x00 }
84 };
85
86
87 static ngx_proxy_protocol_tlv_entry_t ngx_proxy_protocol_tlv_ssl_entries[] = {
88 { ngx_string("version"), 0x21 },
89 { ngx_string("cn"), 0x22 },
90 { ngx_string("cipher"), 0x23 },
91 { ngx_string("sig_alg"), 0x24 },
92 { ngx_string("key_alg"), 0x25 },
93 { ngx_null_string, 0x00 }
94 };
49 95
50 96
51 u_char * 97 u_char *
52 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) 98 ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last)
53 { 99 {
416 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0, 462 ngx_log_debug4(NGX_LOG_DEBUG_CORE, c->log, 0,
417 "PROXY protocol v2 src: %V %d, dst: %V %d", 463 "PROXY protocol v2 src: %V %d, dst: %V %d",
418 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port); 464 &pp->src_addr, pp->src_port, &pp->dst_addr, pp->dst_port);
419 465
420 if (buf < end) { 466 if (buf < end) {
421 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, 467 pp->tlvs.data = ngx_pnalloc(c->pool, end - buf);
422 "PROXY protocol v2 %z bytes of tlv ignored", end - buf); 468 if (pp->tlvs.data == NULL) {
469 return NULL;
470 }
471
472 ngx_memcpy(pp->tlvs.data, buf, end - buf);
473 pp->tlvs.len = end - buf;
423 } 474 }
424 475
425 c->proxy_protocol = pp; 476 c->proxy_protocol = pp;
426 477
427 return end; 478 return end;
428 } 479 }
480
481
482 ngx_int_t
483 ngx_proxy_protocol_get_tlv(ngx_connection_t *c, ngx_str_t *name,
484 ngx_str_t *value)
485 {
486 u_char *p;
487 size_t n;
488 uint32_t verify;
489 ngx_str_t ssl, *tlvs;
490 ngx_int_t rc, type;
491 ngx_proxy_protocol_tlv_ssl_t *tlv_ssl;
492 ngx_proxy_protocol_tlv_entry_t *te;
493
494 if (c->proxy_protocol == NULL) {
495 return NGX_DECLINED;
496 }
497
498 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
499 "PROXY protocol v2 get tlv \"%V\"", name);
500
501 te = ngx_proxy_protocol_tlv_entries;
502 tlvs = &c->proxy_protocol->tlvs;
503
504 p = name->data;
505 n = name->len;
506
507 if (n >= 4 && p[0] == 's' && p[1] == 's' && p[2] == 'l' && p[3] == '_') {
508
509 rc = ngx_proxy_protocol_lookup_tlv(c, tlvs, 0x20, &ssl);
510 if (rc != NGX_OK) {
511 return rc;
512 }
513
514 if (ssl.len < sizeof(ngx_proxy_protocol_tlv_ssl_t)) {
515 return NGX_ERROR;
516 }
517
518 p += 4;
519 n -= 4;
520
521 if (n == 6 && ngx_strncmp(p, "verify", 6) == 0) {
522
523 tlv_ssl = (ngx_proxy_protocol_tlv_ssl_t *) ssl.data;
524 verify = ngx_proxy_protocol_parse_uint32(tlv_ssl->verify);
525
526 value->data = ngx_pnalloc(c->pool, NGX_INT32_LEN);
527 if (value->data == NULL) {
528 return NGX_ERROR;
529 }
530
531 value->len = ngx_sprintf(value->data, "%uD", verify)
532 - value->data;
533 return NGX_OK;
534 }
535
536 ssl.data += sizeof(ngx_proxy_protocol_tlv_ssl_t);
537 ssl.len -= sizeof(ngx_proxy_protocol_tlv_ssl_t);
538
539 te = ngx_proxy_protocol_tlv_ssl_entries;
540 tlvs = &ssl;
541 }
542
543 if (n >= 2 && p[0] == '0' && p[1] == 'x') {
544
545 type = ngx_hextoi(p + 2, n - 2);
546 if (type == NGX_ERROR) {
547 ngx_log_error(NGX_LOG_ERR, c->log, 0,
548 "invalid PROXY protocol TLV \"%V\"", name);
549 return NGX_ERROR;
550 }
551
552 return ngx_proxy_protocol_lookup_tlv(c, tlvs, type, value);
553 }
554
555 for ( /* void */ ; te->type; te++) {
556 if (te->name.len == n && ngx_strncmp(te->name.data, p, n) == 0) {
557 return ngx_proxy_protocol_lookup_tlv(c, tlvs, te->type, value);
558 }
559 }
560
561 ngx_log_error(NGX_LOG_ERR, c->log, 0,
562 "unknown PROXY protocol TLV \"%V\"", name);
563
564 return NGX_DECLINED;
565 }
566
567
568 static ngx_int_t
569 ngx_proxy_protocol_lookup_tlv(ngx_connection_t *c, ngx_str_t *tlvs,
570 ngx_uint_t type, ngx_str_t *value)
571 {
572 u_char *p;
573 size_t n, len;
574 ngx_proxy_protocol_tlv_t *tlv;
575
576 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
577 "PROXY protocol v2 lookup tlv:%02xi", type);
578
579 p = tlvs->data;
580 n = tlvs->len;
581
582 while (n) {
583 if (n < sizeof(ngx_proxy_protocol_tlv_t)) {
584 ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
585 return NGX_ERROR;
586 }
587
588 tlv = (ngx_proxy_protocol_tlv_t *) p;
589 len = ngx_proxy_protocol_parse_uint16(tlv->len);
590
591 p += sizeof(ngx_proxy_protocol_tlv_t);
592 n -= sizeof(ngx_proxy_protocol_tlv_t);
593
594 if (n < len) {
595 ngx_log_error(NGX_LOG_ERR, c->log, 0, "broken PROXY protocol TLV");
596 return NGX_ERROR;
597 }
598
599 if (tlv->type == type) {
600 value->data = p;
601 value->len = len;
602 return NGX_OK;
603 }
604
605 p += len;
606 n -= len;
607 }
608
609 return NGX_DECLINED;
610 }