1use crate::extract::RequestInformation;
2use crate::Config;
3use core::net::IpAddr;
4
5#[derive(Debug, Clone)]
27pub enum Trusted<'a> {
28 Borrowed(TrustedBorrowed<'a>),
29 Owned(TrustedOwned),
30}
31
32#[derive(Debug, Clone)]
33pub struct TrustedBorrowed<'a> {
34 host: Option<&'a str>,
35 scheme: Option<&'a str>,
36 by: Option<&'a str>,
37 ip: IpAddr,
38}
39
40#[derive(Debug, Clone)]
41pub struct TrustedOwned {
42 host: Option<String>,
43 scheme: Option<String>,
44 by: Option<String>,
45 ip: IpAddr,
46}
47
48fn unquote(val: &str) -> &str {
50 val.trim().trim_start_matches('"').trim_end_matches('"')
51}
52
53fn bare_address(val: &str) -> &str {
55 if val.starts_with('[') {
56 val.split("]:")
57 .next()
58 .map(|s| s.trim_start_matches('[').trim_end_matches(']'))
59 .unwrap_or(val)
62 } else {
63 val.split(':').next().unwrap_or(val)
64 }
65}
66
67impl Trusted<'_> {
68 pub fn into_owned(self) -> Trusted<'static> {
69 match self {
70 Self::Borrowed(trusted) => Trusted::Owned(TrustedOwned {
71 host: trusted.host.map(|s| s.to_string()),
72 scheme: trusted.scheme.map(|s| s.to_string()),
73 by: trusted.by.map(|s| s.to_string()),
74 ip: trusted.ip,
75 }),
76 Self::Owned(trusted) => Trusted::Owned(trusted),
77 }
78 }
79}
80
81impl<'a> Trusted<'a> {
82 pub fn scheme(&self) -> Option<&str> {
84 match self {
85 Self::Borrowed(trusted) => trusted.scheme,
86 Self::Owned(trusted) => trusted.scheme.as_deref(),
87 }
88 }
89
90 pub fn host_with_port(&self) -> Option<&str> {
92 match self {
93 Self::Borrowed(trusted) => trusted.host,
94 Self::Owned(trusted) => trusted.host.as_deref(),
95 }
96 }
97
98 pub fn host(&self) -> Option<&str> {
100 self.host_with_port()
101 .and_then(|host| host.split(':').next())
102 }
103
104 pub fn port(&self) -> Option<u16> {
106 self.host_with_port().and_then(|host| {
107 host.split(':')
108 .nth(1)
109 .and_then(|port| port.parse::<u16>().ok())
110 })
111 }
112
113 pub fn by(&self) -> Option<&str> {
115 match self {
116 Self::Borrowed(trusted) => trusted.by,
117 Self::Owned(trusted) => trusted.by.as_deref(),
118 }
119 }
120
121 pub fn ip(&self) -> IpAddr {
123 match self {
124 Self::Borrowed(trusted) => trusted.ip,
125 Self::Owned(trusted) => trusted.ip,
126 }
127 }
128
129 pub fn from<T: RequestInformation>(ip_addr: IpAddr, request: &'a T, config: &Config) -> Self {
131 let (trusted_host, trusted_scheme, trusted_by, trusted_ip) =
132 if !config.is_ip_trusted(&ip_addr) {
133 (
136 request.default_host(),
137 request.default_scheme(),
138 None,
139 ip_addr,
140 )
141 } else {
142 let mut host = None;
144 let mut scheme = None;
145 let mut by = None;
146 let mut realip_remote_addr = None;
147
148 if config.is_forwarded_trusted {
150 let forwarded_list = request
158 .forwarded()
159 .flat_map(|vals| vals.split(','))
161 .rev();
163
164 'forwaded: for forwarded in forwarded_list {
165 for (key, value) in forwarded.split(';').map(|item| {
166 let mut kv = item.splitn(2, '=');
167
168 (
169 kv.next().map(|s| s.trim()).unwrap_or_default(),
170 kv.next().map(|s| unquote(s.trim())).unwrap_or_default(),
171 )
172 }) {
173 match key.to_lowercase().as_str() {
174 "for" => {
175 if let Ok(ip) = bare_address(value).parse::<IpAddr>() {
176 realip_remote_addr = Some(ip);
177
178 if config.is_ip_trusted(&ip) {
179 host = None;
180 scheme = None;
181 by = None;
182 realip_remote_addr = None;
183
184 continue 'forwaded;
185 }
186 }
187 }
188 "proto" => {
189 scheme = Some(value);
190 }
191 "host" => {
192 host = Some(value);
193 }
194 "by" => {
195 by = Some(value);
196 }
197 _ => {}
198 }
199 }
200
201 break;
202 }
203 }
204
205 if realip_remote_addr.is_none() && config.is_x_forwarded_for_trusted {
206 for value in request
207 .x_forwarded_for()
208 .flat_map(|vals| vals.split(','))
209 .map(|s| s.trim())
210 .rev()
211 {
212 if let Ok(ip) = bare_address(value).parse::<IpAddr>() {
213 if config.is_ip_trusted(&ip) {
214 continue;
215 }
216
217 realip_remote_addr = Some(ip);
218 }
219
220 break;
221 }
222 }
223
224 if host.is_none() && config.is_x_forwarded_host_trusted {
225 host = request
226 .x_forwarded_host()
227 .flat_map(|vals| vals.split(','))
228 .map(|s| s.trim())
229 .next_back();
230 }
231
232 if scheme.is_none() && config.is_x_forwarded_proto_trusted {
233 scheme = request
234 .x_forwarded_proto()
235 .flat_map(|vals| vals.split(','))
236 .map(|s| s.trim())
237 .next_back();
238 }
239
240 if by.is_none() && config.is_x_forwarded_by_trusted {
241 by = request
242 .x_forwarded_by()
243 .flat_map(|vals| vals.split(','))
244 .map(|s| s.trim())
245 .next_back();
246 }
247
248 (
249 host.or_else(|| request.default_host()),
250 scheme.or_else(|| request.default_scheme()),
251 by,
252 realip_remote_addr.unwrap_or(ip_addr),
253 )
254 };
255
256 Self::Borrowed(TrustedBorrowed {
257 host: trusted_host,
258 scheme: trusted_scheme,
259 by: trusted_by,
260 ip: trusted_ip,
261 })
262 }
263}
264
265#[cfg(all(test, feature = "http"))]
266mod tests {
267 use super::*;
268 use http::{header, Request, Version};
269
270 #[test]
271 fn default() {
272 let request = Request::get("http://localhost:8080/").body(()).unwrap();
273 let config = Config::default();
274 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
275
276 assert_eq!(trusted.scheme(), Some("http"));
277 assert_eq!(trusted.host(), Some("localhost"));
278 assert_eq!(trusted.port(), Some(8080));
279 assert_eq!(trusted.ip(), "127.0.0.1".parse::<IpAddr>().unwrap())
280 }
281
282 #[test]
283 fn host_header() {
284 let mut request = Request::get("http://localhost:8080/").body(()).unwrap();
285 request
286 .headers_mut()
287 .insert(header::HOST, "rust-lang.org:8081".parse().unwrap());
288 let config = Config::default();
289 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
290
291 assert_eq!(trusted.scheme(), Some("http"));
292 assert_eq!(trusted.host(), Some("rust-lang.org"));
293 assert_eq!(trusted.port(), Some(8081));
294 assert_eq!(trusted.ip(), "127.0.0.1".parse::<IpAddr>().unwrap());
295 }
296
297 #[test]
298 fn host_header_not_allowed() {
299 let mut request = Request::get("http://localhost:8080/").body(()).unwrap();
300 request
301 .headers_mut()
302 .insert(header::HOST, "rust-lang.org".parse().unwrap());
303 *request.version_mut() = Version::HTTP_2;
304 let config = Config::default();
305 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
306
307 assert_eq!(trusted.scheme(), Some("http"));
308 assert_eq!(trusted.host(), Some("localhost"));
309 assert_eq!(trusted.ip(), "127.0.0.1".parse::<IpAddr>().unwrap());
310 }
311
312 #[test]
313 fn x_forwarded_for_header_trusted() {
314 let mut request = Request::get("/").body(()).unwrap();
315 request.headers_mut().insert(
316 header::HeaderName::from_static("x-forwarded-for"),
317 "1.1.1.1".parse().unwrap(),
318 );
319
320 let config = Config::default();
321
322 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
324
325 assert_eq!(trusted.ip(), "1.1.1.1".parse::<IpAddr>().unwrap());
326 }
327
328 #[test]
329 fn x_forwarded_for_header_trusted_multiple() {
330 let mut request = Request::get("/").body(()).unwrap();
331 request.headers_mut().append(
332 header::HeaderName::from_static("x-forwarded-for"),
333 "1.1.1.1".parse().unwrap(),
334 );
335 request.headers_mut().append(
336 header::HeaderName::from_static("x-forwarded-for"),
337 "8.8.8.8".parse().unwrap(),
338 );
339
340 let config = Config::default();
341
342 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
344
345 assert_eq!(trusted.ip(), "8.8.8.8".parse::<IpAddr>().unwrap());
346
347 let mut request = Request::get("/").body(()).unwrap();
348 request.headers_mut().append(
349 header::HeaderName::from_static("x-forwarded-for"),
350 "1.1.1.1".parse().unwrap(),
351 );
352 request.headers_mut().append(
353 header::HeaderName::from_static("x-forwarded-for"),
354 "8.8.8.8".parse().unwrap(),
355 );
356
357 let mut config = Config::default();
358 config
359 .add_trusted_ip("8.8.8.8")
360 .expect("Failed to add trusted ip");
361
362 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
364
365 assert_eq!(trusted.ip(), "1.1.1.1".parse::<IpAddr>().unwrap());
366
367 let mut request = Request::get("/").body(()).unwrap();
368 request.headers_mut().append(
369 header::HeaderName::from_static("x-forwarded-for"),
370 "1.1.1.1, 8.8.8.8".parse().unwrap(),
371 );
372
373 let config = Config::default();
374
375 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
377
378 assert_eq!(trusted.ip(), "8.8.8.8".parse::<IpAddr>().unwrap());
379
380 let mut request = Request::get("/").body(()).unwrap();
381 request.headers_mut().append(
382 header::HeaderName::from_static("x-forwarded-for"),
383 "1.1.1.1, 8.8.8.8".parse().unwrap(),
384 );
385
386 let mut config = Config::default();
387 config
388 .add_trusted_ip("8.8.8.8")
389 .expect("Failed to add trusted ip");
390
391 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
393
394 assert_eq!(trusted.ip(), "1.1.1.1".parse::<IpAddr>().unwrap());
395 }
396
397 #[test]
398 fn x_forwarded_for_header_untrusted() {
399 let mut request = Request::get("/").body(()).unwrap();
400 request.headers_mut().append(
401 header::HeaderName::from_static("x-forwarded-for"),
402 "8.8.8.8".parse().unwrap(),
403 );
404
405 let mut config = Config::new();
406 config
407 .add_trusted_ip("8.8.8.8")
408 .expect("Failed to add trusted ip");
409
410 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
412
413 assert_eq!(trusted.ip(), "192.168.2.60".parse::<IpAddr>().unwrap());
414 }
415
416 #[test]
417 fn x_forwarded_host_header_trusted() {
418 let mut request = Request::get("/").body(()).unwrap();
419 request.headers_mut().append(
420 header::HeaderName::from_static("x-forwarded-host"),
421 "example.com:8080".parse().unwrap(),
422 );
423
424 let mut config = Config::default();
425 config.trust_x_forwarded_host();
426
427 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
429
430 assert_eq!(trusted.host(), Some("example.com"));
431 assert_eq!(trusted.port(), Some(8080));
432
433 let mut request = Request::get("/").body(()).unwrap();
434 request.headers_mut().append(
436 header::HeaderName::from_static("x-forwarded-host"),
437 "first.com:1234, example.com".parse().unwrap(),
438 );
439
440 let mut config = Config::default();
441 config.trust_x_forwarded_host();
442
443 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
445
446 assert_eq!(trusted.host(), Some("example.com"));
447 assert_eq!(trusted.port(), None);
448
449 let mut request = Request::get("/").body(()).unwrap();
450 request.headers_mut().append(
452 header::HeaderName::from_static("x-forwarded-host"),
453 "first.com, example.com".parse().unwrap(),
454 );
455
456 let mut config = Config::default();
457 config.trust_x_forwarded_host();
458
459 let trusted = Trusted::from("1.1.1.1".parse().unwrap(), &request, &config);
461
462 assert_eq!(trusted.host(), None);
463 }
464
465 #[test]
466 fn x_forwarded_host_header_untrusted() {
467 let mut request = Request::get("/").body(()).unwrap();
468 request.headers_mut().append(
470 header::HeaderName::from_static("x-forwarded-host"),
471 "first.com, example.com".parse().unwrap(),
472 );
473
474 let config = Config::default();
475
476 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
478
479 assert_eq!(trusted.host(), None);
480 }
481
482 #[test]
483 fn x_forwarded_proto_header_trusted() {
484 let mut request = Request::get("/").body(()).unwrap();
485 request.headers_mut().append(
486 header::HeaderName::from_static("x-forwarded-proto"),
487 "https".parse().unwrap(),
488 );
489
490 let mut config = Config::default();
491 config.trust_x_forwarded_proto();
492
493 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
495
496 assert_eq!(trusted.scheme(), Some("https"));
497
498 let mut request = Request::get("/").body(()).unwrap();
499 request.headers_mut().append(
500 header::HeaderName::from_static("x-forwarded-proto"),
501 "http".parse().unwrap(),
502 );
503 request.headers_mut().append(
504 header::HeaderName::from_static("x-forwarded-proto"),
505 "https".parse().unwrap(),
506 );
507
508 let mut config = Config::default();
509 config.trust_x_forwarded_proto();
510
511 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
513
514 assert_eq!(trusted.scheme(), Some("https"));
515
516 let mut request = Request::get("/").body(()).unwrap();
517 request.headers_mut().append(
518 header::HeaderName::from_static("x-forwarded-proto"),
519 "http, https".parse().unwrap(),
520 );
521
522 let mut config = Config::default();
523 config.trust_x_forwarded_proto();
524
525 let trusted = Trusted::from("192.168.2.60".parse().unwrap(), &request, &config);
527
528 assert_eq!(trusted.scheme(), Some("https"));
529
530 let mut request = Request::get("/").body(()).unwrap();
531 request.headers_mut().append(
533 header::HeaderName::from_static("x-forwarded-proto"),
534 "https".parse().unwrap(),
535 );
536
537 let mut config = Config::default();
538 config.trust_x_forwarded_proto();
539
540 let trusted = Trusted::from("1.1.1.1".parse().unwrap(), &request, &config);
542
543 assert_eq!(trusted.scheme(), None);
544 }
545
546 #[test]
547 fn x_forwarded_proto_header_untrusted() {
548 let mut request = Request::get("/").body(()).unwrap();
549 request.headers_mut().append(
551 header::HeaderName::from_static("x-forwarded-proto"),
552 "https".parse().unwrap(),
553 );
554
555 let config = Config::default();
556
557 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
559
560 assert_eq!(trusted.scheme(), None);
561 }
562
563 #[test]
564 fn forwarded_header() {
565 let mut request = Request::get("/").body(()).unwrap();
566 request.headers_mut().append(
567 header::HeaderName::from_static("forwarded"),
568 "for=192.0.2.60; proto=https; by=203.0.113.43; host=rust-lang.org"
569 .parse()
570 .unwrap(),
571 );
572
573 let config = Config::default();
574
575 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
577
578 assert_eq!(trusted.scheme(), Some("https"));
579 assert_eq!(trusted.host(), Some("rust-lang.org"));
580 assert_eq!(trusted.by(), Some("203.0.113.43"));
581 assert_eq!(trusted.ip(), "192.0.2.60".parse::<IpAddr>().unwrap());
582 }
583
584 #[test]
585 fn forwarded_case_sensitivity() {
586 let mut request = Request::get("/").body(()).unwrap();
587 request.headers_mut().append(
588 header::HeaderName::from_static("forwarded"),
589 "For=192.0.2.60".parse().unwrap(),
590 );
591
592 let config = Config::default();
593
594 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
596
597 assert_eq!(trusted.ip(), "192.0.2.60".parse::<IpAddr>().unwrap());
598 }
599
600 #[test]
601 fn forwarded_for_quoted() {
602 let mut request = Request::get("/").body(()).unwrap();
603 request.headers_mut().append(
604 header::HeaderName::from_static("forwarded"),
605 r#"for="192.0.2.60:8080""#.parse().unwrap(),
606 );
607
608 let config = Config::default();
609
610 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
612 assert_eq!(trusted.ip(), "192.0.2.60".parse::<IpAddr>().unwrap());
613 }
614
615 #[test]
616 fn forwarded_for_ipv6() {
617 let mut request = Request::get("/").body(()).unwrap();
618 request.headers_mut().append(
619 header::HeaderName::from_static("forwarded"),
620 r#"for="[2001:db8:cafe::17]""#.parse().unwrap(),
621 );
622
623 let config = Config::default();
624
625 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
627 assert_eq!(trusted.ip(), "2001:db8:cafe::17".parse::<IpAddr>().unwrap());
628 assert!(trusted.ip().is_ipv6());
629 }
630
631 #[test]
632 fn forwarded_for_ipv6_with_port() {
633 let mut request = Request::get("/").body(()).unwrap();
634 request.headers_mut().append(
635 header::HeaderName::from_static("forwarded"),
636 r#"for="[2001:db8:cafe::17]:4711""#.parse().unwrap(),
637 );
638
639 let config = Config::default();
640
641 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
643 assert_eq!(trusted.ip(), "2001:db8:cafe::17".parse::<IpAddr>().unwrap());
644 assert!(trusted.ip().is_ipv6());
645 }
646
647 #[test]
648 fn forwarded_for_multiple() {
649 let mut request = Request::get("/").body(()).unwrap();
650 request.headers_mut().append(
651 header::HeaderName::from_static("forwarded"),
652 "for=192.0.2.60, for=198.51.100.17".parse().unwrap(),
653 );
654
655 let config = Config::default();
656
657 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
659 assert_eq!(trusted.ip(), "198.51.100.17".parse::<IpAddr>().unwrap());
660
661 let mut request = Request::get("/").body(()).unwrap();
662 request.headers_mut().append(
663 header::HeaderName::from_static("forwarded"),
664 "for=192.0.2.60;proto=https, for=198.51.100.17;proto=http"
665 .parse()
666 .unwrap(),
667 );
668
669 let mut config = Config::default();
670 config
671 .add_trusted_ip("198.51.100.17")
672 .expect("Failed to add trusted ip");
673
674 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
676 assert_eq!(trusted.ip(), "192.0.2.60".parse::<IpAddr>().unwrap());
677 assert_eq!(trusted.scheme(), Some("https"));
678
679 let mut request = Request::get("/").body(()).unwrap();
680 request.headers_mut().append(
681 header::HeaderName::from_static("forwarded"),
682 "for=192.0.2.60, for=198.51.100.17;proto=http"
683 .parse()
684 .unwrap(),
685 );
686
687 let mut config = Config::default();
688 config
689 .add_trusted_ip("198.51.100.17")
690 .expect("Failed to add trusted ip");
691
692 let trusted = Trusted::from("127.0.0.1".parse().unwrap(), &request, &config);
694 assert_eq!(trusted.ip(), "192.0.2.60".parse::<IpAddr>().unwrap());
695 assert_eq!(trusted.scheme(), None);
696 }
697}