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("2001:db8:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap()));
215 }
216
217 #[test]
220 fn blocks_ipv6_ula() {
221 assert!(is_blocked_ip("fc00::1".parse().unwrap()));
222 assert!(is_blocked_ip("fd00::1".parse().unwrap()));
223 assert!(is_blocked_ip("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap()));
224 }
225
226 #[test]
229 fn blocks_ipv4_mapped_private() {
230 assert!(is_blocked_ip("::ffff:10.0.0.1".parse().unwrap()));
231 assert!(is_blocked_ip("::ffff:192.168.1.1".parse().unwrap()));
232 }
233
234 #[test]
235 fn blocks_ipv4_mapped_loopback() {
236 assert!(is_blocked_ip("::ffff:127.0.0.1".parse().unwrap()));
237 }
238
239 #[test]
240 fn blocks_ipv4_mapped_cgnat() {
241 assert!(is_blocked_ip("::ffff:100.64.0.1".parse().unwrap()));
242 }
243
244 #[test]
245 fn allows_ipv4_mapped_public() {
246 assert!(!is_blocked_ip("::ffff:1.1.1.1".parse().unwrap()));
247 }
248
249 #[test]
252 fn blocks_6to4_private() {
253 assert!(is_blocked_ip("2002:c0a8:0101::".parse().unwrap()));
255 }
256
257 #[test]
258 fn blocks_6to4_loopback() {
259 assert!(is_blocked_ip("2002:7f00:0001::".parse().unwrap()));
261 }
262
263 #[test]
264 fn allows_6to4_public() {
265 assert!(!is_blocked_ip("2002:0101:0101::".parse().unwrap()));
267 }
268
269 #[test]
272 fn blocks_nat64_prefix() {
273 assert!(is_blocked_ip("64:ff9b::".parse().unwrap()));
274 assert!(is_blocked_ip("64:ff9b::1".parse().unwrap()));
275 assert!(is_blocked_ip("64:ff9b::7f00:1".parse().unwrap()));
276 }
277
278 #[test]
281 fn allows_public_ipv4() {
282 assert!(!is_blocked_ip("1.1.1.1".parse().unwrap()));
283 assert!(!is_blocked_ip("8.8.8.8".parse().unwrap()));
284 assert!(!is_blocked_ip("9.9.9.9".parse().unwrap()));
285 }
286
287 #[test]
288 fn allows_public_ipv6() {
289 assert!(!is_blocked_ip("2001:4860:4860::8888".parse().unwrap()));
290 assert!(!is_blocked_ip("2606:4700:4700::1111".parse().unwrap()));
291 }
292
293 #[test]
296 fn boundary_172_rfc1918() {
297 assert!(is_blocked_ip("172.31.255.255".parse().unwrap()));
298 assert!(!is_blocked_ip("172.32.0.0".parse().unwrap()));
299 assert!(!is_blocked_ip("172.15.255.255".parse().unwrap()));
300 }
301
302 #[test]
303 fn boundary_loopback_v4() {
304 assert!(is_blocked_ip("127.0.0.0".parse().unwrap()));
305 assert!(!is_blocked_ip("126.255.255.255".parse().unwrap()));
306 assert!(!is_blocked_ip("128.0.0.0".parse().unwrap()));
307 }
308
309 #[test]
310 fn boundary_multicast_v4() {
311 assert!(is_blocked_ip("224.0.0.0".parse().unwrap()));
312 assert!(!is_blocked_ip("223.255.255.255".parse().unwrap()));
313 }
314}