netray_common/
ip_filter.rs1use std::net::{IpAddr, Ipv4Addr};
2
3pub fn is_blocked_ip(ip: IpAddr) -> bool {
6 match ip {
7 IpAddr::V4(v4) => is_blocked_v4(v4),
8 IpAddr::V6(v6) => {
9 if let Some(v4) = v6.to_ipv4_mapped() {
11 return is_blocked_v4(v4);
12 }
13 is_blocked_v6(v6)
14 }
15 }
16}
17
18fn is_blocked_v4(v4: Ipv4Addr) -> bool {
19 if v4.is_loopback() {
20 return true;
21 }
22 if v4.is_unspecified() {
23 return true;
24 }
25 if v4.is_multicast() {
26 return true;
27 }
28 if v4.is_private() {
30 return true;
31 }
32 if v4.is_link_local() {
34 return true;
35 }
36 let o = v4.octets();
38 if o[0] == 100 && (o[1] & 0xC0) == 64 {
39 return true;
40 }
41 if (o[0] == 192 && o[1] == 0 && o[2] == 2)
43 || (o[0] == 198 && o[1] == 51 && o[2] == 100)
44 || (o[0] == 203 && o[1] == 0 && o[2] == 113)
45 {
46 return true;
47 }
48 false
49}
50
51fn is_blocked_v6(v6: std::net::Ipv6Addr) -> bool {
52 if v6.is_loopback() {
53 return true;
54 }
55 if v6.is_unspecified() {
56 return true;
57 }
58 if v6.is_multicast() {
59 return true;
60 }
61 let segs = v6.segments();
62 if (segs[0] & 0xFFC0) == 0xFE80 {
64 return true;
65 }
66 if (segs[0] & 0xFE00) == 0xFC00 {
68 return true;
69 }
70 if segs[0] == 0x2001 && segs[1] == 0x0DB8 {
72 return true;
73 }
74 if segs[0] == 0x2002 {
76 let embedded = Ipv4Addr::new(
77 (segs[1] >> 8) as u8,
78 (segs[1] & 0xFF) as u8,
79 (segs[2] >> 8) as u8,
80 (segs[2] & 0xFF) as u8,
81 );
82 return is_blocked_v4(embedded);
83 }
84 if segs[0] == 0x0064
86 && segs[1] == 0xFF9B
87 && segs[2] == 0
88 && segs[3] == 0
89 && segs[4] == 0
90 && segs[5] == 0
91 {
92 return true;
93 }
94 false
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use std::net::{Ipv4Addr, Ipv6Addr};
101
102 #[test]
105 fn blocks_ipv4_loopback() {
106 assert!(is_blocked_ip(IpAddr::V4(Ipv4Addr::LOCALHOST)));
107 assert!(is_blocked_ip("127.0.0.1".parse().unwrap()));
108 assert!(is_blocked_ip("127.255.255.255".parse().unwrap()));
109 }
110
111 #[test]
112 fn blocks_ipv6_loopback() {
113 assert!(is_blocked_ip(IpAddr::V6(Ipv6Addr::LOCALHOST)));
114 assert!(is_blocked_ip("::1".parse().unwrap()));
115 }
116
117 #[test]
120 fn blocks_ipv4_unspecified() {
121 assert!(is_blocked_ip(IpAddr::V4(Ipv4Addr::UNSPECIFIED)));
122 assert!(is_blocked_ip("0.0.0.0".parse().unwrap()));
123 }
124
125 #[test]
126 fn blocks_ipv6_unspecified() {
127 assert!(is_blocked_ip(IpAddr::V6(Ipv6Addr::UNSPECIFIED)));
128 assert!(is_blocked_ip("::".parse().unwrap()));
129 }
130
131 #[test]
134 fn blocks_ipv4_multicast() {
135 assert!(is_blocked_ip("224.0.0.0".parse().unwrap()));
136 assert!(is_blocked_ip("224.0.0.1".parse().unwrap()));
137 assert!(is_blocked_ip("239.255.255.255".parse().unwrap()));
138 }
139
140 #[test]
141 fn blocks_ipv6_multicast() {
142 assert!(is_blocked_ip("ff02::1".parse().unwrap()));
143 assert!(is_blocked_ip("ff00::".parse().unwrap()));
144 }
145
146 #[test]
149 fn blocks_rfc1918_10() {
150 assert!(is_blocked_ip("10.0.0.0".parse().unwrap()));
151 assert!(is_blocked_ip("10.0.0.1".parse().unwrap()));
152 assert!(is_blocked_ip("10.255.255.255".parse().unwrap()));
153 }
154
155 #[test]
156 fn blocks_rfc1918_172_16() {
157 assert!(is_blocked_ip("172.16.0.0".parse().unwrap()));
158 assert!(is_blocked_ip("172.16.0.1".parse().unwrap()));
159 assert!(is_blocked_ip("172.31.255.255".parse().unwrap()));
160 }
161
162 #[test]
163 fn blocks_rfc1918_192_168() {
164 assert!(is_blocked_ip("192.168.0.0".parse().unwrap()));
165 assert!(is_blocked_ip("192.168.1.1".parse().unwrap()));
166 assert!(is_blocked_ip("192.168.255.255".parse().unwrap()));
167 }
168
169 #[test]
172 fn blocks_ipv4_link_local() {
173 assert!(is_blocked_ip("169.254.0.0".parse().unwrap()));
174 assert!(is_blocked_ip("169.254.1.1".parse().unwrap()));
175 assert!(is_blocked_ip("169.254.255.255".parse().unwrap()));
176 }
177
178 #[test]
179 fn blocks_ipv6_link_local() {
180 assert!(is_blocked_ip("fe80::1".parse().unwrap()));
181 assert!(is_blocked_ip("febf::ffff".parse().unwrap()));
182 }
183
184 #[test]
187 fn blocks_cgnat() {
188 assert!(is_blocked_ip("100.64.0.0".parse().unwrap()));
189 assert!(is_blocked_ip("100.64.0.1".parse().unwrap()));
190 assert!(is_blocked_ip("100.127.255.255".parse().unwrap()));
191 }
192
193 #[test]
194 fn allows_100_outside_cgnat() {
195 assert!(!is_blocked_ip("100.63.255.255".parse().unwrap()));
196 assert!(!is_blocked_ip("100.128.0.0".parse().unwrap()));
197 }
198
199 #[test]
202 fn blocks_documentation_ipv4() {
203 assert!(is_blocked_ip("192.0.2.0".parse().unwrap()));
204 assert!(is_blocked_ip("192.0.2.1".parse().unwrap()));
205 assert!(is_blocked_ip("198.51.100.0".parse().unwrap()));
206 assert!(is_blocked_ip("198.51.100.1".parse().unwrap()));
207 assert!(is_blocked_ip("203.0.113.0".parse().unwrap()));
208 assert!(is_blocked_ip("203.0.113.1".parse().unwrap()));
209 }
210
211 #[test]
212 fn blocks_documentation_ipv6() {
213 assert!(is_blocked_ip("2001:db8::1".parse().unwrap()));
214 assert!(is_blocked_ip(
215 "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap()
216 ));
217 }
218
219 #[test]
222 fn blocks_ipv6_ula() {
223 assert!(is_blocked_ip("fc00::1".parse().unwrap()));
224 assert!(is_blocked_ip("fd00::1".parse().unwrap()));
225 assert!(is_blocked_ip(
226 "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap()
227 ));
228 }
229
230 #[test]
233 fn blocks_ipv4_mapped_private() {
234 assert!(is_blocked_ip("::ffff:10.0.0.1".parse().unwrap()));
235 assert!(is_blocked_ip("::ffff:192.168.1.1".parse().unwrap()));
236 }
237
238 #[test]
239 fn blocks_ipv4_mapped_loopback() {
240 assert!(is_blocked_ip("::ffff:127.0.0.1".parse().unwrap()));
241 }
242
243 #[test]
244 fn blocks_ipv4_mapped_cgnat() {
245 assert!(is_blocked_ip("::ffff:100.64.0.1".parse().unwrap()));
246 }
247
248 #[test]
249 fn allows_ipv4_mapped_public() {
250 assert!(!is_blocked_ip("::ffff:1.1.1.1".parse().unwrap()));
251 }
252
253 #[test]
256 fn blocks_6to4_private() {
257 assert!(is_blocked_ip("2002:c0a8:0101::".parse().unwrap()));
259 }
260
261 #[test]
262 fn blocks_6to4_loopback() {
263 assert!(is_blocked_ip("2002:7f00:0001::".parse().unwrap()));
265 }
266
267 #[test]
268 fn allows_6to4_public() {
269 assert!(!is_blocked_ip("2002:0101:0101::".parse().unwrap()));
271 }
272
273 #[test]
276 fn blocks_nat64_prefix() {
277 assert!(is_blocked_ip("64:ff9b::".parse().unwrap()));
278 assert!(is_blocked_ip("64:ff9b::1".parse().unwrap()));
279 assert!(is_blocked_ip("64:ff9b::7f00:1".parse().unwrap()));
280 }
281
282 #[test]
285 fn allows_public_ipv4() {
286 assert!(!is_blocked_ip("1.1.1.1".parse().unwrap()));
287 assert!(!is_blocked_ip("8.8.8.8".parse().unwrap()));
288 assert!(!is_blocked_ip("9.9.9.9".parse().unwrap()));
289 }
290
291 #[test]
292 fn allows_public_ipv6() {
293 assert!(!is_blocked_ip("2001:4860:4860::8888".parse().unwrap()));
294 assert!(!is_blocked_ip("2606:4700:4700::1111".parse().unwrap()));
295 }
296
297 #[test]
300 fn boundary_172_rfc1918() {
301 assert!(is_blocked_ip("172.31.255.255".parse().unwrap()));
302 assert!(!is_blocked_ip("172.32.0.0".parse().unwrap()));
303 assert!(!is_blocked_ip("172.15.255.255".parse().unwrap()));
304 }
305
306 #[test]
307 fn boundary_loopback_v4() {
308 assert!(is_blocked_ip("127.0.0.0".parse().unwrap()));
309 assert!(!is_blocked_ip("126.255.255.255".parse().unwrap()));
310 assert!(!is_blocked_ip("128.0.0.0".parse().unwrap()));
311 }
312
313 #[test]
314 fn boundary_multicast_v4() {
315 assert!(is_blocked_ip("224.0.0.0".parse().unwrap()));
316 assert!(!is_blocked_ip("223.255.255.255".parse().unwrap()));
317 }
318}