1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
10use std::str;
11
12use crate::crc32c::Crc32c;
13use crate::proxy::{ProxyError, ProxyFacts, ProxyVersions};
14
15const V1_PREFIX: &[u8] = b"PROXY ";
16const V1_MAX: usize = 107;
17const V2_SIGNATURE: [u8; 12] = [
18 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
19];
20const V2_FIXED: usize = 16;
21
22const TLV_ALPN: u8 = 0x01;
23const TLV_AUTHORITY: u8 = 0x02;
24const TLV_CRC32C: u8 = 0x03;
25const TLV_NOOP: u8 = 0x04;
26const TLV_UNIQUE_ID: u8 = 0x05;
27const TLV_SSL: u8 = 0x20;
28const SSL_VERSION: u8 = 0x21;
29const SSL_CN: u8 = 0x22;
30const SSL_CIPHER: u8 = 0x23;
31const SSL_SIG_ALG: u8 = 0x24;
32const SSL_KEY_ALG: u8 = 0x25;
33const TLV_NETNS: u8 = 0x30;
34const UNIQUE_ID_MAX: usize = 128;
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38enum Kind {
39 Undecided,
40 V1,
41 V2,
42}
43
44#[derive(Clone, Debug)]
62pub struct ProxyParser {
63 versions: ProxyVersions,
64 v2_body_max: u16,
65 kind: Kind,
66 scanned: usize,
68}
69
70#[derive(Debug)]
72pub enum ProxyProgress<'a> {
73 NeedMore {
75 at_least: usize,
77 },
78 Done {
80 header: ProxyHeader<'a>,
82 consumed: usize,
84 },
85}
86
87#[non_exhaustive]
89#[derive(Clone, Copy, Debug)]
90pub struct ProxyHeader<'a> {
91 pub version: u8,
93 pub command: ProxyCommand,
96 pub transport: ProxyTransport,
98 pub source: Option<ProxyAddress<'a>>,
100 pub destination: Option<ProxyAddress<'a>>,
102 pub tlvs: Tlvs<'a>,
104 crc_checked: bool,
105}
106
107#[non_exhaustive]
109#[derive(Clone, Copy, Debug, PartialEq, Eq)]
110pub enum ProxyCommand {
111 Proxy,
113 Local,
115}
116
117#[non_exhaustive]
119#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub enum ProxyTransport {
121 Stream,
123 Datagram,
125 Unspecified,
127}
128
129#[non_exhaustive]
131#[derive(Clone, Copy, Debug, PartialEq, Eq)]
132pub enum ProxyAddress<'a> {
133 Ip(SocketAddr),
135 Unix(&'a [u8]),
137}
138
139impl ProxyAddress<'_> {
140 #[must_use]
142 pub fn socket_addr(&self) -> Option<SocketAddr> {
143 match self {
144 ProxyAddress::Ip(a) => Some(*a),
145 ProxyAddress::Unix(_) => None,
146 }
147 }
148}
149
150impl std::fmt::Display for ProxyAddress<'_> {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 match self {
153 ProxyAddress::Ip(a) => write!(f, "{a}"),
154 ProxyAddress::Unix(p) => write!(f, "{}", String::from_utf8_lossy(p)),
155 }
156 }
157}
158
159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub struct Tlv<'a> {
162 pub kind: u8,
164 pub value: &'a [u8],
166}
167
168#[derive(Clone, Copy, Debug)]
170pub struct Tlvs<'a> {
171 rest: &'a [u8],
172}
173
174impl<'a> Iterator for Tlvs<'a> {
175 type Item = Tlv<'a>;
176
177 fn next(&mut self) -> Option<Tlv<'a>> {
178 loop {
179 let (tlv, rest) = split_tlv(self.rest)?;
180 self.rest = rest;
181 if tlv.kind != TLV_NOOP {
182 return Some(tlv);
183 }
184 }
185 }
186}
187
188#[non_exhaustive]
190#[derive(Clone, Copy, Debug)]
191pub struct ProxySsl<'a> {
192 pub client: u8,
195 pub verified: bool,
197 pub version: Option<&'a str>,
199 pub common_name: Option<&'a str>,
201 pub cipher: Option<&'a str>,
203 pub signature_algorithm: Option<&'a str>,
205 pub key_algorithm: Option<&'a str>,
207}
208
209impl<'a> ProxyHeader<'a> {
210 fn find(&self, kind: u8) -> Option<&'a [u8]> {
211 let mut tlvs = self.tlvs;
212 tlvs.find(|t| t.kind == kind).map(|t| t.value)
213 }
214
215 #[must_use]
217 pub fn alpn(&self) -> Option<&'a [u8]> {
218 self.find(TLV_ALPN)
219 }
220
221 #[must_use]
223 pub fn authority(&self) -> Option<&'a str> {
224 self.find(TLV_AUTHORITY)
225 .and_then(|v| str::from_utf8(v).ok())
226 }
227
228 #[must_use]
230 pub fn unique_id(&self) -> Option<&'a [u8]> {
231 self.find(TLV_UNIQUE_ID)
232 }
233
234 #[must_use]
236 pub fn ssl(&self) -> Option<ProxySsl<'a>> {
237 let v = self.find(TLV_SSL)?;
238 let client = v[0];
239 let verify = u32::from_be_bytes([v[1], v[2], v[3], v[4]]);
240 let mut ssl = ProxySsl {
241 client,
242 verified: verify == 0,
243 version: None,
244 common_name: None,
245 cipher: None,
246 signature_algorithm: None,
247 key_algorithm: None,
248 };
249 let mut rest = &v[5..];
250 while let Some((sub, more)) = split_tlv(rest) {
251 let text = str::from_utf8(sub.value).ok();
252 match sub.kind {
253 SSL_VERSION => ssl.version = text,
254 SSL_CN => ssl.common_name = text,
255 SSL_CIPHER => ssl.cipher = text,
256 SSL_SIG_ALG => ssl.signature_algorithm = text,
257 SSL_KEY_ALG => ssl.key_algorithm = text,
258 _ => {}
259 }
260 rest = more;
261 }
262 Some(ssl)
263 }
264
265 #[must_use]
267 pub fn network_namespace(&self) -> Option<&'a [u8]> {
268 self.find(TLV_NETNS)
269 }
270
271 #[must_use]
273 pub fn crc_checked(&self) -> bool {
274 self.crc_checked
275 }
276
277 #[must_use]
280 pub fn to_facts(&self) -> ProxyFacts {
281 ProxyFacts::from_parts(
282 self.alpn(),
283 self.authority(),
284 self.unique_id(),
285 self.ssl().map(|s| s.client),
286 )
287 }
288}
289
290impl ProxyParser {
291 #[must_use]
294 pub fn new(versions: ProxyVersions, v2_body_max: u16) -> ProxyParser {
295 ProxyParser {
296 versions,
297 v2_body_max,
298 kind: Kind::Undecided,
299 scanned: 0,
300 }
301 }
302
303 pub fn feed<'a>(&mut self, input: &'a [u8]) -> Result<ProxyProgress<'a>, ProxyError> {
309 if self.kind == Kind::Undecided {
310 let Some(&first) = input.first() else {
311 return Ok(ProxyProgress::NeedMore { at_least: 1 });
312 };
313 let v1 = matches!(self.versions, ProxyVersions::V1 | ProxyVersions::Both);
314 let v2 = matches!(self.versions, ProxyVersions::V2 | ProxyVersions::Both);
315 self.kind = match first {
316 b'P' if v1 => Kind::V1,
317 0x0D if v2 => Kind::V2,
318 _ => return Err(ProxyError::NotProxy),
319 };
320 }
321 match self.kind {
322 Kind::V1 => self.feed_v1(input),
323 _ => self.feed_v2(input),
324 }
325 }
326
327 fn feed_v1<'a>(&mut self, input: &'a [u8]) -> Result<ProxyProgress<'a>, ProxyError> {
328 let n = input.len().min(V1_PREFIX.len());
329 if input[..n] != V1_PREFIX[..n] {
330 return Err(ProxyError::NotProxy);
331 }
332 let limit = input.len().min(V1_MAX);
333 let start = self.scanned.min(limit);
334 let Some(lf) = input[start..limit].iter().position(|&b| b == b'\n') else {
335 if input.len() >= V1_MAX {
336 return Err(ProxyError::V1TooLong);
337 }
338 self.scanned = limit;
339 return Ok(ProxyProgress::NeedMore { at_least: 1 });
340 };
341 let lf = start + lf;
342 if lf == 0 || input[lf - 1] != b'\r' {
343 return Err(ProxyError::V1Syntax { at: offset(lf) });
344 }
345 let header = parse_v1_line(&input[..lf - 1])?;
346 Ok(ProxyProgress::Done {
347 header,
348 consumed: lf + 1,
349 })
350 }
351
352 fn feed_v2<'a>(&mut self, input: &'a [u8]) -> Result<ProxyProgress<'a>, ProxyError> {
353 let n = input.len().min(V2_SIGNATURE.len());
354 if input[..n] != V2_SIGNATURE[..n] {
355 return Err(ProxyError::NotProxy);
356 }
357 if input.len() < V2_FIXED {
358 return Ok(ProxyProgress::NeedMore {
359 at_least: V2_FIXED - input.len(),
360 });
361 }
362 let version = input[12] >> 4;
363 if version != 2 {
364 return Err(ProxyError::V2BadVersion);
365 }
366 let command = match input[12] & 0x0F {
367 0x0 => ProxyCommand::Local,
368 0x1 => ProxyCommand::Proxy,
369 _ => return Err(ProxyError::V2BadCommand),
370 };
371 let family = input[13];
372 let (address_len, transport) = match family {
373 0x00 => (0, ProxyTransport::Unspecified),
374 0x11 => (12, ProxyTransport::Stream),
375 0x12 => (12, ProxyTransport::Datagram),
376 0x21 => (36, ProxyTransport::Stream),
377 0x22 => (36, ProxyTransport::Datagram),
378 0x31 => (216, ProxyTransport::Stream),
379 0x32 => (216, ProxyTransport::Datagram),
380 _ => return Err(ProxyError::V2BadFamily),
381 };
382 let declared = u16::from_be_bytes([input[14], input[15]]);
383 if declared > self.v2_body_max {
384 return Err(ProxyError::V2LengthTooLarge {
385 declared,
386 max: self.v2_body_max,
387 });
388 }
389 let total = V2_FIXED + usize::from(declared);
390 if input.len() < total {
391 return Ok(ProxyProgress::NeedMore {
392 at_least: total - input.len(),
393 });
394 }
395 let header = &input[..total];
396 let body = &header[V2_FIXED..];
397 if body.len() < address_len {
398 return Err(ProxyError::V2AddressTooShort);
399 }
400 let (source, destination) = if command == ProxyCommand::Proxy {
401 v2_addresses(family >> 4, &body[..address_len])
402 } else {
403 (None, None)
404 };
405 let tlv_bytes = &body[address_len..];
406 let crc_checked = check_tlvs(header, V2_FIXED + address_len)?;
407 Ok(ProxyProgress::Done {
408 header: ProxyHeader {
409 version: 2,
410 command,
411 transport,
412 source,
413 destination,
414 tlvs: Tlvs { rest: tlv_bytes },
415 crc_checked,
416 },
417 consumed: total,
418 })
419 }
420}
421
422fn offset(at: usize) -> u8 {
424 u8::try_from(at).unwrap_or(u8::MAX)
425}
426
427fn split_tlv(bytes: &[u8]) -> Option<(Tlv<'_>, &[u8])> {
429 if bytes.len() < 3 {
430 return None;
431 }
432 let len = usize::from(u16::from_be_bytes([bytes[1], bytes[2]]));
433 let value = bytes.get(3..3 + len)?;
434 Some((
435 Tlv {
436 kind: bytes[0],
437 value,
438 },
439 &bytes[3 + len..],
440 ))
441}
442
443fn check_tlvs(header: &[u8], start: usize) -> Result<bool, ProxyError> {
447 let mut pos = start;
448 let mut crc_checked = false;
449 while pos < header.len() {
450 let rest = &header[pos..];
451 let Some((tlv, _)) = split_tlv(rest) else {
452 return Err(ProxyError::V2TlvOverrun);
453 };
454 let value_at = pos + 3;
455 match tlv.kind {
456 TLV_CRC32C => {
457 if tlv.value.len() != 4 {
458 return Err(ProxyError::V2CrcMismatch);
459 }
460 let expected =
461 u32::from_be_bytes([tlv.value[0], tlv.value[1], tlv.value[2], tlv.value[3]]);
462 let mut c = Crc32c::new();
463 c.update(&header[..value_at]);
464 c.update(&[0; 4]);
465 c.update(&header[value_at + 4..]);
466 if c.finish() != expected {
467 return Err(ProxyError::V2CrcMismatch);
468 }
469 crc_checked = true;
470 }
471 TLV_UNIQUE_ID if tlv.value.len() > UNIQUE_ID_MAX => {
472 return Err(ProxyError::V2UniqueIdTooLong);
473 }
474 TLV_SSL => check_ssl(tlv.value)?,
475 _ => {}
476 }
477 pos = value_at + tlv.value.len();
478 }
479 Ok(crc_checked)
480}
481
482fn check_ssl(value: &[u8]) -> Result<(), ProxyError> {
483 if value.len() < 5 {
484 return Err(ProxyError::V2SslMalformed);
485 }
486 let mut rest = &value[5..];
487 while !rest.is_empty() {
488 match split_tlv(rest) {
489 Some((_, more)) => rest = more,
490 None => return Err(ProxyError::V2SslMalformed),
491 }
492 }
493 Ok(())
494}
495
496fn v2_addresses(family: u8, block: &[u8]) -> (Option<ProxyAddress<'_>>, Option<ProxyAddress<'_>>) {
497 let port = |b: &[u8]| u16::from_be_bytes([b[0], b[1]]);
498 match family {
499 0x1 => {
500 let src = Ipv4Addr::new(block[0], block[1], block[2], block[3]);
501 let dst = Ipv4Addr::new(block[4], block[5], block[6], block[7]);
502 (
503 Some(ProxyAddress::Ip(SocketAddr::new(
504 IpAddr::V4(src),
505 port(&block[8..]),
506 ))),
507 Some(ProxyAddress::Ip(SocketAddr::new(
508 IpAddr::V4(dst),
509 port(&block[10..]),
510 ))),
511 )
512 }
513 0x2 => {
514 let mut s = [0u8; 16];
515 let mut d = [0u8; 16];
516 s.copy_from_slice(&block[..16]);
517 d.copy_from_slice(&block[16..32]);
518 (
519 Some(ProxyAddress::Ip(SocketAddr::new(
520 IpAddr::V6(Ipv6Addr::from(s)),
521 port(&block[32..]),
522 ))),
523 Some(ProxyAddress::Ip(SocketAddr::new(
524 IpAddr::V6(Ipv6Addr::from(d)),
525 port(&block[34..]),
526 ))),
527 )
528 }
529 0x3 => (
530 Some(ProxyAddress::Unix(trim_zeros(&block[..108]))),
531 Some(ProxyAddress::Unix(trim_zeros(&block[108..216]))),
532 ),
533 _ => (None, None),
534 }
535}
536
537fn trim_zeros(path: &[u8]) -> &[u8] {
538 let end = path.iter().rposition(|&b| b != 0).map_or(0, |i| i + 1);
539 &path[..end]
540}
541
542fn parse_v1_line(line: &[u8]) -> Result<ProxyHeader<'static>, ProxyError> {
544 let rest = &line[V1_PREFIX.len()..];
545 let base = V1_PREFIX.len();
546 let empty = Tlvs { rest: &[] };
547 if let Some(after) = rest.strip_prefix(b"UNKNOWN") {
548 if after.is_empty() || after[0] == b' ' {
550 return Ok(ProxyHeader {
551 version: 1,
552 command: ProxyCommand::Proxy,
553 transport: ProxyTransport::Unspecified,
554 source: None,
555 destination: None,
556 tlvs: empty,
557 crc_checked: false,
558 });
559 }
560 return Err(ProxyError::V1Syntax {
561 at: offset(base + 7),
562 });
563 }
564 let mut fields = [&[][..]; 5];
565 let mut count = 0;
566 let mut at = base;
567 for field in rest.split(|&b| b == b' ') {
568 if field.is_empty() || count == 5 {
569 return Err(ProxyError::V1Syntax { at: offset(at) });
570 }
571 fields[count] = field;
572 count += 1;
573 at += field.len() + 1;
574 }
575 if count != 5 {
576 return Err(ProxyError::V1Syntax {
577 at: offset(line.len()),
578 });
579 }
580 let v6 = match fields[0] {
581 b"TCP4" => false,
582 b"TCP6" => true,
583 _ => return Err(ProxyError::V1Syntax { at: offset(base) }),
584 };
585 let address = |text: &[u8]| -> Result<IpAddr, ProxyError> {
586 let (mine, other) = if v6 {
587 (
588 parse_ipv6(text).map(IpAddr::V6),
589 parse_ipv4(text).map(IpAddr::V4),
590 )
591 } else {
592 (
593 parse_ipv4(text).map(IpAddr::V4),
594 parse_ipv6(text).map(IpAddr::V6),
595 )
596 };
597 match (mine, other) {
598 (Some(ip), _) => Ok(ip),
599 (None, Some(_)) => Err(ProxyError::FamilyMismatch),
600 (None, None) => Err(ProxyError::V1BadAddress),
601 }
602 };
603 let src = address(fields[1])?;
604 let dst = address(fields[2])?;
605 let sport = parse_port(fields[3]).ok_or(ProxyError::V1BadPort)?;
606 let dport = parse_port(fields[4]).ok_or(ProxyError::V1BadPort)?;
607 Ok(ProxyHeader {
608 version: 1,
609 command: ProxyCommand::Proxy,
610 transport: ProxyTransport::Stream,
611 source: Some(ProxyAddress::Ip(SocketAddr::new(src, sport))),
612 destination: Some(ProxyAddress::Ip(SocketAddr::new(dst, dport))),
613 tlvs: empty,
614 crc_checked: false,
615 })
616}
617
618fn parse_port(text: &[u8]) -> Option<u16> {
620 decimal(text, 5).and_then(|v| u16::try_from(v).ok())
621}
622
623fn decimal(text: &[u8], max_digits: usize) -> Option<u32> {
625 if text.is_empty() || text.len() > max_digits || (text.len() > 1 && text[0] == b'0') {
626 return None;
627 }
628 text.iter().try_fold(0u32, |acc, &b| {
629 b.is_ascii_digit().then(|| acc * 10 + u32::from(b - b'0'))
630 })
631}
632
633fn parse_ipv4(text: &[u8]) -> Option<Ipv4Addr> {
635 let mut octets = [0u8; 4];
636 let mut n = 0;
637 for part in text.split(|&b| b == b'.') {
638 if n == 4 {
639 return None;
640 }
641 octets[n] = u8::try_from(decimal(part, 3)?).ok()?;
642 n += 1;
643 }
644 (n == 4).then(|| Ipv4Addr::from(octets))
645}
646
647fn parse_ipv6(text: &[u8]) -> Option<Ipv6Addr> {
651 let (head, tail, compressed) = match find_double_colon(text) {
652 Some(i) => (&text[..i], &text[i + 2..], true),
653 None => (text, &[][..], false),
654 };
655 if compressed && find_double_colon(tail).is_some() {
656 return None;
657 }
658 let mut groups = [0u16; 8];
659 let front = groups_into(head, &mut groups, 0, !compressed)?;
661 if !compressed {
662 return (front == 8).then(|| Ipv6Addr::from(groups));
663 }
664 let mut back = [0u16; 8];
665 let n_back = groups_into(tail, &mut back, 0, true)?;
666 if front + n_back > 7 {
667 return None;
668 }
669 groups[8 - n_back..].copy_from_slice(&back[..n_back]);
670 Some(Ipv6Addr::from(groups))
671}
672
673fn find_double_colon(text: &[u8]) -> Option<usize> {
674 text.windows(2).position(|w| w == b"::")
675}
676
677fn groups_into(text: &[u8], out: &mut [u16; 8], mut at: usize, last: bool) -> Option<usize> {
681 if text.is_empty() {
682 return Some(at);
683 }
684 let mut parts = text.split(|&b| b == b':').peekable();
685 while let Some(part) = parts.next() {
686 let is_last = parts.peek().is_none();
687 if is_last && last && part.contains(&b'.') {
688 let v4 = parse_ipv4(part)?.octets();
689 if at + 2 > 8 {
690 return None;
691 }
692 out[at] = u16::from_be_bytes([v4[0], v4[1]]);
693 out[at + 1] = u16::from_be_bytes([v4[2], v4[3]]);
694 at += 2;
695 continue;
696 }
697 if part.is_empty() || part.len() > 4 || at >= 8 {
698 return None;
699 }
700 let mut v = 0u16;
701 for &b in part {
702 let d = (b as char).to_digit(16)?;
703 v = (v << 4) | u16::try_from(d).ok()?;
704 }
705 out[at] = v;
706 at += 1;
707 }
708 Some(at)
709}
710
711#[cfg(test)]
712mod tests {
713 use super::*;
714
715 fn done(p: &mut ProxyParser, bytes: &[u8]) -> (ProxyHeader<'static>, usize) {
716 let bytes: &'static [u8] = Box::leak(bytes.to_vec().into_boxed_slice());
717 match p.feed(bytes).unwrap() {
718 ProxyProgress::Done { header, consumed } => (header, consumed),
719 ProxyProgress::NeedMore { at_least } => panic!("need {at_least} more"),
720 }
721 }
722
723 fn v1(line: &str) -> Result<ProxyHeader<'static>, ProxyError> {
724 let bytes: &'static [u8] = Box::leak(line.as_bytes().to_vec().into_boxed_slice());
725 match ProxyParser::new(ProxyVersions::Both, 1024).feed(bytes)? {
726 ProxyProgress::Done { header, .. } => Ok(header),
727 ProxyProgress::NeedMore { .. } => panic!("incomplete: {line:?}"),
728 }
729 }
730
731 fn v2(command: u8, family: u8, block: &[u8], tlvs: &[(u8, &[u8])], crc: bool) -> Vec<u8> {
733 let mut body = block.to_vec();
734 for (kind, value) in tlvs {
735 body.push(*kind);
736 body.extend_from_slice(&u16::try_from(value.len()).unwrap().to_be_bytes());
737 body.extend_from_slice(value);
738 }
739 let crc_at = if crc {
740 body.extend_from_slice(&[TLV_CRC32C, 0, 4, 0, 0, 0, 0]);
741 Some(V2_FIXED + body.len() - 4)
742 } else {
743 None
744 };
745 let mut h = V2_SIGNATURE.to_vec();
746 h.push(0x20 | command);
747 h.push(family);
748 h.extend_from_slice(&u16::try_from(body.len()).unwrap().to_be_bytes());
749 h.extend_from_slice(&body);
750 if let Some(at) = crc_at {
751 let sum = crate::crc32c::crc32c(&h);
752 h[at..at + 4].copy_from_slice(&sum.to_be_bytes());
753 }
754 h
755 }
756
757 fn ipv4_block() -> Vec<u8> {
758 let mut b = vec![192, 0, 2, 1, 198, 51, 100, 2];
759 b.extend_from_slice(&51000u16.to_be_bytes());
760 b.extend_from_slice(&443u16.to_be_bytes());
761 b
762 }
763
764 #[test]
765 fn test_v1_tcp4_and_rest_is_data() {
766 let mut p = ProxyParser::new(ProxyVersions::Both, 1024);
767 let (h, consumed) = done(
768 &mut p,
769 b"PROXY TCP4 192.0.2.1 198.51.100.2 51000 443\r\nGET",
770 );
771 assert_eq!(h.version, 1);
772 assert_eq!(
773 h.source,
774 Some(ProxyAddress::Ip("192.0.2.1:51000".parse().unwrap()))
775 );
776 assert_eq!(
777 h.destination,
778 Some(ProxyAddress::Ip("198.51.100.2:443".parse().unwrap()))
779 );
780 assert_eq!(consumed, 45);
781 }
782
783 #[test]
784 fn test_v1_tcp6_unknown_and_mapped() {
785 let h = v1("PROXY TCP6 2001:db8::1 ::ffff:192.0.2.1 1 65535\r\n").unwrap();
786 assert_eq!(h.source.unwrap().to_string(), "[2001:db8::1]:1");
787 let h = v1("PROXY UNKNOWN\r\n").unwrap();
788 assert!(h.source.is_none());
789 let h = v1("PROXY UNKNOWN anything at all 1 2\r\n").unwrap();
790 assert_eq!(h.transport, ProxyTransport::Unspecified);
791 }
792
793 #[test]
794 fn test_v1_strict_grammar() {
795 use ProxyError::*;
796 let bad = [
797 ("PROXY TCP4 192.0.2.1 198.51.100.2 1 2\r\n", "double space"),
798 (
799 "PROXY TCP4 192.0.2.1 198.51.100.2 1 2 \r\n",
800 "trailing space",
801 ),
802 ("PROXY TCP4 192.0.2.1 198.51.100.2 1\r\n", "missing port"),
803 ("PROXY TCP5 192.0.2.1 198.51.100.2 1 2\r\n", "protocol"),
804 ("PROXY UNKNOWNX\r\n", "unknown suffix"),
805 ];
806 for (line, why) in bad {
807 assert!(
808 matches!(v1(line), Err(V1Syntax { .. })),
809 "{why}: {:?}",
810 v1(line)
811 );
812 }
813 assert_eq!(
814 v1("PROXY TCP4 192.0.2.01 198.51.100.2 1 2\r\n").unwrap_err(),
815 V1BadAddress
816 );
817 assert_eq!(
818 v1("PROXY TCP4 256.0.2.1 198.51.100.2 1 2\r\n").unwrap_err(),
819 V1BadAddress
820 );
821 assert_eq!(
822 v1("PROXY TCP4 192.0.2.1 198.51.100.2 01 2\r\n").unwrap_err(),
823 V1BadPort
824 );
825 assert_eq!(
826 v1("PROXY TCP4 192.0.2.1 198.51.100.2 +1 2\r\n").unwrap_err(),
827 V1BadPort
828 );
829 assert_eq!(
830 v1("PROXY TCP4 192.0.2.1 198.51.100.2 65536 2\r\n").unwrap_err(),
831 V1BadPort
832 );
833 assert_eq!(
834 v1("PROXY TCP4 2001:db8::1 198.51.100.2 1 2\r\n").unwrap_err(),
835 FamilyMismatch
836 );
837 assert_eq!(
838 v1("PROXY TCP6 192.0.2.1 ::1 1 2\r\n").unwrap_err(),
839 FamilyMismatch
840 );
841 assert!(matches!(
842 ProxyParser::new(ProxyVersions::Both, 1024).feed(b"PROXY TCP4 1.2.3.4 1.2.3.4 1 2\n"),
843 Err(V1Syntax { .. })
844 ));
845 }
846
847 #[test]
849 fn test_v1_too_long() {
850 let mut line = b"PROXY UNKNOWN ".to_vec();
851 line.resize(107, b'x');
852 let r = ProxyParser::new(ProxyVersions::V1, 1024).feed(&line);
853 assert_eq!(r.unwrap_err(), ProxyError::V1TooLong);
854 let mut ok = b"PROXY UNKNOWN ".to_vec();
855 ok.resize(105, b'x');
856 ok.extend_from_slice(b"\r\n");
857 assert!(matches!(
858 ProxyParser::new(ProxyVersions::V1, 1024).feed(&ok),
859 Ok(ProxyProgress::Done { consumed: 107, .. })
860 ));
861 }
862
863 #[test]
864 fn test_not_proxy_and_version_filters() {
865 let mut p = ProxyParser::new(ProxyVersions::Both, 1024);
866 assert_eq!(p.feed(b"GET / HTTP/1.1").unwrap_err(), ProxyError::NotProxy);
867 assert_eq!(
868 ProxyParser::new(ProxyVersions::Both, 1024)
869 .feed(b"PROXX")
870 .unwrap_err(),
871 ProxyError::NotProxy
872 );
873 let v2h = v2(1, 0x11, &ipv4_block(), &[], false);
874 assert_eq!(
875 ProxyParser::new(ProxyVersions::V1, 1024)
876 .feed(&v2h)
877 .unwrap_err(),
878 ProxyError::NotProxy
879 );
880 assert_eq!(
881 ProxyParser::new(ProxyVersions::V2, 1024)
882 .feed(b"PROXY TCP4")
883 .unwrap_err(),
884 ProxyError::NotProxy
885 );
886 }
887
888 #[test]
889 fn test_v2_ipv4_tlvs_and_crc() {
890 let h = v2(
891 1,
892 0x11,
893 &ipv4_block(),
894 &[
895 (TLV_ALPN, b"h2"),
896 (TLV_NOOP, b"pad"),
897 (TLV_AUTHORITY, b"example.com"),
898 (TLV_UNIQUE_ID, b"id-1"),
899 (
900 TLV_SSL,
901 &[
902 0x07,
903 0,
904 0,
905 0,
906 0,
907 SSL_VERSION,
908 0,
909 7,
910 b'T',
911 b'L',
912 b'S',
913 b'v',
914 b'1',
915 b'.',
916 b'3',
917 SSL_CN,
918 0,
919 3,
920 b'b',
921 b'o',
922 b'b',
923 ],
924 ),
925 (0xE0, b"custom"),
926 ],
927 true,
928 );
929 let mut p = ProxyParser::new(ProxyVersions::Both, 1024);
930 let (header, consumed) = done(&mut p, &h);
931 assert_eq!(consumed, h.len());
932 assert_eq!(header.command, ProxyCommand::Proxy);
933 assert_eq!(header.source.unwrap().to_string(), "192.0.2.1:51000");
934 assert_eq!(header.alpn(), Some(&b"h2"[..]));
935 assert_eq!(header.authority(), Some("example.com"));
936 assert_eq!(header.unique_id(), Some(&b"id-1"[..]));
937 assert!(header.crc_checked());
938 let ssl = header.ssl().unwrap();
939 assert_eq!(
940 (ssl.client, ssl.verified, ssl.version, ssl.common_name),
941 (7, true, Some("TLSv1.3"), Some("bob"))
942 );
943 assert!({ header.tlvs }.all(|t| t.kind != TLV_NOOP), "NOOP skipped");
944 assert!({ header.tlvs }.any(|t| t.kind == 0xE0 && t.value == b"custom"));
945 let facts = header.to_facts();
946 assert_eq!(facts.alpn(), Some(&b"h2"[..]));
947 assert_eq!(facts.authority(), Some("example.com"));
948 assert_eq!(facts.ssl_client(), Some(7));
949 }
950
951 #[test]
952 fn test_v2_ipv6_unix_local_unspec() {
953 let mut block = vec![0u8; 36];
954 block[15] = 1;
955 block[31] = 2;
956 block[32..34].copy_from_slice(&80u16.to_be_bytes());
957 let h = v2(1, 0x21, &block, &[], false);
958 let (hd, _) = done(&mut ProxyParser::new(ProxyVersions::V2, 1024), &h);
959 assert_eq!(hd.source.unwrap().to_string(), "[::1]:80");
960 let mut unix = vec![0u8; 216];
961 unix[..9].copy_from_slice(b"/run/a.sk");
962 let h = v2(1, 0x31, &unix, &[], false);
963 let (hd, _) = done(&mut ProxyParser::new(ProxyVersions::V2, 1024), &h);
964 assert_eq!(hd.source, Some(ProxyAddress::Unix(b"/run/a.sk")));
965 let h = v2(0, 0x11, &ipv4_block(), &[], false);
966 let (hd, _) = done(&mut ProxyParser::new(ProxyVersions::V2, 1024), &h);
967 assert_eq!((hd.command, hd.source), (ProxyCommand::Local, None));
968 let h = v2(1, 0x00, &[], &[], false);
969 let (hd, _) = done(&mut ProxyParser::new(ProxyVersions::V2, 1024), &h);
970 assert_eq!(
971 (hd.transport, hd.source),
972 (ProxyTransport::Unspecified, None)
973 );
974 }
975
976 #[test]
977 fn test_v2_errors() {
978 use ProxyError::*;
979 let feed = |h: &[u8]| ProxyParser::new(ProxyVersions::V2, 64).feed(h).map(|_| ());
980 let mut h = v2(1, 0x11, &ipv4_block(), &[], false);
981 h[12] = 0x11;
982 assert_eq!(feed(&h).unwrap_err(), V2BadVersion);
983 let mut h = v2(1, 0x11, &ipv4_block(), &[], false);
984 h[12] = 0x22;
985 assert_eq!(feed(&h).unwrap_err(), V2BadCommand);
986 let mut h = v2(1, 0x11, &ipv4_block(), &[], false);
987 h[13] = 0x13;
988 assert_eq!(feed(&h).unwrap_err(), V2BadFamily);
989 let big = v2(1, 0x11, &ipv4_block(), &[(0xE0, &[0u8; 100])], false);
990 assert_eq!(
991 feed(&big).unwrap_err(),
992 V2LengthTooLarge {
993 declared: 115,
994 max: 64
995 }
996 );
997 let short = v2(1, 0x21, &[0u8; 20], &[], false);
998 assert_eq!(feed(&short).unwrap_err(), V2AddressTooShort);
999 let mut over = v2(1, 0x11, &ipv4_block(), &[(0xE0, b"abc")], false);
1000 let n = over.len();
1001 over[n - 4] = 9; assert_eq!(feed(&over).unwrap_err(), V2TlvOverrun);
1003 let mut crc = v2(1, 0x11, &ipv4_block(), &[(TLV_ALPN, b"h2")], true);
1004 let n = crc.len();
1005 crc[n - 1] ^= 1;
1006 assert_eq!(feed(&crc).unwrap_err(), V2CrcMismatch);
1007 let long_id = vec![b'i'; 129];
1008 let h = v2(1, 0x11, &ipv4_block(), &[(TLV_UNIQUE_ID, &long_id)], false);
1009 assert_eq!(
1010 ProxyParser::new(ProxyVersions::V2, 1024)
1011 .feed(&h)
1012 .map(|_| ())
1013 .unwrap_err(),
1014 V2UniqueIdTooLong
1015 );
1016 let h = v2(1, 0x11, &ipv4_block(), &[(TLV_SSL, &[1, 0, 0])], false);
1017 assert_eq!(feed(&h).unwrap_err(), V2SslMalformed);
1018 }
1019
1020 #[test]
1022 fn test_v2_split_into_segments_waits_then_succeeds() {
1023 let mut h = v2(
1024 1,
1025 0x11,
1026 &ipv4_block(),
1027 &[(TLV_AUTHORITY, b"a.example")],
1028 true,
1029 );
1030 h.extend_from_slice(b"DATA");
1031 let total = h.len() - 4;
1032 let mut p = ProxyParser::new(ProxyVersions::Both, 1024);
1033 let step = h.len().div_ceil(12);
1034 let mut have = 0;
1035 loop {
1036 have = (have + step).min(h.len());
1037 match p.feed(&h[..have]).unwrap() {
1038 ProxyProgress::NeedMore { at_least } => assert!(at_least > 0 && have < h.len()),
1039 ProxyProgress::Done { consumed, .. } => {
1040 assert_eq!(consumed, total);
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
1047 #[test]
1050 fn test_second_header_is_data() {
1051 let two = b"PROXY UNKNOWN\r\nPROXY UNKNOWN\r\n";
1052 let mut p = ProxyParser::new(ProxyVersions::V1, 1024);
1053 let (_, consumed) = done(&mut p, two);
1054 assert_eq!(&two[consumed..], b"PROXY UNKNOWN\r\n");
1055 }
1056
1057 #[test]
1059 fn prop_every_split_point_agrees() {
1060 let headers: Vec<Vec<u8>> = vec![
1061 b"PROXY TCP6 2001:db8:0:0:1:0:0:1 ::ffff:10.0.0.1 1024 8080\r\n".to_vec(),
1062 v2(
1063 1,
1064 0x11,
1065 &ipv4_block(),
1066 &[(TLV_ALPN, b"http/1.1"), (TLV_UNIQUE_ID, b"u")],
1067 true,
1068 ),
1069 ];
1070 for h in headers {
1071 for split in 0..h.len() {
1072 let mut p = ProxyParser::new(ProxyVersions::Both, 1024);
1073 if split > 0 {
1074 assert!(
1075 matches!(p.feed(&h[..split]).unwrap(), ProxyProgress::NeedMore { .. }),
1076 "split {split}"
1077 );
1078 }
1079 match p.feed(&h).unwrap() {
1080 ProxyProgress::Done { consumed, .. } => assert_eq!(consumed, h.len()),
1081 ProxyProgress::NeedMore { .. } => {
1082 panic!("whole header incomplete at split {split}")
1083 }
1084 }
1085 }
1086 }
1087 }
1088
1089 #[test]
1091 fn prop_random_input_never_panics() {
1092 use crate::testing::Gen;
1093 let mut g = Gen::new(0x9F0C_7E11);
1094 for _ in 0..if cfg!(miri) { 200 } else { 50_000 } {
1095 let len = g.below(300) as usize;
1096 let mut bytes: Vec<u8> = (0..len).map(|_| g.next_u64() as u8).collect();
1097 match g.below(3) {
1098 0 if len >= 12 => bytes[..12].copy_from_slice(&V2_SIGNATURE),
1099 1 if len >= 6 => bytes[..6].copy_from_slice(V1_PREFIX),
1100 _ => {}
1101 }
1102 let mut p = ProxyParser::new(ProxyVersions::Both, u16::MAX);
1103 if let Ok(ProxyProgress::Done { consumed, header }) = p.feed(&bytes) {
1104 assert!(consumed <= bytes.len());
1105 let _ = (header.alpn(), header.ssl(), header.tlvs.count());
1106 }
1107 }
1108 }
1109
1110 #[test]
1113 fn prop_ipv6_grammar_matches_std() {
1114 use crate::testing::Gen;
1115 let mut g = Gen::new(0x1FE6_0001);
1116 let alphabet = b"0123456789abcdefABCDEF:.";
1117 for _ in 0..if cfg!(miri) { 200 } else { 100_000 } {
1118 let len = 1 + g.below(40) as usize;
1119 let text: Vec<u8> = (0..len)
1120 .map(|_| alphabet[g.below(alphabet.len() as u64) as usize])
1121 .collect();
1122 if let Some(ours) = parse_ipv6(&text) {
1123 let s = str::from_utf8(&text).unwrap();
1124 assert_eq!(s.parse::<Ipv6Addr>().ok(), Some(ours), "{s}");
1125 }
1126 }
1127 for _ in 0..if cfg!(miri) { 200 } else { 20_000 } {
1128 let mut b = [0u8; 16];
1129 for x in &mut b {
1130 *x = if g.chance(2) { 0 } else { g.next_u64() as u8 };
1132 }
1133 let a = Ipv6Addr::from(b);
1134 assert_eq!(parse_ipv6(a.to_string().as_bytes()), Some(a), "{a}");
1135 }
1136 for (s, ok) in [
1137 ("::", true),
1138 ("::1", true),
1139 ("1::", true),
1140 ("1:2:3:4:5:6:7:8", true),
1141 ("1:2:3:4:5:6:7::", true),
1142 ("1:2:3:4:5:6:1.2.3.4", true),
1143 (":1", false),
1144 ("1:", false),
1145 ("1:::2", false),
1146 ("1::2::3", false),
1147 ("1:2:3:4:5:6:7:8:9", false),
1148 ("12345::", false),
1149 ("::1.2.3", false),
1150 ("fe80::1%eth0", false),
1151 ] {
1152 assert_eq!(parse_ipv6(s.as_bytes()).is_some(), ok, "{s}");
1153 }
1154 }
1155
1156 #[test]
1157 fn test_ipv4_grammar() {
1158 for (s, ok) in [
1159 ("0.0.0.0", true),
1160 ("255.255.255.255", true),
1161 ("1.2.3.04", false),
1162 ("1.2.3", false),
1163 ("1.2.3.4.5", false),
1164 ("1.2.3.256", false),
1165 ("1..3.4", false),
1166 (" 1.2.3.4", false),
1167 ] {
1168 assert_eq!(parse_ipv4(s.as_bytes()).is_some(), ok, "{s}");
1169 }
1170 }
1171}