diff --git a/src/config.rs b/src/config.rs index b1ccc876..346cb14c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -92,6 +92,13 @@ pub struct Config { /// will last indefinitely. Default is 1 hour. pub ban_duration: Option, + /// Allows connections from nodes who have set their ENR to a specific IP address which is not + /// the same as the incoming packet. We will respond to requests via the ENR IP address, not + /// the address that is sending the packets. This is useful for asymmetric connections + /// where a node may send from one IP address but receive traffic on another. + /// The default value is false. + pub permit_invalid_enr: bool, + /// A custom executor which can spawn the discv5 tasks. This must be a tokio runtime, with /// timing support. By default, the executor that created the discv5 struct will be used. pub executor: Option>, @@ -141,6 +148,7 @@ impl ConfigBuilder { filter_max_bans_per_ip: Some(5), permit_ban_list: PermitBanList::default(), ban_duration: Some(Duration::from_secs(3600)), // 1 hour + permit_invalid_enr: false, executor: None, listen_config, }; @@ -295,6 +303,16 @@ impl ConfigBuilder { self } + /// Allows connections from nodes who have set their ENR to a specific IP address which is not + /// the same as the incoming packet. We will respond to requests via the ENR IP address, not + /// the address that is sending the packets. This is useful for asymmetric connections + /// where a node may send from one IP address but receive traffic on another. + /// The default value is false. + pub fn permit_invalid_enr(&mut self) -> &mut Self { + self.config.permit_invalid_enr = true; + self + } + /// A custom executor which can spawn the discv5 tasks. This must be a tokio runtime, with /// timing support. pub fn executor(&mut self, executor: Box) -> &mut Self { @@ -334,6 +352,7 @@ impl std::fmt::Debug for Config { .field("ip_limit", &self.ip_limit) .field("incoming_bucket_limit", &self.incoming_bucket_limit) .field("ping_interval", &self.ping_interval) + .field("permit_invalid_enr", &self.permit_invalid_enr) .field("ban_duration", &self.ban_duration) .field("listen_config", &self.listen_config) .finish() diff --git a/src/handler/mod.rs b/src/handler/mod.rs index f67f8c3c..34036f8c 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -226,6 +226,9 @@ pub struct Handler { listen_sockets: SmallVec<[SocketAddr; 2]>, /// The discovery v5 UDP socket tasks. socket: Socket, + /// Permits connections from nodes that have ENR socket addresses set different from the + /// observed address of the packet. + permit_invalid_enr: bool, /// Exit channel to shutdown the handler. exit: oneshot::Receiver<()>, } @@ -317,6 +320,7 @@ impl Handler { service_send, listen_sockets, socket, + permit_invalid_enr: config.permit_invalid_enr, exit, }; debug!("Handler Starting"); @@ -852,7 +856,7 @@ impl Handler { self.remove_expected_response(node_address.socket_addr); // Receiving an AuthResponse must give us an up-to-date view of the node ENR. // Verify the ENR is valid - if self.verify_enr(&enr, &node_address) { + if self.permit_invalid_enr || self.verify_enr(&enr, &node_address) { // Session is valid // Notify the application // The session established here are from WHOAREYOU packets that we sent. @@ -1129,7 +1133,9 @@ impl Handler { ResponseBody::Nodes { mut nodes, .. } => { // Received the requested ENR if let Some(enr) = nodes.pop() { - if self.verify_enr(&enr, &node_address) { + if self.permit_invalid_enr + || self.verify_enr(&enr, &node_address) + { // Notify the application // This can occur when we try to dial a node without an // ENR. In this case we have attempted to establish the diff --git a/src/handler/tests.rs b/src/handler/tests.rs index a2bc9565..1a4381e8 100644 --- a/src/handler/tests.rs +++ b/src/handler/tests.rs @@ -85,6 +85,7 @@ async fn build_handler( active_challenges: HashMapDelay::new(config.request_timeout), service_recv, service_send, + permit_invalid_enr: false, listen_sockets, socket, exit,