diff --git a/p2p/base/p2ptransportchannel_unittest.cc b/p2p/base/p2ptransportchannel_unittest.cc index fadcb0a338..03a31032c0 100644 --- a/p2p/base/p2ptransportchannel_unittest.cc +++ b/p2p/base/p2ptransportchannel_unittest.cc @@ -4761,6 +4761,8 @@ TEST_F(P2PTransportChannelTest, CanConnectWithHostCandidateWithMDnsName) { // with a peer reflexive candidate from ep2. ASSERT_TRUE_WAIT((ep1_ch1()->selected_connection()) != nullptr, kMediumTimeout); + EXPECT_EQ(LOCAL_PORT_TYPE, + ep1_ch1()->selected_connection()->local_candidate().type()); EXPECT_EQ(PRFLX_PORT_TYPE, ep1_ch1()->selected_connection()->remote_candidate().type()); diff --git a/p2p/base/port.cc b/p2p/base/port.cc index 095b3a6d02..1fe7305fa2 100644 --- a/p2p/base/port.cc +++ b/p2p/base/port.cc @@ -440,6 +440,11 @@ void Port::AddAddress(const rtc::SocketAddress& address, const std::string& name) mutable { RTC_DCHECK(c.address().ipaddr() == addr); rtc::SocketAddress hostname_address(name, c.address().port()); + // In Port and Connection, we need the IP address information to + // correctly handle the update of candidate type to prflx. The removal + // of IP address when signaling this candidate will take place in + // BasicPortAllocatorSession::OnCandidateReady, via SanitizeCandidate. + hostname_address.SetResolvedIP(addr); c.set_address(hostname_address); RTC_DCHECK(c.related_address() == rtc::SocketAddress()); if (weak_ptr != nullptr) { diff --git a/p2p/client/basicportallocator.cc b/p2p/client/basicportallocator.cc index 5b48f5e9d7..92c8338eb5 100644 --- a/p2p/client/basicportallocator.cc +++ b/p2p/client/basicportallocator.cc @@ -496,13 +496,21 @@ void BasicPortAllocatorSession::GetCandidatesFromPort( if (!CheckCandidateFilter(candidate)) { continue; } - candidates->push_back(SanitizeRelatedAddress(candidate)); + auto sanitized_candidate = SanitizeCandidate(candidate); + candidates->push_back(sanitized_candidate); } } -Candidate BasicPortAllocatorSession::SanitizeRelatedAddress( +Candidate BasicPortAllocatorSession::SanitizeCandidate( const Candidate& c) const { Candidate copy = c; + // If the candidate has a generated hostname, we need to obfuscate its IP + // address when signaling this candidate. + if (!c.address().hostname().empty() && !c.address().IsUnresolvedIP()) { + rtc::SocketAddress hostname_only_addr(c.address().hostname(), + c.address().port()); + copy.set_address(hostname_only_addr); + } // If adapter enumeration is disabled or host candidates are disabled, // clear the raddr of STUN candidates to avoid local address leakage. bool filter_stun_related_address = @@ -916,7 +924,7 @@ void BasicPortAllocatorSession::OnCandidateReady(Port* port, if (data->ready() && CheckCandidateFilter(c)) { std::vector candidates; - candidates.push_back(SanitizeRelatedAddress(c)); + candidates.push_back(SanitizeCandidate(c)); SignalCandidatesReady(this, candidates); } else { RTC_LOG(LS_INFO) << "Discarding candidate because it doesn't match filter."; diff --git a/p2p/client/basicportallocator.h b/p2p/client/basicportallocator.h index 07bf2f99b8..8b951cae9e 100644 --- a/p2p/client/basicportallocator.h +++ b/p2p/client/basicportallocator.h @@ -235,9 +235,10 @@ class BasicPortAllocatorSession : public PortAllocatorSession, bool CheckCandidateFilter(const Candidate& c) const; bool CandidatePairable(const Candidate& c, const Port* port) const; - // Clear the related address according to the flags and candidate filter - // in order to avoid leaking any information. - Candidate SanitizeRelatedAddress(const Candidate& c) const; + // Clears 1) the address if the candidate is supposedly a hostname candidate; + // 2) the related address according to the flags and candidate filter in order + // to avoid leaking any information. + Candidate SanitizeCandidate(const Candidate& c) const; std::vector GetUnprunedPorts( const std::vector& networks);