Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Default to the blacklisting reserved IP ranges. #8870

Merged
merged 17 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog.d/8821.bugfix
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Apply the `federation_ip_range_blacklist` to push and key revocation requests.
Apply an IP range blacklist to push and key revocation requests.
1 change: 1 addition & 0 deletions changelog.d/8870.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Apply an IP range blacklist to push and key revocation requests.
52 changes: 38 additions & 14 deletions docs/sample_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -643,27 +643,45 @@ acme:
# - syd.example.com

# Prevent outgoing requests from being sent to the following blacklisted IP address
# CIDR ranges. If this option is not specified, or specified with an empty list,
# no IP range blacklist will be enforced.
# CIDR ranges. If this option is not specified or is empty then it defaults to
# private IP address ranges (see the example below).
#
# The blacklist applies to the outbound requests for federation, identity servers,
# push servers, and for checking key validitity for third-party invite events.
# push servers, and for checking key validity for third-party invite events.
#
# (0.0.0.0 and :: are always blacklisted, whether or not they are explicitly
# listed here, since they correspond to unroutable addresses.)
#
# This option replaces federation_ip_range_blacklist in Synapse v1.24.0.
clokep marked this conversation as resolved.
Show resolved Hide resolved
#
ip_range_blacklist:
- '127.0.0.0/8'
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- '100.64.0.0/10'
- '169.254.0.0/16'
- '::1/128'
- 'fe80::/64'
- 'fc00::/7'
#ip_range_blacklist:
# - '127.0.0.0/8'
# - '10.0.0.0/8'
# - '172.16.0.0/12'
# - '192.168.0.0/16'
# - '100.64.0.0/10'
# - '192.0.0.0/24'
# - '169.254.0.0/16'
# - '198.18.0.0/15'
# - '192.0.2.0/24'
# - '198.51.100.0/24'
# - '203.0.113.0/24'
# - '224.0.0.0/4'
# - '::1/128'
# - 'fe80::/10'
# - 'fc00::/7'

# List of IP address CIDR ranges that should be allowed for federation,
# identity servers, push servers, and for checking key validity for
# third-party invite events. This is useful for specifying exceptions to
# wide-ranging blacklisted target IP ranges - e.g. for communication with
# a push server only visible in your network.
#
# This whitelist overrides ip_range_blacklist and defaults to an empty
# list.
#
#ip_range_whitelist:
# - '192.168.1.1'

# Report prometheus metrics on the age of PDUs being sent to and received from
# the following domains. This can be used to give an idea of "delay" on inbound
Expand Down Expand Up @@ -955,9 +973,15 @@ media_store_path: "DATADIR/media_store"
# - '172.16.0.0/12'
# - '192.168.0.0/16'
# - '100.64.0.0/10'
# - '192.0.0.0/24'
# - '169.254.0.0/16'
# - '198.18.0.0/15'
# - '192.0.2.0/24'
# - '198.51.100.0/24'
# - '203.0.113.0/24'
# - '224.0.0.0/4'
# - '::1/128'
# - 'fe80::/64'
# - 'fe80::/10'
# - 'fc00::/7'

# List of IP address CIDR ranges that the URL preview spider is allowed
Expand Down
76 changes: 60 additions & 16 deletions synapse/config/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,41 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional

from netaddr import IPSet

from synapse.config._base import Config, ConfigError
from synapse.config._util import validate_config

DEFAULT_IP_RANGE_BLACKLIST = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not 100% sure where these came from? They seem to partially block "private" IP spaces, but not all, see https://github.com/netaddr/netaddr/blob/master/netaddr/ip/__init__.py#L1918-L1972 / RFC6890.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was copied from the url_preview blacklist, which itself has evolved rather than being put together carefully (see #1198 for example). It might be a good time to consider if there are others we should add.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to what is there we should probably add:

  • 192.0.0.0/24: IANA IPv4 Special Purpose Address Registry (RFC 5736)
  • 198.18.0.0/15: Testing of inter-network communications between subnets (RFC 2544)
  • 0.0.0.0/8: Broadcast message (RFC 1700)
  • 192.0.2.0/24: TEST-NET examples and documentation (RFC 5737)
  • 198.51.100.0/24: TEST-NET-2 examples and documentation (RFC 5737)
  • 203.0.113.0/24: TEST-NET-3 examples and documentation (RFC 5737)

I don't see why we would ever talk to multicast addresses:

  • 239.0.0.0 - 239.255.255.255: Administrative Multicast
  • 224.0.0.0/4: Multicast
  • 240.0.0.0/4: Reserved for multicast assignments (RFC 5771)
  • 233.252.0.0/24: Multicast test network
  • 234.0.0.0 - 238.255.255.255: Reserved multicast
  • 225.0.0.0 - 231.255.255.255: Reserved multicast
  • ff00::/8: Multicast

Ones we should modify:

  • fe80::/64 -> fe80::/10: link local

Ones I'm unsure about:

  • 192.88.99.0/24: 6to4 anycast relays (RFC 3068)
  • fec0::/10: Site Local Addresses (deprecated - RFC 3879)
  • The other IPv6 reserved: ff00::/12, ::/8, 0100::/8, 0200::/7, 0400::/6, 0800::/5, 1000::/4, 4000::/3, 6000::/3, 8000::/3, A000::/3, C000::/3, E000::/4, F000::/5, F800::/6, FE00::/9

That's quite a big change though, what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally I agree with adding all of those to the default value, but a few points:

  • Note that 0.0.0.0/32 is already special-cased (I can't quite remember the history there). Should we update that special-casing rather than add 0.0.0.0/8 to the default here?
  • Are the IPv6 reserved addresses just "not yet assigned"? My instinct is not to blacklist them (though I'm surprised to see ::/8 there, given ::1 is localhost)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you're correct that those IPv6 addresses have just not been assigned yet, which is quite different.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like https://tools.ietf.org/html/rfc6890 is the proper reference to be using.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list mentioned above looks sane to me.

IMO, we could and should add everything from the above lists, up to the "not yet assigned" addresses.

Regarding Site Local Addresses, RFC 3879 mentions that the block is not supposed to be reassigned except by future IETF action and that router implementations SHOULD prevent routing. Taking that into account, I don't see any downside in adding them to the default blacklist and it's nice from a defence in depth perspective, just in case there's a bad/old router implementation somewhere.

I think we can safely skip the "not yet assigned" addresses for now. On the topic of ::1, I suppose the intent is that the entire ::/8 block is unassigned, except for ::1 which is treated as an exception and a special address.

I can't think of anything else that should be added to the list at the moment.

# Localhost
"127.0.0.0/8",
# Private networks.
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
# Carrier grade NAT.
"100.64.0.0/10",
# Address registry.
"192.0.0.0/24",
# Link-local networks.
"169.254.0.0/16",
# Testing networks.
"198.18.0.0/15",
"192.0.2.0/24",
"198.51.100.0/24",
"203.0.113.0/24",
# Multicast.
"224.0.0.0/4",
# Localhost
"::1/128",
# Link-local addresses.
"fe80::/10",
# Unique local addresses.
"fc00::/7",
]


class FederationConfig(Config):
section = "federation"
Expand All @@ -36,7 +63,9 @@ def read_config(self, config, **kwargs):
for domain in federation_domain_whitelist:
self.federation_domain_whitelist[domain] = True

ip_range_blacklist = config.get("ip_range_blacklist", [])
ip_range_blacklist = config.get(
"ip_range_blacklist", DEFAULT_IP_RANGE_BLACKLIST
)

# Attempt to create an IPSet from the given ranges
try:
Expand All @@ -46,6 +75,11 @@ def read_config(self, config, **kwargs):
# Always blacklist 0.0.0.0, ::
self.ip_range_blacklist.update(["0.0.0.0", "::"])

try:
self.ip_range_whitelist = IPSet(config.get("ip_range_whitelist", ()))
except Exception as e:
raise ConfigError("Invalid range(s) provided in ip_range_whitelist: %s" % e)
clokep marked this conversation as resolved.
Show resolved Hide resolved

# The federation_ip_range_blacklist is used for backwards-compatibility
# and only applies to federation and identity servers. If it is not given,
# default to ip_range_blacklist.
Expand All @@ -70,6 +104,10 @@ def read_config(self, config, **kwargs):
self.federation_metrics_domains = set(federation_metrics_domains)

def generate_config_section(self, config_dir_path, server_name, **kwargs):
ip_range_blacklist = "\n".join(
" # - '%s'" % ip for ip in DEFAULT_IP_RANGE_BLACKLIST
)

return """\
## Federation ##

Expand All @@ -85,27 +123,31 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
# - syd.example.com

# Prevent outgoing requests from being sent to the following blacklisted IP address
# CIDR ranges. If this option is not specified, or specified with an empty list,
# no IP range blacklist will be enforced.
# CIDR ranges. If this option is not specified or is empty then it defaults to
clokep marked this conversation as resolved.
Show resolved Hide resolved
# private IP address ranges (see the example below).
#
# The blacklist applies to the outbound requests for federation, identity servers,
# push servers, and for checking key validitity for third-party invite events.
# push servers, and for checking key validity for third-party invite events.
#
# (0.0.0.0 and :: are always blacklisted, whether or not they are explicitly
# listed here, since they correspond to unroutable addresses.)
#
# This option replaces federation_ip_range_blacklist in Synapse v1.24.0.
#
ip_range_blacklist:
- '127.0.0.0/8'
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- '100.64.0.0/10'
- '169.254.0.0/16'
- '::1/128'
- 'fe80::/64'
- 'fc00::/7'
#ip_range_blacklist:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like these options no longer really belong in the Federation section of the sample config.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were moved here in #7798 from server. I've moved them back.

%(ip_range_blacklist)s

# List of IP address CIDR ranges that should be allowed for federation,
# identity servers, push servers, and for checking key validity for
# third-party invite events. This is useful for specifying exceptions to
# wide-ranging blacklisted target IP ranges - e.g. for communication with
# a push server only visible in your network.
#
# This whitelist overrides ip_range_blacklist and defaults to an empty
# list.
#
#ip_range_whitelist:
# - '192.168.1.1'

# Report prometheus metrics on the age of PDUs being sent to and received from
# the following domains. This can be used to give an idea of "delay" on inbound
Expand All @@ -117,7 +159,9 @@ def generate_config_section(self, config_dir_path, server_name, **kwargs):
#federation_metrics_domains:
# - matrix.org
# - example.com
"""
""" % {
"ip_range_blacklist": ip_range_blacklist
}


_METRICS_FOR_DOMAINS_SCHEMA = {"type": "array", "items": {"type": "string"}}
20 changes: 8 additions & 12 deletions synapse/config/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
from collections import namedtuple
from typing import Dict, List

from netaddr import IPSet
clokep marked this conversation as resolved.
Show resolved Hide resolved

from synapse.config.federation import DEFAULT_IP_RANGE_BLACKLIST
from synapse.python_dependencies import DependencyException, check_requirements
from synapse.util.module_loader import load_module

Expand Down Expand Up @@ -184,9 +187,6 @@ def read_config(self, config, **kwargs):
"to work"
)

# netaddr is a dependency for url_preview
from netaddr import IPSet

self.url_preview_ip_range_blacklist = IPSet(
config["url_preview_ip_range_blacklist"]
)
Expand Down Expand Up @@ -215,6 +215,10 @@ def generate_config_section(self, data_dir_path, **kwargs):
# strip final NL
formatted_thumbnail_sizes = formatted_thumbnail_sizes[:-1]

ip_range_blacklist = "\n".join(
" # - '%s'" % ip for ip in DEFAULT_IP_RANGE_BLACKLIST
)

return (
r"""
## Media Store ##
Expand Down Expand Up @@ -285,15 +289,7 @@ def generate_config_section(self, data_dir_path, **kwargs):
# you uncomment the following list as a starting point.
#
#url_preview_ip_range_blacklist:
# - '127.0.0.0/8'
# - '10.0.0.0/8'
# - '172.16.0.0/12'
# - '192.168.0.0/16'
# - '100.64.0.0/10'
# - '169.254.0.0/16'
# - '::1/128'
# - 'fe80::/64'
# - 'fc00::/7'
%(ip_range_blacklist)s

# List of IP address CIDR ranges that the URL preview spider is allowed
# to access even if they are specified in url_preview_ip_range_blacklist.
Expand Down
3 changes: 2 additions & 1 deletion synapse/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,11 @@ def get_proxied_http_client(self) -> SimpleHttpClient:
def get_proxied_blacklisted_http_client(self) -> SimpleHttpClient:
"""
An HTTP client that uses configured HTTP(S) proxies and blacklists IPs
based on the IP range blacklist.
based on the IP range blacklist/whitelist.
"""
return SimpleHttpClient(
self,
ip_whitelist=self.config.ip_range_whitelist,
ip_blacklist=self.config.ip_range_blacklist,
http_proxy=os.getenvb(b"http_proxy"),
https_proxy=os.getenvb(b"HTTPS_PROXY"),
Expand Down
2 changes: 1 addition & 1 deletion tests/replication/test_multi_media_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def prepare(self, reactor, clock, hs):
self.user_id = self.register_user("user", "pass")
self.access_token = self.login("user", "pass")

self.reactor.lookups["example.com"] = "127.0.0.2"
self.reactor.lookups["example.com"] = "1.2.3.4"

def default_config(self):
conf = super().default_config()
Expand Down