Mercurial > hg > nginx
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 } |