zebra_network/meta_addr/
peer_addr.rs

1//! Wrappers for peer addresses which hide sensitive user and node operator details in logs and
2//! metrics.
3
4use std::{
5    fmt,
6    net::{Ipv4Addr, SocketAddr},
7    ops::{Deref, DerefMut},
8    str::FromStr,
9};
10
11#[cfg(any(test, feature = "proptest-impl"))]
12use proptest_derive::Arbitrary;
13
14/// A thin wrapper for [`SocketAddr`] which hides peer IP addresses in logs and metrics.
15#[derive(
16    Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
17)]
18#[serde(transparent)]
19#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
20pub struct PeerSocketAddr(SocketAddr);
21
22impl fmt::Debug for PeerSocketAddr {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        fmt::Display::fmt(self, f)
25    }
26}
27
28impl fmt::Display for PeerSocketAddr {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        let ip_version = if self.is_ipv4() { "v4" } else { "v6" };
31
32        // The port is usually not sensitive, and it's useful for debugging.
33        f.pad(&format!("{}redacted:{}", ip_version, self.port()))
34    }
35}
36
37impl FromStr for PeerSocketAddr {
38    type Err = <SocketAddr as FromStr>::Err;
39
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        Ok(Self(s.parse()?))
42    }
43}
44
45impl<S> From<S> for PeerSocketAddr
46where
47    S: Into<SocketAddr>,
48{
49    fn from(value: S) -> Self {
50        Self(value.into())
51    }
52}
53
54impl Deref for PeerSocketAddr {
55    type Target = SocketAddr;
56
57    fn deref(&self) -> &Self::Target {
58        &self.0
59    }
60}
61
62impl DerefMut for PeerSocketAddr {
63    fn deref_mut(&mut self) -> &mut Self::Target {
64        &mut self.0
65    }
66}
67
68impl PeerSocketAddr {
69    /// Returns an unspecified `PeerSocketAddr`, which can't be used for outbound connections.
70    pub fn unspecified() -> Self {
71        Self(SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0))
72    }
73
74    /// Return the underlying [`SocketAddr`], which allows sensitive peer address information to
75    /// be printed and logged.
76    pub fn remove_socket_addr_privacy(&self) -> SocketAddr {
77        **self
78    }
79}