Skip to content

Commit

Permalink
Move to service level
Browse files Browse the repository at this point in the history
  • Loading branch information
howardjohn committed Jun 20, 2024
1 parent 2cb4dfb commit fd058fc
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
33 changes: 26 additions & 7 deletions src/dns/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use crate::dns::resolver::{Answer, Resolver};
use crate::metrics::{DeferRecorder, IncrementRecorder, Recorder};
use crate::proxy::Error;
use crate::socket::to_canonical;
use crate::state::service::IpFamily;
use crate::state::workload::address::Address;
use crate::state::workload::{NetworkAddress, Workload};
use crate::state::DemandProxyState;
Expand Down Expand Up @@ -425,15 +426,11 @@ impl Store {
Address::Service(service) => {
if service.vips.is_empty() {
// Headless service. Use the endpoint IPs.
let family = service.ip_families;
service
.endpoints
.iter()
.filter_map(|(_, ep)| match &ep.address {
Some(addr) => {
if let Some(false) = family.map(|f| f.accepts_ip(addr.address)) {
return None;
}
if is_record_type(&addr.address, record_type) {
Some(addr.address)
} else {
Expand Down Expand Up @@ -566,12 +563,18 @@ impl Resolver for Store {
source: Some(&client),
});

// Get the addresses for the service.
let addresses = self.get_addresses(&client, &service_match.server, record_type);

// From this point on, we are the authority for the response.
let is_authoritative = true;

if !service_family_allowed(&service_match.server, record_type) {
debug!(alias=%service_match.alias, %record_type, ans=?Answer::new(Vec::default(), is_authoritative), "service does not support this record type");
// This is not NXDOMAIN, since we found the host. Just return an empty set of records.
return Ok(Answer::new(Vec::default(), is_authoritative));
}

// Get the addresses for the service.
let addresses = self.get_addresses(&client, &service_match.server, record_type);

if addresses.is_empty() {
debug!(alias=%service_match.alias, name=%service_match.name, "no records");
// Lookup succeeded, but no records were returned. This is not NXDOMAIN, since we
Expand Down Expand Up @@ -622,6 +625,22 @@ impl Resolver for Store {
}
}

/// service_family_allowed indicates whether the service supports the given record type.
/// This is primarily to support headless services; an IPv4 only service should only have IPv4 addresses
/// anyway, so would naturally work.
/// Headless services, however, do not have VIPs, and the Pods behind them can have dual stack IPs even with
/// the Service being single-stack. In this case, we are NOT supposed to return both IPs.
fn service_family_allowed(server: &Address, record_type: RecordType) -> bool {
match server {
Address::Service(service) => match service.ip_families {
Some(IpFamily::IPv4) if record_type == RecordType::AAAA => false,
Some(IpFamily::IPv6) if record_type == RecordType::A => false,
_ => true,
},
_ => true,
}
}

/// An alias for the requested hostname.
#[derive(Debug)]
struct Alias {
Expand Down
29 changes: 9 additions & 20 deletions src/proxy/outbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1024,12 +1024,7 @@ mod tests {
tunnel_protocol: 1,
services: std::collections::HashMap::from([(
"/example.com".to_string(),
PortList {
ports: vec![Port {
service_port: 80,
target_port: 1234,
}],
},
PortList { ports: vec![] },
)]),
..Default::default()
});
Expand All @@ -1046,16 +1041,10 @@ mod tests {
address: "::3".parse::<Ipv6Addr>().unwrap().octets().into(),
},
],
ports: vec![
Port {
service_port: 80,
target_port: 0, // named port
},
Port {
service_port: 8080,
target_port: 0, // named port
},
],
ports: vec![Port {
service_port: 80,
target_port: 80,
}],
..Default::default()
};
s.set_ip_families(f);
Expand All @@ -1068,7 +1057,7 @@ mod tests {
vec![svc(IpFamilies::Ipv6Only), workload.clone()],
Some(ExpectedRequest {
protocol: Protocol::HBONE,
hbone_destination: "[ff06::c3]:1234",
hbone_destination: "[ff06::c3]:80",
destination: "[ff06::c3]:15008",
}),
)
Expand All @@ -1080,7 +1069,7 @@ mod tests {
vec![svc(IpFamilies::Ipv4Only), workload.clone()],
Some(ExpectedRequest {
protocol: Protocol::HBONE,
hbone_destination: "127.0.0.2:1234",
hbone_destination: "127.0.0.2:80",
destination: "127.0.0.2:15008",
}),
)
Expand All @@ -1092,7 +1081,7 @@ mod tests {
vec![svc(IpFamilies::Dual), workload.clone()],
Some(ExpectedRequest {
protocol: Protocol::HBONE,
hbone_destination: "127.0.0.2:1234",
hbone_destination: "127.0.0.2:80",
destination: "127.0.0.2:15008",
}),
)
Expand All @@ -1104,7 +1093,7 @@ mod tests {
vec![svc(IpFamilies::Dual), workload.clone()],
Some(ExpectedRequest {
protocol: Protocol::HBONE,
hbone_destination: "[ff06::c3]:1234",
hbone_destination: "[ff06::c3]:80",
destination: "[ff06::c3]:15008",
}),
)
Expand Down

0 comments on commit fd058fc

Please sign in to comment.