ferron/modules/
blocklist.rs

1use std::error::Error;
2use std::sync::Arc;
3
4use crate::ferron_common::{
5  ErrorLogger, HyperResponse, RequestData, ResponseData, ServerConfig, ServerModule,
6  ServerModuleHandlers, SocketData,
7};
8use crate::ferron_common::{HyperUpgraded, WithRuntime};
9use async_trait::async_trait;
10use hyper::StatusCode;
11use hyper_tungstenite::HyperWebsocket;
12use tokio::runtime::Handle;
13
14use crate::ferron_util::ip_blocklist::IpBlockList;
15
16struct BlockListModule {
17  blocklist: Arc<IpBlockList>,
18}
19
20pub fn server_module_init(
21  config: &ServerConfig,
22) -> Result<Box<dyn ServerModule + Send + Sync>, Box<dyn Error + Send + Sync>> {
23  let blocklist_vec = match config["global"]["blocklist"].as_vec() {
24    Some(blocklist_vec) => blocklist_vec,
25    None => &Vec::new(),
26  };
27
28  let mut blocklist_str_vec = Vec::new();
29  for blocked_yaml in blocklist_vec.iter() {
30    if let Some(blocked) = blocked_yaml.as_str() {
31      blocklist_str_vec.push(blocked);
32    }
33  }
34
35  let mut blocklist = IpBlockList::new();
36  blocklist.load_from_vec(blocklist_str_vec);
37
38  Ok(Box::new(BlockListModule::new(Arc::new(blocklist))))
39}
40
41impl BlockListModule {
42  fn new(blocklist: Arc<IpBlockList>) -> Self {
43    Self { blocklist }
44  }
45}
46
47impl ServerModule for BlockListModule {
48  fn get_handlers(&self, handle: Handle) -> Box<dyn ServerModuleHandlers + Send> {
49    Box::new(BlockListModuleHandlers {
50      blocklist: self.blocklist.clone(),
51      handle,
52    })
53  }
54}
55struct BlockListModuleHandlers {
56  blocklist: Arc<IpBlockList>,
57  handle: Handle,
58}
59
60#[async_trait]
61impl ServerModuleHandlers for BlockListModuleHandlers {
62  async fn request_handler(
63    &mut self,
64    request: RequestData,
65    _config: &ServerConfig,
66    socket_data: &SocketData,
67    _error_logger: &ErrorLogger,
68  ) -> Result<ResponseData, Box<dyn Error + Send + Sync>> {
69    WithRuntime::new(self.handle.clone(), async move {
70      if self.blocklist.is_blocked(socket_data.remote_addr.ip()) {
71        return Ok(
72          ResponseData::builder(request)
73            .status(StatusCode::FORBIDDEN)
74            .build(),
75        );
76      }
77      Ok(ResponseData::builder(request).build())
78    })
79    .await
80  }
81
82  async fn proxy_request_handler(
83    &mut self,
84    request: RequestData,
85    _config: &ServerConfig,
86    _socket_data: &SocketData,
87    _error_logger: &ErrorLogger,
88  ) -> Result<ResponseData, Box<dyn Error + Send + Sync>> {
89    Ok(ResponseData::builder(request).build())
90  }
91
92  async fn response_modifying_handler(
93    &mut self,
94    response: HyperResponse,
95  ) -> Result<HyperResponse, Box<dyn Error + Send + Sync>> {
96    Ok(response)
97  }
98
99  async fn proxy_response_modifying_handler(
100    &mut self,
101    response: HyperResponse,
102  ) -> Result<HyperResponse, Box<dyn Error + Send + Sync>> {
103    Ok(response)
104  }
105
106  async fn connect_proxy_request_handler(
107    &mut self,
108    _upgraded_request: HyperUpgraded,
109    _connect_address: &str,
110    _config: &ServerConfig,
111    _socket_data: &SocketData,
112    _error_logger: &ErrorLogger,
113  ) -> Result<(), Box<dyn Error + Send + Sync>> {
114    Ok(())
115  }
116
117  fn does_connect_proxy_requests(&mut self) -> bool {
118    false
119  }
120
121  async fn websocket_request_handler(
122    &mut self,
123    _websocket: HyperWebsocket,
124    _uri: &hyper::Uri,
125    _config: &ServerConfig,
126    _socket_data: &SocketData,
127    _error_logger: &ErrorLogger,
128  ) -> Result<(), Box<dyn Error + Send + Sync>> {
129    Ok(())
130  }
131
132  fn does_websocket_requests(&mut self, _config: &ServerConfig, _socket_data: &SocketData) -> bool {
133    false
134  }
135}