Skip to content

Commit 3f89e1b

Browse files
authored
outbound: Strip peer-sent l5d-proxy-error headers (#1285)
If the outbound proxy is not configured to emit headers, then we shouldn't surface `l5d-proxy-error` headers sent by peer proxies. This change adds a module to the outbound HTTP endpoint stack to strip these headers when appropriate.
1 parent 0e0e47a commit 3f89e1b

File tree

5 files changed

+62
-8
lines changed

5 files changed

+62
-8
lines changed

linkerd/app/outbound/src/http/endpoint.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{NewRequireIdentity, ProxyConnectionClose};
1+
use super::{NewRequireIdentity, NewStripProxyError, ProxyConnectionClose};
22
use crate::Outbound;
33
use linkerd_app_core::{
44
classify, config, errors, http_tracing, metrics,
@@ -49,6 +49,9 @@ impl<C> Outbound<C> {
4949
// Set the TLS status on responses so that the stack can detect whether the request
5050
// was sent over a meshed connection.
5151
.push_http_response_insert_target::<tls::ConditionalClientTls>()
52+
// If the outbound proxy is not configured to emit headers, then strip the
53+
// `l5d-proxy-errors` header if set by the peer.
54+
.push(NewStripProxyError::layer(config.emit_headers))
5255
// Tear down server connections when a peer proxy generates an error.
5356
// TODO(ver) this should only be honored when forwarding and not when the connection
5457
// is part of a balancer.

linkerd/app/outbound/src/http/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ pub mod logical;
44
mod proxy_connection_close;
55
mod require_id_header;
66
mod server;
7+
mod strip_proxy_error;
78

8-
use self::{proxy_connection_close::ProxyConnectionClose, require_id_header::NewRequireIdentity};
9+
use self::{
10+
proxy_connection_close::ProxyConnectionClose, require_id_header::NewRequireIdentity,
11+
strip_proxy_error::NewStripProxyError,
12+
};
913
pub(crate) use self::{require_id_header::IdentityRequired, server::ServerRescue};
1014
use crate::tcp;
1115
pub use linkerd_app_core::proxy::http::*;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use linkerd_app_core::{
2+
errors::respond::L5D_PROXY_ERROR,
3+
proxy::http,
4+
svc::{self, NewService},
5+
};
6+
7+
#[derive(Clone, Debug)]
8+
pub struct NewStripProxyError<N> {
9+
strip: bool,
10+
inner: N,
11+
}
12+
13+
impl<N> NewStripProxyError<N> {
14+
pub fn layer(emit_headers: bool) -> impl svc::layer::Layer<N, Service = Self> + Clone {
15+
svc::layer::mk(move |inner| Self {
16+
strip: !emit_headers,
17+
inner,
18+
})
19+
}
20+
}
21+
22+
impl<T, N> NewService<T> for NewStripProxyError<N>
23+
where
24+
N: NewService<T>,
25+
{
26+
type Service = svc::Either<
27+
N::Service,
28+
http::strip_header::response::StripHeader<&'static str, N::Service>,
29+
>;
30+
31+
fn new_service(&self, target: T) -> Self::Service {
32+
let inner = self.inner.new_service(target);
33+
34+
if self.strip {
35+
return svc::Either::B(http::StripHeader::response(L5D_PROXY_ERROR, inner));
36+
};
37+
38+
svc::Either::A(inner)
39+
}
40+
}

linkerd/proxy/http/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub use self::{
3333
override_authority::{AuthorityOverride, NewOverrideAuthority},
3434
retain::Retain,
3535
server::NewServeHttp,
36+
strip_header::StripHeader,
3637
timeout::{NewTimeout, ResponseTimeout, ResponseTimeoutError},
3738
version::Version,
3839
};

linkerd/proxy/http/src/strip_header.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,13 @@ pub mod response {
9797
/// stripped.
9898
pub enum RspHeader {}
9999

100-
type StripHeader<H, S> = super::StripHeader<H, S, RspHeader>;
100+
pub type StripHeader<H, S> = super::StripHeader<H, S, RspHeader>;
101101

102102
pub fn layer<H, S>(header: H) -> impl layer::Layer<S, Service = StripHeader<H, S>> + Clone
103103
where
104104
H: AsHeaderName + Clone,
105105
{
106-
layer::mk(move |inner| StripHeader {
107-
inner,
108-
header: header.clone(),
109-
_marker: PhantomData,
110-
})
106+
layer::mk(move |inner| StripHeader::response(header.clone(), inner))
111107
}
112108

113109
#[pin_project]
@@ -117,6 +113,16 @@ pub mod response {
117113
header: H,
118114
}
119115

116+
impl<H, S> StripHeader<H, S> {
117+
pub fn response(header: H, inner: S) -> Self {
118+
Self {
119+
inner,
120+
header,
121+
_marker: PhantomData,
122+
}
123+
}
124+
}
125+
120126
impl<H, S, B, Req> tower::Service<Req> for StripHeader<H, S>
121127
where
122128
H: AsHeaderName + Clone,

0 commit comments

Comments
 (0)