ferron/modules/
x_forwarded_for.rs

1use std::error::Error;
2use std::net::{IpAddr, SocketAddr};
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
14struct XForwardedForModule;
15
16pub fn server_module_init(
17) -> Result<Box<dyn ServerModule + Send + Sync>, Box<dyn Error + Send + Sync>> {
18  Ok(Box::new(XForwardedForModule::new()))
19}
20
21impl XForwardedForModule {
22  fn new() -> Self {
23    Self
24  }
25}
26
27impl ServerModule for XForwardedForModule {
28  fn get_handlers(&self, handle: Handle) -> Box<dyn ServerModuleHandlers + Send> {
29    Box::new(XForwardedForModuleHandlers { handle })
30  }
31}
32struct XForwardedForModuleHandlers {
33  handle: Handle,
34}
35
36#[async_trait]
37impl ServerModuleHandlers for XForwardedForModuleHandlers {
38  async fn request_handler(
39    &mut self,
40    request: RequestData,
41    config: &ServerConfig,
42    socket_data: &SocketData,
43    _error_logger: &ErrorLogger,
44  ) -> Result<ResponseData, Box<dyn Error + Send + Sync>> {
45    WithRuntime::new(self.handle.clone(), async move {
46      if config["enableIPSpoofing"].as_bool() == Some(true) {
47        let hyper_request = request.get_hyper_request();
48
49        if let Some(x_forwarded_for_value) = hyper_request.headers().get("x-forwarded-for") {
50          let x_forwarded_for = x_forwarded_for_value.to_str()?;
51
52          let prepared_remote_ip_str = match x_forwarded_for.split(",").nth(0) {
53            Some(ip_address_str) => ip_address_str.replace(" ", ""),
54            None => {
55              return Ok(
56                ResponseData::builder(request)
57                  .status(StatusCode::BAD_REQUEST)
58                  .build(),
59              );
60            }
61          };
62
63          let prepared_remote_ip: IpAddr = match prepared_remote_ip_str.parse() {
64            Ok(ip_address) => ip_address,
65            Err(_) => {
66              return Ok(
67                ResponseData::builder(request)
68                  .status(StatusCode::BAD_REQUEST)
69                  .build(),
70              );
71            }
72          };
73
74          let new_socket_addr = SocketAddr::new(prepared_remote_ip, socket_data.remote_addr.port());
75
76          return Ok(
77            ResponseData::builder(request)
78              .new_remote_address(new_socket_addr)
79              .build(),
80          );
81        }
82
83        return Ok(ResponseData::builder(request).build());
84      }
85
86      Ok(ResponseData::builder(request).build())
87    })
88    .await
89  }
90
91  async fn proxy_request_handler(
92    &mut self,
93    request: RequestData,
94    _config: &ServerConfig,
95    _socket_data: &SocketData,
96    _error_logger: &ErrorLogger,
97  ) -> Result<ResponseData, Box<dyn Error + Send + Sync>> {
98    Ok(ResponseData::builder(request).build())
99  }
100
101  async fn response_modifying_handler(
102    &mut self,
103    response: HyperResponse,
104  ) -> Result<HyperResponse, Box<dyn Error + Send + Sync>> {
105    Ok(response)
106  }
107
108  async fn proxy_response_modifying_handler(
109    &mut self,
110    response: HyperResponse,
111  ) -> Result<HyperResponse, Box<dyn Error + Send + Sync>> {
112    Ok(response)
113  }
114
115  async fn connect_proxy_request_handler(
116    &mut self,
117    _upgraded_request: HyperUpgraded,
118    _connect_address: &str,
119    _config: &ServerConfig,
120    _socket_data: &SocketData,
121    _error_logger: &ErrorLogger,
122  ) -> Result<(), Box<dyn Error + Send + Sync>> {
123    Ok(())
124  }
125
126  fn does_connect_proxy_requests(&mut self) -> bool {
127    false
128  }
129
130  async fn websocket_request_handler(
131    &mut self,
132    _websocket: HyperWebsocket,
133    _uri: &hyper::Uri,
134    _config: &ServerConfig,
135    _socket_data: &SocketData,
136    _error_logger: &ErrorLogger,
137  ) -> Result<(), Box<dyn Error + Send + Sync>> {
138    Ok(())
139  }
140
141  fn does_websocket_requests(&mut self, _config: &ServerConfig, _socket_data: &SocketData) -> bool {
142    false
143  }
144}