ferron/util/
ip_blocklist.rs

1use std::collections::HashSet;
2use std::net::{IpAddr, Ipv6Addr};
3
4pub struct IpBlockList {
5  blocked_ips: HashSet<IpAddr>,
6}
7
8impl IpBlockList {
9  // Create a new empty block list
10  pub fn new() -> Self {
11    Self {
12      blocked_ips: HashSet::new(),
13    }
14  }
15
16  // Load the block list from a vector of IP address strings
17  pub fn load_from_vec(&mut self, ip_list: Vec<&str>) {
18    for ip_str in ip_list {
19      match ip_str {
20        "localhost" => {
21          self
22            .blocked_ips
23            .insert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into());
24        }
25        _ => {
26          if let Ok(ip) = ip_str.parse::<IpAddr>() {
27            self.blocked_ips.insert(ip.to_canonical());
28          }
29        }
30      }
31    }
32  }
33
34  // Check if an IP address is blocked
35  pub fn is_blocked(&self, ip: IpAddr) -> bool {
36    self.blocked_ips.contains(&ip.to_canonical())
37  }
38}
39
40#[cfg(test)]
41mod tests {
42  use super::*;
43
44  #[test]
45  fn test_ip_block_list() {
46    let mut block_list = IpBlockList::new();
47    block_list.load_from_vec(vec!["192.168.1.1", "10.0.0.1"]);
48
49    assert!(block_list.is_blocked("192.168.1.1".parse().unwrap()));
50    assert!(block_list.is_blocked("10.0.0.1".parse().unwrap()));
51    assert!(!block_list.is_blocked("8.8.8.8".parse().unwrap()));
52  }
53}