add x-forwarded-proto
This commit is contained in:
parent
907d7e574b
commit
828d2300c0
3 changed files with 96 additions and 86 deletions
|
|
@ -10,8 +10,8 @@ services:
|
||||||
build:
|
build:
|
||||||
context: ./
|
context: ./
|
||||||
environment:
|
environment:
|
||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=debug
|
||||||
- LOG_TO_FILE
|
- LOG_TO_FILE=false
|
||||||
tty: false
|
tty: false
|
||||||
privileged: true
|
privileged: true
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ where
|
||||||
let request_upgraded = req.extensions_mut().remove::<hyper::upgrade::OnUpgrade>();
|
let request_upgraded = req.extensions_mut().remove::<hyper::upgrade::OnUpgrade>();
|
||||||
|
|
||||||
// Build request from destination information
|
// Build request from destination information
|
||||||
let req_forwarded = if let Ok(req) = generate_request_forwarded(
|
let req_forwarded = if let Ok(req) = self.generate_request_forwarded(
|
||||||
client_addr,
|
client_addr,
|
||||||
req,
|
req,
|
||||||
upstream_scheme_host,
|
upstream_scheme_host,
|
||||||
|
|
@ -149,7 +149,7 @@ where
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Generate response to client
|
// Generate response to client
|
||||||
if generate_response_forwarded(&mut res_backend).is_ok() {
|
if self.generate_response_forwarded(&mut res_backend).is_ok() {
|
||||||
info!("{} => {}", request_log, response_log);
|
info!("{} => {}", request_log, response_log);
|
||||||
Ok(res_backend)
|
Ok(res_backend)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -158,95 +158,99 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
// Functions to generate messages
|
// Functions to generate messages
|
||||||
|
|
||||||
fn generate_response_forwarded<B: core::fmt::Debug>(response: &mut Response<B>) -> Result<()> {
|
fn generate_response_forwarded<B: core::fmt::Debug>(
|
||||||
let headers = response.headers_mut();
|
&self,
|
||||||
remove_hop_header(headers);
|
response: &mut Response<B>,
|
||||||
remove_connection_header(headers);
|
) -> Result<()> {
|
||||||
append_header_entry(
|
let headers = response.headers_mut();
|
||||||
headers,
|
remove_hop_header(headers);
|
||||||
"server",
|
remove_connection_header(headers);
|
||||||
&format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")),
|
append_header_entry(
|
||||||
)?;
|
headers,
|
||||||
|
"server",
|
||||||
|
&format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_request_forwarded<B: core::fmt::Debug>(
|
fn generate_request_forwarded<B: core::fmt::Debug>(
|
||||||
client_addr: SocketAddr,
|
&self,
|
||||||
mut req: Request<B>,
|
client_addr: SocketAddr,
|
||||||
upstream_scheme_host: &Uri,
|
mut req: Request<B>,
|
||||||
upgrade: &Option<String>,
|
upstream_scheme_host: &Uri,
|
||||||
upstream: &Upstream,
|
upgrade: &Option<String>,
|
||||||
) -> Result<Request<B>> {
|
upstream: &Upstream,
|
||||||
debug!("Generate request to be forwarded");
|
) -> Result<Request<B>> {
|
||||||
|
debug!("Generate request to be forwarded");
|
||||||
|
|
||||||
// Add te: trailer if contained in original request
|
// Add te: trailer if contained in original request
|
||||||
let te_trailers = {
|
let te_trailers = {
|
||||||
if let Some(te) = req.headers().get(header::TE) {
|
if let Some(te) = req.headers().get(header::TE) {
|
||||||
te.to_str()?.split(',').any(|x| x.trim() == "trailers")
|
te.to_str()?.split(',').any(|x| x.trim() == "trailers")
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let headers = req.headers_mut();
|
||||||
|
// delete headers specified in header.connection
|
||||||
|
remove_connection_header(headers);
|
||||||
|
// delete hop headers including header.connection
|
||||||
|
remove_hop_header(headers);
|
||||||
|
// X-Forwarded-For
|
||||||
|
add_forwarding_header(headers, client_addr, self.tls_enabled)?;
|
||||||
|
// println!("{:?}", headers);
|
||||||
|
|
||||||
|
// Add te: trailer if te_trailer
|
||||||
|
if te_trailers {
|
||||||
|
headers.insert(header::TE, "trailer".parse()?);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let headers = req.headers_mut();
|
// add "host" header of original server_name if not exist (default)
|
||||||
// delete headers specified in header.connection
|
if req.headers().get(header::HOST).is_none() {
|
||||||
remove_connection_header(headers);
|
let org_host = req.uri().host().unwrap_or("none").to_owned();
|
||||||
// delete hop headers including header.connection
|
req
|
||||||
remove_hop_header(headers);
|
.headers_mut()
|
||||||
// X-Forwarded-For
|
.insert(header::HOST, HeaderValue::from_str(org_host.as_str())?);
|
||||||
add_forwarding_header(headers, client_addr)?;
|
};
|
||||||
// println!("{:?}", headers);
|
|
||||||
|
|
||||||
// Add te: trailer if te_trailer
|
// apply upstream-specific headers given in upstream_option
|
||||||
if te_trailers {
|
let headers = req.headers_mut();
|
||||||
headers.insert(header::TE, "trailer".parse()?);
|
apply_upstream_options_to_header(headers, client_addr, upstream_scheme_host, upstream)?;
|
||||||
|
|
||||||
|
// update uri in request
|
||||||
|
ensure!(upstream_scheme_host.authority().is_some() && upstream_scheme_host.scheme().is_some());
|
||||||
|
let new_uri = Uri::builder()
|
||||||
|
.scheme(upstream_scheme_host.scheme().unwrap().as_str())
|
||||||
|
.authority(upstream_scheme_host.authority().unwrap().as_str());
|
||||||
|
let pq = req.uri().path_and_query();
|
||||||
|
*req.uri_mut() = match pq {
|
||||||
|
None => new_uri,
|
||||||
|
Some(x) => new_uri.path_and_query(x.to_owned()),
|
||||||
|
}
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
// upgrade
|
||||||
|
if let Some(v) = upgrade {
|
||||||
|
req.headers_mut().insert("upgrade", v.parse()?);
|
||||||
|
req
|
||||||
|
.headers_mut()
|
||||||
|
.insert(header::CONNECTION, HeaderValue::from_str("upgrade")?);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change version to http/1.1 when destination scheme is http
|
||||||
|
if req.version() != Version::HTTP_11 && upstream_scheme_host.scheme() == Some(&Scheme::HTTP) {
|
||||||
|
*req.version_mut() = Version::HTTP_11;
|
||||||
|
} else if req.version() == Version::HTTP_3 {
|
||||||
|
debug!("HTTP/3 is currently unsupported for request to upstream. Use HTTP/2.");
|
||||||
|
*req.version_mut() = Version::HTTP_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add "host" header of original server_name if not exist (default)
|
|
||||||
if req.headers().get(header::HOST).is_none() {
|
|
||||||
let org_host = req.uri().host().unwrap_or("none").to_owned();
|
|
||||||
req
|
|
||||||
.headers_mut()
|
|
||||||
.insert(header::HOST, HeaderValue::from_str(org_host.as_str())?);
|
|
||||||
};
|
|
||||||
|
|
||||||
// apply upstream-specific headers given in upstream_option
|
|
||||||
let headers = req.headers_mut();
|
|
||||||
apply_upstream_options_to_header(headers, client_addr, upstream_scheme_host, upstream)?;
|
|
||||||
|
|
||||||
// update uri in request
|
|
||||||
ensure!(upstream_scheme_host.authority().is_some() && upstream_scheme_host.scheme().is_some());
|
|
||||||
let new_uri = Uri::builder()
|
|
||||||
.scheme(upstream_scheme_host.scheme().unwrap().as_str())
|
|
||||||
.authority(upstream_scheme_host.authority().unwrap().as_str());
|
|
||||||
let pq = req.uri().path_and_query();
|
|
||||||
*req.uri_mut() = match pq {
|
|
||||||
None => new_uri,
|
|
||||||
Some(x) => new_uri.path_and_query(x.to_owned()),
|
|
||||||
}
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
// upgrade
|
|
||||||
if let Some(v) = upgrade {
|
|
||||||
req.headers_mut().insert("upgrade", v.parse()?);
|
|
||||||
req
|
|
||||||
.headers_mut()
|
|
||||||
.insert(header::CONNECTION, HeaderValue::from_str("upgrade")?);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change version to http/1.1 when destination scheme is http
|
|
||||||
if req.version() != Version::HTTP_11 && upstream_scheme_host.scheme() == Some(&Scheme::HTTP) {
|
|
||||||
*req.version_mut() = Version::HTTP_11;
|
|
||||||
} else if req.version() == Version::HTTP_3 {
|
|
||||||
debug!("HTTP/3 is currently unsupported for request to upstream. Use HTTP/2.");
|
|
||||||
*req.version_mut() = Version::HTTP_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(req)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ pub(super) fn append_header_entry(
|
||||||
pub(super) fn add_forwarding_header(
|
pub(super) fn add_forwarding_header(
|
||||||
headers: &mut HeaderMap,
|
headers: &mut HeaderMap,
|
||||||
client_addr: SocketAddr,
|
client_addr: SocketAddr,
|
||||||
|
tls: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// default process
|
// default process
|
||||||
// optional process defined by upstream_option is applied in fn apply_upstream_options
|
// optional process defined by upstream_option is applied in fn apply_upstream_options
|
||||||
|
|
@ -57,6 +58,11 @@ pub(super) fn add_forwarding_header(
|
||||||
"x-forwarded-for",
|
"x-forwarded-for",
|
||||||
&client_addr.to_canonical().ip().to_string(),
|
&client_addr.to_canonical().ip().to_string(),
|
||||||
)?;
|
)?;
|
||||||
|
append_header_entry(
|
||||||
|
headers,
|
||||||
|
"x-forwarded-proto",
|
||||||
|
if tls { "https" } else { "http" },
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue