feat: reduce denial of service protection overhead (#1157) · python-zeroconf/python-zeroconf@2c2f26a

@@ -133,23 +133,6 @@ def _add_answers_additionals(out: DNSOutgoing, answers: _AnswerWithAdditionalsTy

133133

sending.add(additional)

134134135135136-

def sanitize_incoming_record(record: DNSRecord) -> None:

137-

"""Protect zeroconf from records that can cause denial of service.

138-139-

We enforce a minimum TTL for PTR records to avoid

140-

ServiceBrowsers generating excessive queries refresh queries.

141-

Apple uses a 15s minimum TTL, however we do not have the same

142-

level of rate limit and safe guards so we use 1/4 of the recommended value.

143-

"""

144-

if record.ttl and record.ttl < _DNS_PTR_MIN_TTL and isinstance(record, DNSPointer):

145-

log.debug(

146-

"Increasing effective ttl of %s to minimum of %s to protect against excessive refreshes.",

147-

record,

148-

_DNS_PTR_MIN_TTL,

149-

)

150-

record.set_created_ttl(record.created, _DNS_PTR_MIN_TTL)

151-152-153136

class _QueryResponse:

154137

"""A pair for unicast and multicast DNSOutgoing responses."""

155138

@@ -420,14 +403,26 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:

420403

threadsafe.

421404

"""

422405

updates: List[RecordUpdate] = []

423-

address_adds: List[DNSAddress] = []

406+

address_adds: List[DNSRecord] = []

424407

other_adds: List[DNSRecord] = []

425408

removes: Set[DNSRecord] = set()

426409

now = msg.now

427410

unique_types: Set[Tuple[str, int, int]] = set()

428411429412

for record in msg.answers:

430-

sanitize_incoming_record(record)

413+

# Protect zeroconf from records that can cause denial of service.

414+

#

415+

# We enforce a minimum TTL for PTR records to avoid

416+

# ServiceBrowsers generating excessive queries refresh queries.

417+

# Apple uses a 15s minimum TTL, however we do not have the same

418+

# level of rate limit and safe guards so we use 1/4 of the recommended value.

419+

if record.ttl and record.type == _TYPE_PTR and record.ttl < _DNS_PTR_MIN_TTL:

420+

log.debug(

421+

"Increasing effective ttl of %s to minimum of %s to protect against excessive refreshes.",

422+

record,

423+

_DNS_PTR_MIN_TTL,

424+

)

425+

record.set_created_ttl(record.created, _DNS_PTR_MIN_TTL)

431426432427

if record.unique: # https://tools.ietf.org/html/rfc6762#section-10.2

433428

unique_types.add((record.name, record.type, record.class_))

@@ -437,7 +432,7 @@ def async_updates_from_response(self, msg: DNSIncoming) -> None:

437432

if maybe_entry is not None:

438433

maybe_entry.reset_ttl(record)

439434

else:

440-

if isinstance(record, DNSAddress):

435+

if record.type in _ADDRESS_RECORD_TYPES:

441436

address_adds.append(record)

442437

else:

443438

other_adds.append(record)