ferron/modules/
blocklist.rs1use 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}