1use crate::config::TcpAddressInfo;
2use haproxy_protocol::{ProxyHdrV1, ProxyHdrV2, RemoteAddress};
3use std::io::ErrorKind;
4use std::net::SocketAddr;
5use std::sync::Arc;
6use std::time::Duration;
7use tokio::{net::TcpStream, time::timeout};
8
9pub(crate) async fn process_client_addr(
10 stream: TcpStream,
11 connection_addr: SocketAddr,
12 time_limit: Duration,
13 trusted_tcp_info_ips: Arc<TcpAddressInfo>,
14) -> Result<(TcpStream, SocketAddr), std::io::Error> {
15 let canonical_conn_addr = connection_addr.ip().to_canonical();
16
17 let hdr_result = match trusted_tcp_info_ips.as_ref() {
18 TcpAddressInfo::ProxyV2(trusted)
19 if trusted
20 .iter()
21 .any(|ip_cidr| ip_cidr.contains(&canonical_conn_addr)) =>
22 {
23 timeout(time_limit, ProxyHdrV2::parse_from_read(stream))
24 .await
25 .map(|ok_result| ok_result.map(|(stream, hdr)| (stream, hdr.to_remote_addr())))
26 }
27 TcpAddressInfo::ProxyV1(trusted)
28 if trusted
29 .iter()
30 .any(|ip_cidr| ip_cidr.contains(&canonical_conn_addr)) =>
31 {
32 timeout(time_limit, ProxyHdrV1::parse_from_read(stream))
33 .await
34 .map(|ok_result| ok_result.map(|(stream, hdr)| (stream, hdr.to_remote_addr())))
35 }
36 TcpAddressInfo::ProxyV2(_) | TcpAddressInfo::ProxyV1(_) | TcpAddressInfo::None => {
37 return Ok((stream, connection_addr))
38 }
39 };
40
41 match hdr_result {
42 Ok(Ok((stream, remote_addr))) => {
43 let remote_socket_addr = match remote_addr {
44 RemoteAddress::Local => {
45 debug!("PROXY protocol liveness check - will not contain client data");
46 connection_addr
48 }
49 RemoteAddress::TcpV4 { src, dst: _ } => SocketAddr::from(src),
50 RemoteAddress::TcpV6 { src, dst: _ } => SocketAddr::from(src),
51 remote_addr => {
52 error!(?remote_addr, "remote address in proxy header is invalid");
53 return Err(std::io::Error::from(ErrorKind::ConnectionAborted));
54 }
55 };
56
57 Ok((stream, remote_socket_addr))
58 }
59 Ok(Err(err)) => {
60 error!(?connection_addr, ?err, "Unable to process proxy header");
61 Err(std::io::Error::from(ErrorKind::ConnectionAborted))
62 }
63 Err(_) => {
64 error!(?connection_addr, "Timeout receiving proxy header");
65 Err(std::io::Error::from(ErrorKind::TimedOut))
66 }
67 }
68}