mirror of
https://codeberg.org/icewind/real-ip.git
synced 2026-06-03 09:34:08 +02:00
don't return any forwarded hops if the header is invalid
This commit is contained in:
parent
c9aea2fc74
commit
fcd6646f1b
2 changed files with 54 additions and 16 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
use comma_separated::CommaSeparatedIterator;
|
use comma_separated::CommaSeparatedIterator;
|
||||||
|
use either::Either;
|
||||||
use rfc7239::{parse, Forwarded, NodeIdentifier, NodeName};
|
use rfc7239::{parse, Forwarded, NodeIdentifier, NodeName};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter::IntoIterator;
|
use std::iter::{empty, IntoIterator};
|
||||||
use std::net::IpAddr;
|
use std::net::{AddrParseError, IpAddr};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Get the list of ip addresses from an `forwarded` header
|
/// Get the list of ip addresses from an `forwarded` header
|
||||||
|
|
@ -22,17 +23,29 @@ use std::str::FromStr;
|
||||||
pub fn extract_forwarded_header(
|
pub fn extract_forwarded_header(
|
||||||
header_value: &str,
|
header_value: &str,
|
||||||
) -> impl DoubleEndedIterator<Item = IpAddr> + '_ {
|
) -> impl DoubleEndedIterator<Item = IpAddr> + '_ {
|
||||||
parse(header_value).filter_map(|forward| match forward {
|
if parse(header_value).all(|result| result.is_ok()) {
|
||||||
Ok(Forwarded {
|
Either::Left(parse(header_value).filter_map(|forward| match forward {
|
||||||
forwarded_for:
|
Ok(Forwarded {
|
||||||
Some(NodeIdentifier {
|
forwarded_for:
|
||||||
name: NodeName::Ip(ip),
|
Some(NodeIdentifier {
|
||||||
..
|
name: NodeName::Ip(ip),
|
||||||
}),
|
..
|
||||||
..
|
}),
|
||||||
}) => Some(ip),
|
..
|
||||||
_ => None,
|
}) => Some(ip),
|
||||||
})
|
_ => None,
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
Either::Right(empty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_x_forwarded_for_header_raw(
|
||||||
|
header_value: &str,
|
||||||
|
) -> impl DoubleEndedIterator<Item = Result<IpAddr, AddrParseError>> + '_ {
|
||||||
|
CommaSeparatedIterator::new(header_value)
|
||||||
|
.map(str::trim)
|
||||||
|
.map(|x| IpAddr::from_str(maybe_bracketed(&maybe_quoted(x))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the list of ip addresses from an `x-forwarded-for` header
|
/// Get the list of ip addresses from an `x-forwarded-for` header
|
||||||
|
|
@ -50,9 +63,11 @@ pub fn extract_forwarded_header(
|
||||||
pub fn extract_x_forwarded_for_header(
|
pub fn extract_x_forwarded_for_header(
|
||||||
header_value: &str,
|
header_value: &str,
|
||||||
) -> impl DoubleEndedIterator<Item = IpAddr> + '_ {
|
) -> impl DoubleEndedIterator<Item = IpAddr> + '_ {
|
||||||
CommaSeparatedIterator::new(header_value)
|
if extract_x_forwarded_for_header_raw(header_value).all(|result| result.is_ok()) {
|
||||||
.map(str::trim)
|
Either::Left(extract_x_forwarded_for_header_raw(header_value).flatten())
|
||||||
.flat_map(|x| IpAddr::from_str(maybe_bracketed(&maybe_quoted(x))))
|
} else {
|
||||||
|
Either::Right(empty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the list of ip addresses from an `x-real-ip` header
|
/// Get the list of ip addresses from an `x-real-ip` header
|
||||||
|
|
|
||||||
23
src/lib.rs
23
src/lib.rs
|
|
@ -74,6 +74,7 @@ pub fn real_ip(headers: &HeaderMap, remote: IpAddr, trusted_proxies: &[IpNet]) -
|
||||||
|
|
||||||
'outer: for hop in hops.rev() {
|
'outer: for hop in hops.rev() {
|
||||||
for proxy in trusted_proxies {
|
for proxy in trusted_proxies {
|
||||||
|
dbg!(proxy);
|
||||||
if proxy.contains(&hop) {
|
if proxy.contains(&hop) {
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
|
|
@ -110,3 +111,25 @@ pub fn get_forwarded_for(headers: &HeaderMap) -> impl DoubleEndedIterator<Item =
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[doc = include_str!("../README.md")]
|
#[doc = include_str!("../README.md")]
|
||||||
fn test_readme_examples() {}
|
fn test_readme_examples() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_malformed() {
|
||||||
|
use http::header::HeaderValue;
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
"forwarded",
|
||||||
|
HeaderValue::from_static(
|
||||||
|
"by=203.0.111.42;for=1.2.3.4:8888,for=5.6.7.8;proto=https;nonsense",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let trusted_proxies = [
|
||||||
|
IpAddr::from([2, 3, 4, 5]).into(),
|
||||||
|
IpAddr::from([5, 6, 7, 8]).into(),
|
||||||
|
];
|
||||||
|
let remote = IpAddr::from([2, 3, 4, 5]);
|
||||||
|
assert!(get_forwarded_for(&headers).next().is_none());
|
||||||
|
assert_eq!(
|
||||||
|
Some(IpAddr::from([2, 3, 4, 5])),
|
||||||
|
real_ip(&headers, remote, &trusted_proxies)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue