mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
add restricted nat retries
This commit is contained in:
parent
21548771ab
commit
e0a52bceb1
@ -105,108 +105,143 @@ impl Network {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_udpv4_dialinfo_task_routine(self, l: u64, t: u64) -> Result<(), String> {
|
pub async fn update_udpv4_dialinfo_task_routine(self, _l: u64, _t: u64) -> Result<(), String> {
|
||||||
trace!("looking for udpv4 public dial info");
|
trace!("looking for udpv4 public dial info");
|
||||||
let routing_table = self.routing_table();
|
let routing_table = self.routing_table();
|
||||||
|
|
||||||
|
let mut retry_count = {
|
||||||
|
let c = self.config.get();
|
||||||
|
c.network.restricted_nat_retries
|
||||||
|
};
|
||||||
|
|
||||||
// Get our local address
|
// Get our local address
|
||||||
let local1 = self.discover_local_address(ProtocolAddressType::UDPv4)?;
|
let local1 = self.discover_local_address(ProtocolAddressType::UDPv4)?;
|
||||||
// Get our external address from some fast node, call it node B
|
|
||||||
let (external1, node_b) = self
|
|
||||||
.discover_external_address(ProtocolAddressType::UDPv4, None)
|
|
||||||
.await?;
|
|
||||||
let external1_dial_info = DialInfo::udp_from_socketaddr(external1);
|
|
||||||
|
|
||||||
// If local1 == external1 then there is no NAT in place
|
// Loop for restricted NAT retries
|
||||||
if local1 == external1 {
|
loop {
|
||||||
// No NAT
|
// Get our external address from some fast node, call it node B
|
||||||
// Do a validate_dial_info on the external address from a routed node
|
let (external1, node_b) = self
|
||||||
if self
|
.discover_external_address(ProtocolAddressType::UDPv4, None)
|
||||||
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
.await?;
|
||||||
.await
|
let external1_dial_info = DialInfo::udp_from_socketaddr(external1);
|
||||||
{
|
|
||||||
// Add public dial info with Server network class
|
|
||||||
routing_table.register_public_dial_info(
|
|
||||||
external1_dial_info,
|
|
||||||
Some(NetworkClass::Server),
|
|
||||||
DialInfoOrigin::Discovered,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// UDP firewall?
|
|
||||||
warn!("UDP static public dial info not reachable. UDP firewall may be blocking inbound to {:?} for {:?}",external1_dial_info, node_b);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// There is -some NAT-
|
|
||||||
// Attempt a UDP port mapping via all available and enabled mechanisms
|
|
||||||
if let Some(external_mapped) = self
|
|
||||||
.try_port_mapping(local1.clone(), ProtocolAddressType::UDPv4)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
// Got a port mapping, let's use it
|
|
||||||
let external_mapped_dial_info = DialInfo::udp_from_socketaddr(external_mapped);
|
|
||||||
routing_table.register_public_dial_info(
|
|
||||||
external_mapped_dial_info,
|
|
||||||
Some(NetworkClass::Mapped),
|
|
||||||
DialInfoOrigin::Mapped,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Port mapping was not possible, let's see what kind of NAT we have
|
|
||||||
|
|
||||||
// Does a redirected dial info validation find us?
|
// If local1 == external1 then there is no NAT in place
|
||||||
|
if local1 == external1 {
|
||||||
|
// No NAT
|
||||||
|
// Do a validate_dial_info on the external address from a routed node
|
||||||
if self
|
if self
|
||||||
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
.validate_dial_info(node_b.clone(), external1_dial_info.clone(), true, false)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
// Yes, another machine can use the dial info directly, so Full Cone
|
// Add public dial info with Server network class
|
||||||
// Add public dial info with full cone NAT network class
|
|
||||||
routing_table.register_public_dial_info(
|
routing_table.register_public_dial_info(
|
||||||
external1_dial_info,
|
external1_dial_info,
|
||||||
Some(NetworkClass::FullNAT),
|
Some(NetworkClass::Server),
|
||||||
DialInfoOrigin::Discovered,
|
DialInfoOrigin::Discovered,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
// No, we are restricted, determine what kind of restriction
|
|
||||||
|
|
||||||
// Get our external address from some fast node, that is not node B, call it node D
|
// No more retries
|
||||||
let (external2, node_d) = self
|
break;
|
||||||
.discover_external_address(
|
} else {
|
||||||
ProtocolAddressType::UDPv4,
|
// UDP firewall?
|
||||||
Some(node_b.node_id()),
|
warn!("UDP static public dial info not reachable. UDP firewall may be blocking inbound to {:?} for {:?}",external1_dial_info, node_b);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is -some NAT-
|
||||||
|
// Attempt a UDP port mapping via all available and enabled mechanisms
|
||||||
|
if let Some(external_mapped) = self
|
||||||
|
.try_port_mapping(local1.clone(), ProtocolAddressType::UDPv4)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Got a port mapping, let's use it
|
||||||
|
let external_mapped_dial_info = DialInfo::udp_from_socketaddr(external_mapped);
|
||||||
|
routing_table.register_public_dial_info(
|
||||||
|
external_mapped_dial_info,
|
||||||
|
Some(NetworkClass::Mapped),
|
||||||
|
DialInfoOrigin::Mapped,
|
||||||
|
);
|
||||||
|
|
||||||
|
// No more retries
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Port mapping was not possible, let's see what kind of NAT we have
|
||||||
|
|
||||||
|
// Does a redirected dial info validation find us?
|
||||||
|
if self
|
||||||
|
.validate_dial_info(
|
||||||
|
node_b.clone(),
|
||||||
|
external1_dial_info.clone(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
// If we have two different external addresses, then this is a symmetric NAT
|
{
|
||||||
if external2 != external1 {
|
// Yes, another machine can use the dial info directly, so Full Cone
|
||||||
// Symmetric NAT is outbound only, no public dial info will work
|
// Add public dial info with full cone NAT network class
|
||||||
self.inner.lock().network_class = Some(NetworkClass::OutboundOnly);
|
routing_table.register_public_dial_info(
|
||||||
|
external1_dial_info,
|
||||||
|
Some(NetworkClass::FullNAT),
|
||||||
|
DialInfoOrigin::Discovered,
|
||||||
|
);
|
||||||
|
|
||||||
|
// No more retries
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Address is the same, so it's address or port restricted
|
// No, we are restricted, determine what kind of restriction
|
||||||
let external2_dial_info = DialInfo::udp_from_socketaddr(external2);
|
|
||||||
// Do a validate_dial_info on the external address from a routed node
|
// Get our external address from some fast node, that is not node B, call it node D
|
||||||
if self
|
let (external2, node_d) = self
|
||||||
.validate_dial_info(
|
.discover_external_address(
|
||||||
node_d.clone(),
|
ProtocolAddressType::UDPv4,
|
||||||
external2_dial_info.clone(),
|
Some(node_b.node_id()),
|
||||||
false,
|
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
{
|
// If we have two different external addresses, then this is a symmetric NAT
|
||||||
// Got a reply from a non-default port, which means we're only address restricted
|
if external2 != external1 {
|
||||||
routing_table.register_public_dial_info(
|
// Symmetric NAT is outbound only, no public dial info will work
|
||||||
external1_dial_info,
|
self.inner.lock().network_class = Some(NetworkClass::OutboundOnly);
|
||||||
Some(NetworkClass::AddressRestrictedNAT),
|
|
||||||
DialInfoOrigin::Discovered,
|
// No more retries
|
||||||
);
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Didn't get a reply from a non-default port, which means we are also port restricted
|
// If we're going to end up as a restricted NAT of some sort
|
||||||
routing_table.register_public_dial_info(
|
// we should go through our retries before we assign a dial info
|
||||||
external1_dial_info,
|
if retry_count == 0 {
|
||||||
Some(NetworkClass::PortRestrictedNAT),
|
// Address is the same, so it's address or port restricted
|
||||||
DialInfoOrigin::Discovered,
|
let external2_dial_info = DialInfo::udp_from_socketaddr(external2);
|
||||||
);
|
// Do a validate_dial_info on the external address from a routed node
|
||||||
|
if self
|
||||||
|
.validate_dial_info(
|
||||||
|
node_d.clone(),
|
||||||
|
external2_dial_info.clone(),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Got a reply from a non-default port, which means we're only address restricted
|
||||||
|
routing_table.register_public_dial_info(
|
||||||
|
external1_dial_info,
|
||||||
|
Some(NetworkClass::AddressRestrictedNAT),
|
||||||
|
DialInfoOrigin::Discovered,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Didn't get a reply from a non-default port, which means we are also port restricted
|
||||||
|
routing_table.register_public_dial_info(
|
||||||
|
external1_dial_info,
|
||||||
|
Some(NetworkClass::PortRestrictedNAT),
|
||||||
|
DialInfoOrigin::Discovered,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if retry_count == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retry_count -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +183,7 @@ pub fn config_callback(key: String) -> Result<Box<dyn core::any::Any>, String> {
|
|||||||
"network.upnp" => Ok(Box::new(false)),
|
"network.upnp" => Ok(Box::new(false)),
|
||||||
"network.natpmp" => Ok(Box::new(false)),
|
"network.natpmp" => Ok(Box::new(false)),
|
||||||
"network.address_filter" => Ok(Box::new(true)),
|
"network.address_filter" => Ok(Box::new(true)),
|
||||||
|
"network.restricted_nat_retries" => Ok(Box::new(3u32)),
|
||||||
"network.tls.certificate_path" => Ok(Box::new(get_certfile_path())),
|
"network.tls.certificate_path" => Ok(Box::new(get_certfile_path())),
|
||||||
"network.tls.private_key_path" => Ok(Box::new(get_keyfile_path())),
|
"network.tls.private_key_path" => Ok(Box::new(get_keyfile_path())),
|
||||||
"network.tls.connection_initial_timeout" => Ok(Box::new(2_000_000u64)),
|
"network.tls.connection_initial_timeout" => Ok(Box::new(2_000_000u64)),
|
||||||
@ -270,6 +271,7 @@ pub async fn test_config() {
|
|||||||
assert_eq!(inner.network.upnp, false);
|
assert_eq!(inner.network.upnp, false);
|
||||||
assert_eq!(inner.network.natpmp, false);
|
assert_eq!(inner.network.natpmp, false);
|
||||||
assert_eq!(inner.network.address_filter, true);
|
assert_eq!(inner.network.address_filter, true);
|
||||||
|
assert_eq!(inner.network.restricted_nat_retries, 3u32);
|
||||||
assert_eq!(inner.network.tls.certificate_path, get_certfile_path());
|
assert_eq!(inner.network.tls.certificate_path, get_certfile_path());
|
||||||
assert_eq!(inner.network.tls.private_key_path, get_keyfile_path());
|
assert_eq!(inner.network.tls.private_key_path, get_keyfile_path());
|
||||||
assert_eq!(inner.network.tls.connection_initial_timeout, 2_000_000u64);
|
assert_eq!(inner.network.tls.connection_initial_timeout, 2_000_000u64);
|
||||||
|
@ -128,6 +128,7 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub upnp: bool,
|
pub upnp: bool,
|
||||||
pub natpmp: bool,
|
pub natpmp: bool,
|
||||||
pub address_filter: bool,
|
pub address_filter: bool,
|
||||||
|
pub restricted_nat_retries: u32,
|
||||||
pub tls: VeilidConfigTLS,
|
pub tls: VeilidConfigTLS,
|
||||||
pub application: VeilidConfigApplication,
|
pub application: VeilidConfigApplication,
|
||||||
pub protocol: VeilidConfigProtocol,
|
pub protocol: VeilidConfigProtocol,
|
||||||
@ -222,6 +223,7 @@ impl VeilidConfig {
|
|||||||
get_config!(inner.network.upnp);
|
get_config!(inner.network.upnp);
|
||||||
get_config!(inner.network.natpmp);
|
get_config!(inner.network.natpmp);
|
||||||
get_config!(inner.network.address_filter);
|
get_config!(inner.network.address_filter);
|
||||||
|
get_config!(inner.network.restricted_nat_retries);
|
||||||
get_config!(inner.network.tls.certificate_path);
|
get_config!(inner.network.tls.certificate_path);
|
||||||
get_config!(inner.network.tls.private_key_path);
|
get_config!(inner.network.tls.private_key_path);
|
||||||
get_config!(inner.network.tls.connection_initial_timeout);
|
get_config!(inner.network.tls.connection_initial_timeout);
|
||||||
|
@ -63,6 +63,7 @@ core:
|
|||||||
upnp: false
|
upnp: false
|
||||||
natpmp: false
|
natpmp: false
|
||||||
address_filter: true
|
address_filter: true
|
||||||
|
restricted_nat_retries: 3
|
||||||
tls:
|
tls:
|
||||||
certificate_path: "/etc/veilid/server.crt"
|
certificate_path: "/etc/veilid/server.crt"
|
||||||
private_key_path: "/etc/veilid/private/server.key"
|
private_key_path: "/etc/veilid/private/server.key"
|
||||||
@ -391,6 +392,7 @@ pub struct Network {
|
|||||||
pub upnp: bool,
|
pub upnp: bool,
|
||||||
pub natpmp: bool,
|
pub natpmp: bool,
|
||||||
pub address_filter: bool,
|
pub address_filter: bool,
|
||||||
|
pub restricted_nat_retries: u32,
|
||||||
pub tls: TLS,
|
pub tls: TLS,
|
||||||
pub application: Application,
|
pub application: Application,
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
@ -638,6 +640,9 @@ impl Settings {
|
|||||||
"network.upnp" => Ok(Box::new(inner.core.network.upnp)),
|
"network.upnp" => Ok(Box::new(inner.core.network.upnp)),
|
||||||
"network.natpmp" => Ok(Box::new(inner.core.network.natpmp)),
|
"network.natpmp" => Ok(Box::new(inner.core.network.natpmp)),
|
||||||
"network.address_filter" => Ok(Box::new(inner.core.network.address_filter)),
|
"network.address_filter" => Ok(Box::new(inner.core.network.address_filter)),
|
||||||
|
"network.restricted_nat_retries" => {
|
||||||
|
Ok(Box::new(inner.core.network.restricted_nat_retries))
|
||||||
|
}
|
||||||
"network.tls.certificate_path" => Ok(Box::new(
|
"network.tls.certificate_path" => Ok(Box::new(
|
||||||
inner
|
inner
|
||||||
.core
|
.core
|
||||||
@ -869,6 +874,7 @@ mod tests {
|
|||||||
assert_eq!(s.core.network.upnp, false);
|
assert_eq!(s.core.network.upnp, false);
|
||||||
assert_eq!(s.core.network.natpmp, false);
|
assert_eq!(s.core.network.natpmp, false);
|
||||||
assert_eq!(s.core.network.address_filter, true);
|
assert_eq!(s.core.network.address_filter, true);
|
||||||
|
assert_eq!(s.core.network.restricted_nat_retries, 3u32);
|
||||||
//
|
//
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s.core.network.tls.certificate_path,
|
s.core.network.tls.certificate_path,
|
||||||
|
@ -120,6 +120,7 @@ impl JsVeilidCore {
|
|||||||
"network.upnp" => Self::value_to_bool(val),
|
"network.upnp" => Self::value_to_bool(val),
|
||||||
"network.natpmp" => Self::value_to_bool(val),
|
"network.natpmp" => Self::value_to_bool(val),
|
||||||
"network.address_filter" => Self::value_to_bool(val),
|
"network.address_filter" => Self::value_to_bool(val),
|
||||||
|
"network.restricted_nat_retries" => Self::value_to_u32(val),
|
||||||
"network.tls.certificate_path" => Self::value_to_string(val),
|
"network.tls.certificate_path" => Self::value_to_string(val),
|
||||||
"network.tls.private_key_path" => Self::value_to_string(val),
|
"network.tls.private_key_path" => Self::value_to_string(val),
|
||||||
"network.application.path" => Self::value_to_string(val),
|
"network.application.path" => Self::value_to_string(val),
|
||||||
|
@ -63,6 +63,7 @@ fn init_callbacks() {
|
|||||||
case "network.upnp": return false;
|
case "network.upnp": return false;
|
||||||
case "network.natpmp": return false;
|
case "network.natpmp": return false;
|
||||||
case "network.address_filter": return true;
|
case "network.address_filter": return true;
|
||||||
|
case "network.restricted_nat_retries": return 3;
|
||||||
case "network.tls.certificate_path": return "";
|
case "network.tls.certificate_path": return "";
|
||||||
case "network.tls.private_key_path": return "";
|
case "network.tls.private_key_path": return "";
|
||||||
case "network.application.path": return "/app";
|
case "network.application.path": return "/app";
|
||||||
|
Loading…
Reference in New Issue
Block a user