kanidmd_core/
tcp.rs

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                    // This is a check from the proxy, so just use the connection address.
47                    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}