Src-IP in ME Routing + more strict bind_addresses

This commit is contained in:
Alexey
2026-03-14 02:20:51 +03:00
parent a15f74a6f9
commit 780fafa604
7 changed files with 206 additions and 30 deletions
+41 -5
View File
@@ -390,7 +390,7 @@ impl UpstreamManager {
out
}
fn resolve_bind_address(
pub(crate) fn resolve_bind_address(
interface: &Option<String>,
bind_addresses: &Option<Vec<String>>,
target: SocketAddr,
@@ -399,7 +399,7 @@ impl UpstreamManager {
) -> Option<IpAddr> {
let want_ipv6 = target.is_ipv6();
if let Some(addrs) = bind_addresses {
if let Some(addrs) = bind_addresses.as_ref().filter(|v| !v.is_empty()) {
let mut candidates: Vec<IpAddr> = addrs
.iter()
.filter_map(|s| s.parse::<IpAddr>().ok())
@@ -431,7 +431,7 @@ impl UpstreamManager {
warn!(
interface = %iface,
target = %target,
"Configured interface has no addresses for target family; falling back to direct connect without bind"
"Configured interface has no addresses for target family"
);
candidates.clear();
}
@@ -454,10 +454,11 @@ impl UpstreamManager {
warn!(
interface = interface.as_deref().unwrap_or(""),
target = %target,
"No valid bind_addresses left for interface; falling back to direct connect without bind"
"No valid bind_addresses left for interface"
);
return None;
}
return None;
}
if let Some(iface) = interface {
@@ -795,6 +796,13 @@ impl UpstreamManager {
bind_rr.as_deref(),
true,
);
if bind_ip.is_none()
&& bind_addresses.as_ref().is_some_and(|v| !v.is_empty())
{
return Err(ProxyError::Config(format!(
"No valid bind_addresses for target family {target}"
)));
}
let socket = create_outgoing_socket_bound(target, bind_ip)?;
if let Some(ip) = bind_ip {
@@ -1642,4 +1650,32 @@ mod tests {
};
assert!(!UpstreamManager::is_hard_connect_error(&error));
}
#[test]
fn resolve_bind_address_prefers_explicit_bind_ip() {
let target = "203.0.113.10:443".parse::<SocketAddr>().unwrap();
let bind = UpstreamManager::resolve_bind_address(
&Some("198.51.100.20".to_string()),
&Some(vec!["198.51.100.10".to_string()]),
target,
None,
true,
);
assert_eq!(bind, Some("198.51.100.10".parse::<IpAddr>().unwrap()));
}
#[test]
fn resolve_bind_address_does_not_fallback_to_interface_when_bind_addresses_present() {
let target = "203.0.113.10:443".parse::<SocketAddr>().unwrap();
let bind = UpstreamManager::resolve_bind_address(
&Some("198.51.100.20".to_string()),
&Some(vec!["2001:db8::10".to_string()]),
target,
None,
true,
);
assert_eq!(bind, None);
}
}