From 362fbcf90fdd136d58525d7e30ad53fb280b0d6f Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Wed, 1 Nov 2017 18:56:59 -0400 Subject: [PATCH] Proper p2p remote address detection when accepting conn A receiving peer trusts the address advertised by a client. However as we do not have external address detection (and there is generally no very good way to do that), the address detected by a peer is the loopback, which is useless. So we attempt to detect these cases and use the IP detected by the TCP connection while keeping the advertised port. --- p2p/src/handshake.rs | 27 ++++++++++++++++++++++++++- p2p/src/msg.rs | 6 ++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/p2p/src/handshake.rs b/p2p/src/handshake.rs index 1829c8a50..1f355b231 100644 --- a/p2p/src/handshake.rs +++ b/p2p/src/handshake.rs @@ -124,11 +124,12 @@ impl Handshake { })); } } + // all good, keep peer info let peer_info = PeerInfo { capabilities: hand.capabilities, user_agent: hand.user_agent, - addr: hand.sender_addr.0, + addr: extract_ip(&hand.sender_addr.0, &conn), version: hand.version, total_difficulty: hand.total_difficulty, }; @@ -163,3 +164,27 @@ impl Handshake { nonce } } + +// Attempts to make a best guess at the correct remote IP by checking if the +// advertised address is the loopback and our TCP connection. Note that the +// port reported by the connection is always incorrect for receiving +// connections as it's dynamically allocated by the server. +fn extract_ip(advertised: &SocketAddr, conn: &TcpStream) -> SocketAddr { + match advertised { + &SocketAddr::V4(v4sock) => { + if v4sock.ip().is_loopback() { + if let Ok(addr) = conn.peer_addr() { + return SocketAddr::new(addr.ip(), advertised.port()); + } + } + } + &SocketAddr::V6(v6sock) => { + if v6sock.ip().is_loopback() { + if let Ok(addr) = conn.peer_addr() { + return SocketAddr::new(addr.ip(), advertised.port()); + } + } + } + } + advertised.clone() +} diff --git a/p2p/src/msg.rs b/p2p/src/msg.rs index 4a39a5d2c..41d50b77f 100644 --- a/p2p/src/msg.rs +++ b/p2p/src/msg.rs @@ -190,8 +190,7 @@ pub struct Hand { /// randomly generated for each handshake, helps detect self pub nonce: u64, /// total difficulty accumulated by the sender, used to check whether sync - /// may - /// be needed + /// may be needed pub total_difficulty: Difficulty, /// network address of the sender pub sender_addr: SockAddr, @@ -245,8 +244,7 @@ pub struct Shake { /// sender capabilities pub capabilities: Capabilities, /// total difficulty accumulated by the sender, used to check whether sync - /// may - /// be needed + /// may be needed pub total_difficulty: Difficulty, /// name of version of the software pub user_agent: String,