Fix raddr on srflx and relay candidates

Bug: chromium:905690
Change-Id: Ic16d21672db5d456d7a9727ea5194ec26338c9d0
Reviewed-on: https://webrtc-review.googlesource.com/c/111441
Commit-Queue: Jeroen de Borst <jeroendb@webrtc.org>
Reviewed-by: Justin Uberti <juberti@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25810}
This commit is contained in:
Jeroen de Borst
2018-11-27 13:20:39 -08:00
committed by Commit Bot
parent 889b587226
commit 72d2ddd36f
5 changed files with 72 additions and 46 deletions

View File

@ -430,42 +430,50 @@ void Port::AddAddress(const rtc::SocketAddress& address,
c.set_network_name(network_->name());
c.set_network_type(network_->type());
c.set_url(url);
c.set_related_address(related_address);
bool pending = MaybeObfuscateAddress(&c, type, is_final);
if (!pending) {
FinishAddingAddress(c, is_final);
}
}
bool Port::MaybeObfuscateAddress(Candidate* c,
const std::string& type,
bool is_final) {
// TODO(bugs.webrtc.org/9723): Use a config to control the feature of IP
// handling with mDNS.
if (network_->GetMdnsResponder() != nullptr) {
// Obfuscate the IP address of a host candidates by an mDNS hostname.
if (type == LOCAL_PORT_TYPE) {
auto weak_ptr = weak_factory_.GetWeakPtr();
auto callback = [weak_ptr, c, is_final](const rtc::IPAddress& addr,
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) {
weak_ptr->set_mdns_name_registration_status(
MdnsNameRegistrationStatus::kCompleted);
weak_ptr->FinishAddingAddress(c, is_final);
}
};
set_mdns_name_registration_status(
MdnsNameRegistrationStatus::kInProgress);
network_->GetMdnsResponder()->CreateNameForAddress(c.address().ipaddr(),
callback);
return;
}
// For other types of candidates, the related address should be set to
// 0.0.0.0 or ::0.
c.set_related_address(rtc::SocketAddress());
} else {
c.set_related_address(related_address);
if (network_->GetMdnsResponder() == nullptr) {
return false;
}
FinishAddingAddress(c, is_final);
if (type != LOCAL_PORT_TYPE) {
return false;
}
auto copy = *c;
auto weak_ptr = weak_factory_.GetWeakPtr();
auto callback = [weak_ptr, copy, is_final](const rtc::IPAddress& addr,
const std::string& name) mutable {
RTC_DCHECK(copy.address().ipaddr() == addr);
rtc::SocketAddress hostname_address(name, copy.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);
copy.set_address(hostname_address);
copy.set_related_address(rtc::SocketAddress());
if (weak_ptr != nullptr) {
weak_ptr->set_mdns_name_registration_status(
MdnsNameRegistrationStatus::kCompleted);
weak_ptr->FinishAddingAddress(copy, is_final);
}
};
set_mdns_name_registration_status(MdnsNameRegistrationStatus::kInProgress);
network_->GetMdnsResponder()->CreateNameForAddress(copy.address().ipaddr(),
callback);
return true;
}
void Port::FinishAddingAddress(const Candidate& c, bool is_final) {

View File

@ -514,6 +514,10 @@ class Port : public PortInterface,
rtc::WeakPtrFactory<Port> weak_factory_;
bool MaybeObfuscateAddress(Candidate* c,
const std::string& type,
bool is_final);
friend class Connection;
};

View File

@ -518,6 +518,10 @@ void BasicPortAllocatorSession::GetCandidatesFromPort(
}
}
bool BasicPortAllocatorSession::MdnsObfuscationEnabled() const {
return allocator_->network_manager()->GetMdnsResponder() != nullptr;
}
Candidate BasicPortAllocatorSession::SanitizeCandidate(
const Candidate& c) const {
RTC_DCHECK_RUN_ON(network_thread_);
@ -534,7 +538,7 @@ Candidate BasicPortAllocatorSession::SanitizeCandidate(
bool filter_stun_related_address =
((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
(flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) ||
!(candidate_filter_ & CF_HOST);
!(candidate_filter_ & CF_HOST) || MdnsObfuscationEnabled();
// If the candidate filter doesn't allow reflexive addresses, empty TURN raddr
// to avoid reflexive address leakage.
bool filter_turn_related_address = !(candidate_filter_ & CF_REFLEXIVE);

View File

@ -236,6 +236,10 @@ class RTC_EXPORT BasicPortAllocatorSession : public PortAllocatorSession,
bool CheckCandidateFilter(const Candidate& c) const;
bool CandidatePairable(const Candidate& c, const Port* port) const;
// Returns true if there is an mDNS responder attached to the network manager
bool MdnsObfuscationEnabled() 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.

View File

@ -2246,8 +2246,8 @@ TEST_F(BasicPortAllocatorTest, IceRegatheringMetricsLoggedWhenNetworkChanges) {
}
// Test that when an mDNS responder is present, the local address of a host
// candidate is masked by an mDNS hostname and the related address of any other
// type of candidates is set to 0.0.0.0 or ::0.
// candidate is concealed by an mDNS hostname and the related address of a srflx
// candidate is set to 0.0.0.0 or ::0.
TEST_F(BasicPortAllocatorTest, HostCandidateAddressIsReplacedByHostname) {
// Default config uses GTURN and no NAT, so replace that with the
// desired setup (NAT, STUN server, TURN server, UDP/TCP).
@ -2269,23 +2269,29 @@ TEST_F(BasicPortAllocatorTest, HostCandidateAddressIsReplacedByHostname) {
int num_srflx_candidates = 0;
int num_relay_candidates = 0;
for (const auto& candidate : candidates_) {
const auto& raddr = candidate.related_address();
if (candidate.type() == LOCAL_PORT_TYPE) {
EXPECT_TRUE(candidate.address().IsUnresolvedIP());
EXPECT_FALSE(candidate.address().hostname().empty());
EXPECT_TRUE(raddr.IsNil());
if (candidate.protocol() == UDP_PROTOCOL_NAME) {
++num_host_udp_candidates;
} else {
++num_host_tcp_candidates;
}
} else if (candidate.type() == STUN_PORT_TYPE) {
// For a srflx candidate, the related address should be set to 0.0.0.0 or
// ::0
EXPECT_TRUE(IPIsAny(raddr.ipaddr()));
EXPECT_EQ(raddr.port(), 0);
++num_srflx_candidates;
} else if (candidate.type() == RELAY_PORT_TYPE) {
EXPECT_EQ(kNatUdpAddr.ipaddr(), raddr.ipaddr());
EXPECT_EQ(kNatUdpAddr.family(), raddr.family());
++num_relay_candidates;
} else {
EXPECT_NE(PRFLX_PORT_TYPE, candidate.type());
// The related address should be set to 0.0.0.0 or ::0 for srflx and
// relay candidates.
EXPECT_EQ(rtc::SocketAddress(), candidate.related_address());
if (candidate.type() == STUN_PORT_TYPE) {
++num_srflx_candidates;
} else {
++num_relay_candidates;
}
// prflx candidates are not expected
FAIL();
}
}
EXPECT_EQ(1, num_host_udp_candidates);