mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
p2pnet: validate external address of inbound connection
This commit is contained in:
@@ -279,6 +279,7 @@ impl Channel {
|
||||
message_subsystem.add_dispatch::<message::PongMessage>().await;
|
||||
message_subsystem.add_dispatch::<message::GetAddrsMessage>().await;
|
||||
message_subsystem.add_dispatch::<message::AddrsMessage>().await;
|
||||
message_subsystem.add_dispatch::<message::ExtAddrsMessage>().await;
|
||||
}
|
||||
|
||||
/// Convenience function that returns the Message Subsystem.
|
||||
|
||||
@@ -48,7 +48,20 @@ impl Hosts {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add single host store, which also checks that resolved ips are the same as the connection
|
||||
/// Add a new hosts external adders to the host list, after filtering and verifying
|
||||
/// the address url resolves to the provided connection address.
|
||||
pub async fn store_ext(&self, connection_addr: Url, input_addrs: Vec<Url>) {
|
||||
let addrs = if !self.localnet {
|
||||
let filtered = filter_localnet(input_addrs);
|
||||
let filtered = filter_invalid(&self.ipv4_range, &self.ipv6_range, filtered);
|
||||
filter_non_resolving(connection_addr, filtered)
|
||||
} else {
|
||||
input_addrs
|
||||
};
|
||||
for addr in addrs {
|
||||
self.addrs.lock().await.insert(addr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the list of hosts.
|
||||
pub async fn load_all(&self) -> Vec<Url> {
|
||||
@@ -135,6 +148,64 @@ fn filter_invalid(
|
||||
filtered
|
||||
}
|
||||
|
||||
/// Auxiliary function to filter unresolvable hosts, based on provided connection addr (excluding onion).
|
||||
fn filter_non_resolving(connection_addr: Url, input_addrs: Vec<Url>) -> Vec<Url> {
|
||||
let connection_domain = connection_addr.domain().unwrap();
|
||||
// Validate connection onion domain
|
||||
if connection_domain.ends_with(".onion") && !is_valid_onion(connection_domain) {
|
||||
return vec![]
|
||||
}
|
||||
|
||||
// Retrieve connection IPs
|
||||
let mut ipv4_range = vec![];
|
||||
let mut ipv6_range = vec![];
|
||||
for i in connection_addr.socket_addrs(|| None).unwrap() {
|
||||
match i.ip() {
|
||||
IpAddr::V4(a) => {
|
||||
ipv4_range.push(a);
|
||||
}
|
||||
IpAddr::V6(a) => {
|
||||
ipv6_range.push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter input addresses
|
||||
let mut filtered = vec![];
|
||||
for addr in input_addrs {
|
||||
// Keep valid onion domains
|
||||
let addr_domain = addr.domain().unwrap();
|
||||
if addr_domain.ends_with(".onion") && addr_domain == connection_domain {
|
||||
filtered.push(addr.clone());
|
||||
continue
|
||||
}
|
||||
|
||||
// Checking IP validity
|
||||
let mut valid = true;
|
||||
let socket_addrs = addr.socket_addrs(|| None).unwrap();
|
||||
for i in socket_addrs {
|
||||
match i.ip() {
|
||||
IpAddr::V4(a) => {
|
||||
if !ipv4_range.contains(&a) {
|
||||
valid = false;
|
||||
break
|
||||
}
|
||||
}
|
||||
IpAddr::V6(a) => {
|
||||
if !ipv6_range.contains(&a) {
|
||||
valid = false;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if valid {
|
||||
filtered.push(addr.clone());
|
||||
}
|
||||
}
|
||||
filtered
|
||||
}
|
||||
|
||||
/// Auxiliary function to validate an onion.
|
||||
fn is_valid_onion(onion: &str) -> bool {
|
||||
let onion = match onion.strip_suffix(".onion") {
|
||||
|
||||
@@ -37,6 +37,12 @@ pub struct AddrsMessage {
|
||||
pub addrs: Vec<Url>,
|
||||
}
|
||||
|
||||
/// Sends external address information to inbound connection.
|
||||
#[derive(SerialEncodable, SerialDecodable)]
|
||||
pub struct ExtAddrsMessage {
|
||||
pub ext_addrs: Vec<Url>,
|
||||
}
|
||||
|
||||
/// Requests version information of outbound connection.
|
||||
#[derive(SerialEncodable, SerialDecodable)]
|
||||
pub struct VersionMessage {
|
||||
@@ -74,6 +80,12 @@ impl Message for AddrsMessage {
|
||||
}
|
||||
}
|
||||
|
||||
impl Message for ExtAddrsMessage {
|
||||
fn name() -> &'static str {
|
||||
"extaddr"
|
||||
}
|
||||
}
|
||||
|
||||
impl Message for VersionMessage {
|
||||
fn name() -> &'static str {
|
||||
"version"
|
||||
|
||||
@@ -20,6 +20,7 @@ const SEND_ADDR_SLEEP_SECONDS: u64 = 900;
|
||||
pub struct ProtocolAddress {
|
||||
channel: ChannelPtr,
|
||||
addrs_sub: MessageSubscription<message::AddrsMessage>,
|
||||
ext_addrs_sub: MessageSubscription<message::ExtAddrsMessage>,
|
||||
get_addrs_sub: MessageSubscription<message::GetAddrsMessage>,
|
||||
hosts: HostsPtr,
|
||||
jobsman: ProtocolJobsManagerPtr,
|
||||
@@ -27,8 +28,8 @@ pub struct ProtocolAddress {
|
||||
}
|
||||
|
||||
impl ProtocolAddress {
|
||||
/// Create a new address protocol. Makes an address and get-address
|
||||
/// subscription and adds them to the address protocol instance.
|
||||
/// Create a new address protocol. Makes an address, an external address
|
||||
/// and a get-address subscription and adds them to the address protocol instance.
|
||||
pub async fn init(channel: ChannelPtr, p2p: P2pPtr) -> ProtocolBasePtr {
|
||||
let settings = p2p.settings();
|
||||
let hosts = p2p.hosts();
|
||||
@@ -40,6 +41,13 @@ impl ProtocolAddress {
|
||||
.await
|
||||
.expect("Missing addrs dispatcher!");
|
||||
|
||||
// Creates a subscription to external address message.
|
||||
let ext_addrs_sub = channel
|
||||
.clone()
|
||||
.subscribe_msg::<message::ExtAddrsMessage>()
|
||||
.await
|
||||
.expect("Missing ext_addrs dispatcher!");
|
||||
|
||||
// Creates a subscription to get-address message.
|
||||
let get_addrs_sub = channel
|
||||
.clone()
|
||||
@@ -50,6 +58,7 @@ impl ProtocolAddress {
|
||||
Arc::new(Self {
|
||||
channel: channel.clone(),
|
||||
addrs_sub,
|
||||
ext_addrs_sub,
|
||||
get_addrs_sub,
|
||||
hosts,
|
||||
jobsman: ProtocolJobsManager::new("ProtocolAddress", channel),
|
||||
@@ -69,6 +78,18 @@ impl ProtocolAddress {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles receiving the external address message. Loops to continually recieve
|
||||
/// external address messages on the address subsciption. Adds the recieved
|
||||
/// external addresses to the list of hosts.
|
||||
async fn handle_receive_ext_addrs(self: Arc<Self>) -> Result<()> {
|
||||
debug!(target: "net", "ProtocolAddress::handle_receive_ext_addrs() [START]");
|
||||
loop {
|
||||
let ext_addrs_msg = self.ext_addrs_sub.receive().await?;
|
||||
debug!(target: "net", "ProtocolAddress::handle_receive_ext_addrs() received {} addrs", ext_addrs_msg.ext_addrs.len());
|
||||
self.hosts.store_ext(self.channel.address(), ext_addrs_msg.ext_addrs.clone()).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles receiving the get-address message. Continually recieves
|
||||
/// get-address messages on the get-address subsciption. Then replies
|
||||
/// with an address message.
|
||||
@@ -92,9 +113,9 @@ impl ProtocolAddress {
|
||||
async fn send_my_addrs(self: Arc<Self>) -> Result<()> {
|
||||
debug!(target: "net", "ProtocolAddress::send_addrs() [START]");
|
||||
loop {
|
||||
let addrs = self.settings.external_addr.clone();
|
||||
let addr_msg = message::AddrsMessage { addrs };
|
||||
self.channel.clone().send(addr_msg).await?;
|
||||
let ext_addrs = self.settings.external_addr.clone();
|
||||
let ext_addr_msg = message::ExtAddrsMessage { ext_addrs };
|
||||
self.channel.clone().send(ext_addr_msg).await?;
|
||||
async_util::sleep(SEND_ADDR_SLEEP_SECONDS).await;
|
||||
}
|
||||
}
|
||||
@@ -118,6 +139,7 @@ impl ProtocolBase for ProtocolAddress {
|
||||
debug!(target: "net", "ProtocolAddress::start() [START]");
|
||||
self.jobsman.clone().start(executor.clone());
|
||||
self.jobsman.clone().spawn(self.clone().handle_receive_addrs(), executor.clone()).await;
|
||||
self.jobsman.clone().spawn(self.clone().handle_receive_ext_addrs(), executor.clone()).await;
|
||||
self.jobsman.clone().spawn(self.clone().handle_receive_get_addrs(), executor).await;
|
||||
|
||||
// Send get_address message.
|
||||
|
||||
@@ -46,10 +46,10 @@ impl ProtocolSeed {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let addrs = self.settings.external_addr.clone();
|
||||
debug!(target: "net", "ProtocolSeed::send_own_address() addrs={:?}", addrs);
|
||||
let addrs = message::AddrsMessage { addrs };
|
||||
self.channel.clone().send(addrs).await
|
||||
let ext_addrs = self.settings.external_addr.clone();
|
||||
debug!(target: "net", "ProtocolSeed::send_self_address() ext_addrs={:?}", ext_addrs);
|
||||
let ext_addr_msg = message::ExtAddrsMessage { ext_addrs };
|
||||
self.channel.clone().send(ext_addr_msg).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user