mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-12-01 21:34:40 -05:00
Apply an IP range blacklist to push and key revocation requests. (#8821)
Replaces the `federation_ip_range_blacklist` configuration setting with an `ip_range_blacklist` setting with wider scope. It now applies to: * Federation * Identity servers * Push notifications * Checking key validitity for third-party invite events The old `federation_ip_range_blacklist` setting is still honored if present, but with reduced scope (it only applies to federation and identity servers).
This commit is contained in:
parent
c5b6abd53d
commit
30fba62108
43 changed files with 175 additions and 114 deletions
|
|
@ -125,7 +125,7 @@ def _make_scheduler(reactor):
|
|||
return _scheduler
|
||||
|
||||
|
||||
class IPBlacklistingResolver:
|
||||
class _IPBlacklistingResolver:
|
||||
"""
|
||||
A proxy for reactor.nameResolver which only produces non-blacklisted IP
|
||||
addresses, preventing DNS rebinding attacks on URL preview.
|
||||
|
|
@ -199,6 +199,35 @@ class IPBlacklistingResolver:
|
|||
return r
|
||||
|
||||
|
||||
@implementer(IReactorPluggableNameResolver)
|
||||
class BlacklistingReactorWrapper:
|
||||
"""
|
||||
A Reactor wrapper which will prevent DNS resolution to blacklisted IP
|
||||
addresses, to prevent DNS rebinding.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
reactor: IReactorPluggableNameResolver,
|
||||
ip_whitelist: Optional[IPSet],
|
||||
ip_blacklist: IPSet,
|
||||
):
|
||||
self._reactor = reactor
|
||||
|
||||
# We need to use a DNS resolver which filters out blacklisted IP
|
||||
# addresses, to prevent DNS rebinding.
|
||||
self._nameResolver = _IPBlacklistingResolver(
|
||||
self._reactor, ip_whitelist, ip_blacklist
|
||||
)
|
||||
|
||||
def __getattr__(self, attr: str) -> Any:
|
||||
# Passthrough to the real reactor except for the DNS resolver.
|
||||
if attr == "nameResolver":
|
||||
return self._nameResolver
|
||||
else:
|
||||
return getattr(self._reactor, attr)
|
||||
|
||||
|
||||
class BlacklistingAgentWrapper(Agent):
|
||||
"""
|
||||
An Agent wrapper which will prevent access to IP addresses being accessed
|
||||
|
|
@ -292,22 +321,11 @@ class SimpleHttpClient:
|
|||
self.user_agent = self.user_agent.encode("ascii")
|
||||
|
||||
if self._ip_blacklist:
|
||||
real_reactor = hs.get_reactor()
|
||||
# If we have an IP blacklist, we need to use a DNS resolver which
|
||||
# filters out blacklisted IP addresses, to prevent DNS rebinding.
|
||||
nameResolver = IPBlacklistingResolver(
|
||||
real_reactor, self._ip_whitelist, self._ip_blacklist
|
||||
self.reactor = BlacklistingReactorWrapper(
|
||||
hs.get_reactor(), self._ip_whitelist, self._ip_blacklist
|
||||
)
|
||||
|
||||
@implementer(IReactorPluggableNameResolver)
|
||||
class Reactor:
|
||||
def __getattr__(_self, attr):
|
||||
if attr == "nameResolver":
|
||||
return nameResolver
|
||||
else:
|
||||
return getattr(real_reactor, attr)
|
||||
|
||||
self.reactor = Reactor()
|
||||
else:
|
||||
self.reactor = hs.get_reactor()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import logging
|
|||
import urllib.parse
|
||||
from typing import List, Optional
|
||||
|
||||
from netaddr import AddrFormatError, IPAddress
|
||||
from netaddr import AddrFormatError, IPAddress, IPSet
|
||||
from zope.interface import implementer
|
||||
|
||||
from twisted.internet import defer
|
||||
|
|
@ -31,6 +31,7 @@ from twisted.web.http_headers import Headers
|
|||
from twisted.web.iweb import IAgent, IAgentEndpointFactory, IBodyProducer
|
||||
|
||||
from synapse.crypto.context_factory import FederationPolicyForHTTPS
|
||||
from synapse.http.client import BlacklistingAgentWrapper
|
||||
from synapse.http.federation.srv_resolver import Server, SrvResolver
|
||||
from synapse.http.federation.well_known_resolver import WellKnownResolver
|
||||
from synapse.logging.context import make_deferred_yieldable, run_in_background
|
||||
|
|
@ -70,6 +71,7 @@ class MatrixFederationAgent:
|
|||
reactor: IReactorCore,
|
||||
tls_client_options_factory: Optional[FederationPolicyForHTTPS],
|
||||
user_agent: bytes,
|
||||
ip_blacklist: IPSet,
|
||||
_srv_resolver: Optional[SrvResolver] = None,
|
||||
_well_known_resolver: Optional[WellKnownResolver] = None,
|
||||
):
|
||||
|
|
@ -90,12 +92,18 @@ class MatrixFederationAgent:
|
|||
self.user_agent = user_agent
|
||||
|
||||
if _well_known_resolver is None:
|
||||
# Note that the name resolver has already been wrapped in a
|
||||
# IPBlacklistingResolver by MatrixFederationHttpClient.
|
||||
_well_known_resolver = WellKnownResolver(
|
||||
self._reactor,
|
||||
agent=Agent(
|
||||
agent=BlacklistingAgentWrapper(
|
||||
Agent(
|
||||
self._reactor,
|
||||
pool=self._pool,
|
||||
contextFactory=tls_client_options_factory,
|
||||
),
|
||||
self._reactor,
|
||||
pool=self._pool,
|
||||
contextFactory=tls_client_options_factory,
|
||||
ip_blacklist=ip_blacklist,
|
||||
),
|
||||
user_agent=self.user_agent,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,11 +26,10 @@ import treq
|
|||
from canonicaljson import encode_canonical_json
|
||||
from prometheus_client import Counter
|
||||
from signedjson.sign import sign_json
|
||||
from zope.interface import implementer
|
||||
|
||||
from twisted.internet import defer
|
||||
from twisted.internet.error import DNSLookupError
|
||||
from twisted.internet.interfaces import IReactorPluggableNameResolver, IReactorTime
|
||||
from twisted.internet.interfaces import IReactorTime
|
||||
from twisted.internet.task import _EPSILON, Cooperator
|
||||
from twisted.web.http_headers import Headers
|
||||
from twisted.web.iweb import IBodyProducer, IResponse
|
||||
|
|
@ -45,7 +44,7 @@ from synapse.api.errors import (
|
|||
from synapse.http import QuieterFileBodyProducer
|
||||
from synapse.http.client import (
|
||||
BlacklistingAgentWrapper,
|
||||
IPBlacklistingResolver,
|
||||
BlacklistingReactorWrapper,
|
||||
encode_query_args,
|
||||
readBodyToFile,
|
||||
)
|
||||
|
|
@ -221,31 +220,22 @@ class MatrixFederationHttpClient:
|
|||
self.signing_key = hs.signing_key
|
||||
self.server_name = hs.hostname
|
||||
|
||||
real_reactor = hs.get_reactor()
|
||||
|
||||
# We need to use a DNS resolver which filters out blacklisted IP
|
||||
# addresses, to prevent DNS rebinding.
|
||||
nameResolver = IPBlacklistingResolver(
|
||||
real_reactor, None, hs.config.federation_ip_range_blacklist
|
||||
self.reactor = BlacklistingReactorWrapper(
|
||||
hs.get_reactor(), None, hs.config.federation_ip_range_blacklist
|
||||
)
|
||||
|
||||
@implementer(IReactorPluggableNameResolver)
|
||||
class Reactor:
|
||||
def __getattr__(_self, attr):
|
||||
if attr == "nameResolver":
|
||||
return nameResolver
|
||||
else:
|
||||
return getattr(real_reactor, attr)
|
||||
|
||||
self.reactor = Reactor()
|
||||
|
||||
user_agent = hs.version_string
|
||||
if hs.config.user_agent_suffix:
|
||||
user_agent = "%s %s" % (user_agent, hs.config.user_agent_suffix)
|
||||
user_agent = user_agent.encode("ascii")
|
||||
|
||||
self.agent = MatrixFederationAgent(
|
||||
self.reactor, tls_client_options_factory, user_agent
|
||||
self.reactor,
|
||||
tls_client_options_factory,
|
||||
user_agent,
|
||||
hs.config.federation_ip_range_blacklist,
|
||||
)
|
||||
|
||||
# Use a BlacklistingAgentWrapper to prevent circumventing the IP
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue