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