-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
basic sandwich #789
basic sandwich #789
Conversation
😊 Welcome @stevenctl! This is either your first contribution to the Istio ztunnel repo, or it's been You can learn more about the Istio working groups, Code of Conduct, and contribution guidelines Thanks for contributing! Courtesy of your friendly welcome wagon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
direction seems good
src/proxy/inbound.rs
Outdated
match Builder::with_addresses( | ||
Version::Two | Command::Proxy, | ||
Protocol::Stream, proxy_protocol). | ||
write_tlv(0xD0, id.as_bytes()).unwrap(). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is write_tlv infallible in this context?
src/proxy/inbound.rs
Outdated
if let Err(e) = super::copy_hbone( | ||
&mut upgraded, | ||
&mut stream, | ||
&metrics, | ||
transferred_bytes, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So even if we fail to write proxy proto headers for some reason we're going to try to press forward and I suppose it's up to the gateway to decide if that's ok or not. Would it be better to fail fast in zt or do we think most of the time this would be recoverable at the gateway somehow?
src/proxy/inbound.rs
Outdated
if addr.is_err() { | ||
info!("Sending 400, {:?}", addr.err()); | ||
return Ok(Response::builder() | ||
.status(StatusCode::BAD_REQUEST) | ||
.body(Empty::new()) | ||
.unwrap()); | ||
} | ||
|
||
let addr: SocketAddr = addr.unwrap(); | ||
if addr.ip() != conn.dst.ip() { | ||
info!("Sending 400, ip mismatch {addr} != {}", conn.dst); | ||
return Ok(Response::builder() | ||
.status(StatusCode::BAD_REQUEST) | ||
.body(Empty::new()) | ||
.unwrap()); | ||
} | ||
// Orig has 15008, swap with the real port | ||
let conn = Connection { dst: addr, ..conn }; | ||
let dst_network_addr = NetworkAddress { | ||
network: conn.dst_network.to_string(), // dst must be on our network | ||
address: addr.ip(), | ||
}; | ||
let Some((upstream, upstream_service)) = | ||
state.fetch_workload_services(&dst_network_addr).await | ||
else { | ||
info!(%conn, "unknown destination"); | ||
return Ok(Response::builder() | ||
.status(StatusCode::NOT_FOUND) | ||
.body(Empty::new()) | ||
.unwrap()); | ||
}; | ||
let has_waypoint = upstream.waypoint.is_some(); | ||
let from_waypoint = Self::check_waypoint(state.clone(), &upstream, &conn).await; | ||
let from_gateway = Self::check_gateway(state.clone(), &upstream, &conn).await; | ||
let addr: SocketAddr = addr.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitty: this looks a bit odd. I think you can let addr = match addr{...}
and it works Ok so long as arms that won't result in the desired type return.
@stevenctl Is there a proposal, i missed the context |
7c64261
to
28b50e7
Compare
See this doc (primarily the propagating L4 info section) and istio/istio#48362 The goal is to provide alternative Waypoint implementations with an option other than supporting CONNECT. |
src/proxy/outbound.rs
Outdated
) { | ||
(_, Ok(None)) => {} // workload doesn't have a waypoint; this is fine | ||
(true, _) => {} // we already traversed the waypoint | ||
(false, Ok(Some(waypoint_us))) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this branch (and the one for to Service) we're using the port WDS GatewayAddress sends us.
Line 423 in a17e43e
let waypoint_socket_address = SocketAddr::new(waypoint_ip, waypoint_us.port); |
Right now, the CP happens to send us 15008 which happens to be what the ztunnel listens on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the CP going to be smart and send the zTunnel address, or do we need to be smart and use pi.hbone_port
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now as per the protocol 15008 is "the" HBONE port and we assume that in other spots, I suspect.
For this I would suggest maybe splitting the difference and taking what CP sends us, but explicitly checking here that waypoint_us.port == pi.hbone_port
and throwing an error if not. If we wish to intentionally change that behavior in all of ambient later, we can actually remove the check.
cc @bleggett |
Makefile.core.mk
Outdated
@@ -11,6 +11,9 @@ endif | |||
test: | |||
RUST_BACKTRACE=1 cargo test --benches --tests --bins $(FEATURES) | |||
|
|||
test.root: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: +1 on adding RUST_BACKTRACE
here too, but without #821 this will just cause make test.root
to hang for people (unless they explicitly set BUILD_WITH_CONTAINER=0 - which is not the default)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. couple comments/questions
let from_waypoint = proxy::check_from_waypoint( | ||
pi.state.clone(), | ||
&upstream, | ||
conn.src_identity.as_ref(), | ||
&conn.src_ip, | ||
) | ||
.await; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't change anything just yet but not sure we need the check anymore per discussions around svc-addressed vs wl-addressed traffic. A user may have a waypoint for their service but still allow workload addressed without a waypoint and this would be considered valid so either inbound must take this type of configuration into account or elide checks that outbound ztunnel routing was correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I just don't want to take an opinion on that in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created this so I/we don't forget to circle back around on it until a user files a report that things don't work like we said they do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, all comments are theoretical future improvements so good to go ahead
return Some(None); | ||
}; | ||
|
||
// Validate that the HBONE target references the Waypoint we're connecting to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not 100% sure we will want to be this strict forever... but I cannot think of any concrete reasons why not to, and its easier to loosen later. So LGTm
src_ip: &IpAddr, | ||
) -> bool { | ||
let is_waypoint = |wl: &Workload| { | ||
Some(wl.identity()).as_ref() == src_identity && wl.workload_ips.contains(src_ip) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Long term it would be nice to have a method more reliable than source IP. That being said, since its node-local it would be quite strange for this check to not work somehow.
When the Waypoint is captured, zTunnel sees the connection address as the Waypoint's address and the HBONE address as the actual destination.
This impl currently uses that to detect whether the current connection is part of a sandwich, and verifies that the HBONE target actually references the connection address as a Waypoint. Instead of sending traffic to the HBONE target, we send it to the connection address.
Depends on #832 so the relevant commits are: https://github.com/istio/ztunnel/pull/789/files/b5af5ac0fb7e71805ee6f5b9fe56e8010511dead..a17e43e3488a4567c4c84eaae0638bf09d045c4d