hopr_network_types/
addr.rs1use std::{net::IpAddr, sync::atomic::AtomicBool};
2
3use lazy_static::lazy_static;
4use multiaddr::Multiaddr;
5
6lazy_static! {
7 pub(crate) static ref ALLOW_PRIVATE_ADDRESSES: AtomicBool =
8 std::env::var("HOPR_INTERNAL_TRANSPORT_ACCEPT_PRIVATE_NETWORK_IP_ADDRESSES")
9 .map(|v| v.to_lowercase() == "true")
10 .unwrap_or_default()
11 .into();
12}
13
14pub fn is_public(ip_addr: IpAddr) -> bool {
20 match ip_addr {
21 IpAddr::V4(ip) => !ip.is_unspecified() && !ip.is_private() && !ip.is_loopback() && !ip.is_link_local(),
22 IpAddr::V6(ip) => {
23 !ip.is_unspecified() && !ip.is_loopback() && !ip.is_unicast_link_local() && !ip.is_unique_local()
24 }
25 }
26}
27
28#[inline]
29fn is_allowed_for_transport(ip_addr: IpAddr) -> bool {
30 ALLOW_PRIVATE_ADDRESSES.load(std::sync::atomic::Ordering::SeqCst) || is_public(ip_addr)
31}
32
33pub fn is_public_address(addr: &Multiaddr) -> bool {
39 addr.iter().all(|protocol| match protocol {
40 multiaddr::Protocol::Ip4(ip) => is_allowed_for_transport(ip.into()),
41 multiaddr::Protocol::Ip6(ip) => is_allowed_for_transport(ip.into()),
42 _ => true,
43 })
44}
45
46#[cfg(test)]
47mod tests {
48 use std::str::FromStr;
49
50 use super::*;
51
52 #[inline]
53 fn override_allow_private_addresses(value: bool) {
54 ALLOW_PRIVATE_ADDRESSES.store(value, std::sync::atomic::Ordering::SeqCst);
55 }
56
57 #[inline]
58 fn get_allow_private_addresses() -> bool {
59 ALLOW_PRIVATE_ADDRESSES.load(std::sync::atomic::Ordering::SeqCst)
60 }
61
62 #[test]
63 #[serial_test::serial] fn test_is_public_address_ipv4() -> anyhow::Result<()> {
65 override_allow_private_addresses(false);
66 assert!(!get_allow_private_addresses());
67
68 assert!(is_public_address(&Multiaddr::from_str("/ip4/8.8.8.8")?));
70 assert!(is_public_address(&Multiaddr::from_str("/ip4/1.1.1.1")?));
71 assert!(is_public_address(&Multiaddr::from_str("/ip4/104.16.0.0")?));
72
73 assert!(!is_public_address(&Multiaddr::from_str("/ip4/192.168.0.1")?));
75 assert!(!is_public_address(&Multiaddr::from_str("/ip4/192.168.1.254")?));
76 assert!(!is_public_address(&Multiaddr::from_str("/ip4/10.0.0.1")?));
77 assert!(!is_public_address(&Multiaddr::from_str("/ip4/10.1.0.1")?));
78 assert!(!is_public_address(&Multiaddr::from_str("/ip4/10.255.255.255")?));
79 assert!(!is_public_address(&Multiaddr::from_str("/ip4/172.16.0.0")?));
80 assert!(!is_public_address(&Multiaddr::from_str("/ip4/172.31.255.255")?));
81
82 assert!(!is_public_address(&Multiaddr::from_str("/ip4/127.0.0.1")?));
84 assert!(!is_public_address(&Multiaddr::from_str("/ip4/127.255.255.255")?));
85
86 assert!(!is_public_address(&Multiaddr::from_str("/ip4/169.254.1.1")?));
88 assert!(!is_public_address(&Multiaddr::from_str("/ip4/169.254.254.254")?));
89
90 assert!(!is_public_address(&Multiaddr::from_str("/ip4/0.0.0.0")?));
92
93 Ok(())
94 }
95
96 #[test]
97 #[serial_test::serial] fn test_is_public_address_ipv6() -> anyhow::Result<()> {
99 override_allow_private_addresses(false);
100 assert!(!get_allow_private_addresses());
101
102 assert!(is_public_address(&Multiaddr::from_str("/ip6/2001:4860:4860::8888")?));
104 assert!(is_public_address(&Multiaddr::from_str("/ip6/2606:4700:4700::1111")?));
105 assert!(is_public_address(&Multiaddr::from_str(
106 "/ip6/2a00:1450:4001:830::200e"
107 )?));
108
109 assert!(!is_public_address(&Multiaddr::from_str("/ip6/::1")?));
111
112 assert!(!is_public_address(&Multiaddr::from_str("/ip6/fc00::1")?));
114 assert!(!is_public_address(&Multiaddr::from_str("/ip6/fd00::1")?));
115 assert!(!is_public_address(&Multiaddr::from_str(
116 "/ip6/fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
117 )?));
118
119 assert!(!is_public_address(&Multiaddr::from_str("/ip6/fe80::1")?));
121 assert!(!is_public_address(&Multiaddr::from_str(
122 "/ip6/fe80::dead:beef:cafe:babe"
123 )?));
124 assert!(!is_public_address(&Multiaddr::from_str(
125 "/ip6/febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
126 )?));
127
128 assert!(!is_public_address(&Multiaddr::from_str("/ip6/::")?));
130
131 Ok(())
132 }
133
134 #[test]
135 #[serial_test::serial] fn test_is_public_address_with_protocols() -> anyhow::Result<()> {
137 override_allow_private_addresses(false);
138 assert!(!get_allow_private_addresses());
139
140 assert!(is_public_address(&Multiaddr::from_str("/ip4/8.8.8.8/tcp/4001")?));
142 assert!(is_public_address(&Multiaddr::from_str("/ip4/1.1.1.1/udp/30303")?));
143 assert!(is_public_address(&Multiaddr::from_str(
144 "/ip4/8.8.8.8/tcp/4001/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
145 )?));
146 assert!(is_public_address(&Multiaddr::from_str(
147 "/ip6/2001:4860:4860::8888/tcp/4001"
148 )?));
149 assert!(is_public_address(&Multiaddr::from_str(
150 "/ip6/2001:4860:4860::8888/udp/30303"
151 )?));
152 assert!(is_public_address(&Multiaddr::from_str(
153 "/ip6/2606:4700:4700::1111/tcp/443/wss"
154 )?));
155
156 assert!(!is_public_address(&Multiaddr::from_str("/ip4/192.168.0.1/tcp/4001")?));
158 assert!(!is_public_address(&Multiaddr::from_str("/ip4/127.0.0.1/tcp/8080")?));
159 assert!(!is_public_address(&Multiaddr::from_str("/ip4/10.0.0.1/tcp/8080")?));
160 assert!(!is_public_address(&Multiaddr::from_str("/ip4/10.1.0.1/tcp/8080")?));
161 assert!(!is_public_address(&Multiaddr::from_str("/ip4/169.254.1.1/udp/5060")?));
162 assert!(!is_public_address(&Multiaddr::from_str("/ip4/0.0.0.0/tcp/3000")?));
163 assert!(!is_public_address(&Multiaddr::from_str("/ip6/::1/tcp/4001")?));
164 assert!(!is_public_address(&Multiaddr::from_str("/ip6/fe80::1/udp/30303")?));
165 assert!(!is_public_address(&Multiaddr::from_str("/ip6/fc00::1/tcp/443")?));
166 assert!(!is_public_address(&Multiaddr::from_str("/ip6/::/tcp/8080")?));
167
168 Ok(())
169 }
170
171 #[test]
172 #[serial_test::serial] fn test_is_public_address_mixed_protocols() -> anyhow::Result<()> {
174 override_allow_private_addresses(false);
175 assert!(!get_allow_private_addresses());
176
177 assert!(is_public_address(&Multiaddr::from_str("/dns/example.com")?));
179 assert!(is_public_address(&Multiaddr::from_str("/dns4/example.com/tcp/443")?));
180 assert!(is_public_address(&Multiaddr::from_str("/dns6/example.com/tcp/443")?));
181
182 Ok(())
183 }
184
185 #[test]
186 #[serial_test::serial] fn test_local_testing_allows_all_addresses() -> anyhow::Result<()> {
188 override_allow_private_addresses(true);
189 assert!(get_allow_private_addresses());
190
191 assert!(is_public_address(&Multiaddr::from_str("/ip4/127.0.0.1")?));
193 assert!(is_public_address(&Multiaddr::from_str("/ip4/192.168.1.1")?));
194 assert!(is_public_address(&Multiaddr::from_str("/ip4/10.0.0.1")?));
195 assert!(is_public_address(&Multiaddr::from_str("/ip4/172.16.0.1")?));
196 assert!(is_public_address(&Multiaddr::from_str("/ip6/::1")?));
197 assert!(is_public_address(&Multiaddr::from_str("/ip6/fe80::1")?));
198
199 Ok(())
200 }
201}