From d95fb34ba7dcd906af5658f15fd028f1decb5fcb Mon Sep 17 00:00:00 2001 From: Alex Vandiver Date: Tue, 7 Dec 2021 20:13:47 +0000 Subject: [PATCH] puppet: Admit we leave epmd port 4369 open on all interfaces. The Erlang `epmd` daemon listens on port 4369, and provides information (without authentication) about which Erlang processes are listening on what ports. This information is not itself a vulnerability, but may provide information for remote attackers about what local Erlang services (such as `rabbitmq-server`) are running, and where. `epmd` supports an `ERL_EPMD_ADDRESS` environment variable to limit which interfaces it binds on. While this environment variable is set in `/etc/default/rabbitmq-server`, Zulip unfortunately attempts to start `epmd` using an explicit `exec` block, which ignores those settings. Regardless, this lack of `ERL_EPMD_ADDRESS` variable only controls `epmd`'s startup upon first installation. Upon reboot, there are two ways in which `epmd` might be started, neither of which respect `ERL_EPMD_ADDRESS`: - On Focal, an `epmd` service exists and is activated, which uses systemd's configuration to choose which interfaces to bind on, and thus `ERL_EPMD_ADDRESS` is irrelevant. - On Bionic (and Focal, due to a broken dependency from `rabbitmq-server` to `epmd@` instead of `epmd`, which may lead to the explicit `epmd` service losing a race), `epmd` is started by `rabbitmq-server` when it does not detect a running instance. Unfortunately, only `/etc/init.d/rabbitmq-server` would respects `/etc/default/rabbitmq-server` -- and it defers the actual startup to using systemd, which does not pass the environment variable down. Thus, `ERL_EPMD_ADDRESS` is also irrelevant here. We unfortunately cannot limit `epmd` to only listening on localhost, due to a number of overlapping bugs and limitations: - Manually starting `epmd` with `-address 127.0.0.1` silently fails to start on hosts with IPv6 disabled, due to an Erlang bug ([1], [2]). - The dependencies of the systemd `rabbitmq-server` service can be fixed to include the `epmd` service, and systemd can be made to bind to `127.0.0.1:4369` and pass that socket to `epmd`, bypassing the above bug. However, the startup of this service is not guaranteed, because it races with other sources of `epmd` (see below). - Any process that runs `rabbitmqctl` results in `epmd` being started if one is not currently running; these instances do not respect any environment variables as to which addresses to bind on. This is also triggered by `service rabbitmq-server status`, as well as various Zulip cron jobs which inspect the rabbitmq queues. As such, it is difficult-to-impossible to ensure that some other `epmd` process will not win the race and open the port on all interfaces. Since the only known exposure from leaving port 4369 open is information that rabbitmq is running on the host, and the complexity of adjusting this to only bind on localhost is high, we remove the setting which does not address the problem, and document that the port is left open, and should be protected via system-level or network-level firewalls. [1]: https://bugs.launchpad.net/ubuntu/+source/erlang/+bug/1374109 [2]: https://github.com/erlang/otp/issues/4820 --- docs/production/requirements.md | 5 +++++ puppet/zulip/files/rabbitmq/rabbitmq-server | 11 ----------- puppet/zulip/manifests/profile/rabbitmq.pp | 9 --------- 3 files changed, 5 insertions(+), 20 deletions(-) delete mode 100644 puppet/zulip/files/rabbitmq/rabbitmq-server diff --git a/docs/production/requirements.md b/docs/production/requirements.md index 7d73768a42..6d123e28c8 100644 --- a/docs/production/requirements.md +++ b/docs/production/requirements.md @@ -81,6 +81,11 @@ on hardware requirements for larger organizations. HTTPS, and will redirect HTTP requests to HTTPS. - Incoming port 25 if you plan to enable Zulip's [incoming email integration](../production/email-gateway.md). +- Incoming port 4369 should be protected by a firewall to prevent + exposing `epmd`, an Erlang service which does not support binding + only to localhost. Leaving this exposed will allow unauthenticated + remote users to determine that the server is running RabbitMQ, and + on which port, though no further information is leaked. - Outgoing HTTP(S) access (ports 80 and 443) to the public Internet so that Zulip can properly manage image and website previews and mobile push notifications. Outgoing Internet access is not required if you diff --git a/puppet/zulip/files/rabbitmq/rabbitmq-server b/puppet/zulip/files/rabbitmq/rabbitmq-server deleted file mode 100644 index a1c281b888..0000000000 --- a/puppet/zulip/files/rabbitmq/rabbitmq-server +++ /dev/null @@ -1,11 +0,0 @@ -# This file is sourced by /etc/init.d/rabbitmq-server. Its primary -# reason for existing is to allow adjustment of system limits for the -# rabbitmq-server process. -# -# Maximum number of open file handles. This will need to be increased -# to handle many simultaneous connections. Refer to the system -# documentation for ulimit (in man bash) for more information. -# -#ulimit -n 1024 - -export ERL_EPMD_ADDRESS=127.0.0.1 diff --git a/puppet/zulip/manifests/profile/rabbitmq.pp b/puppet/zulip/manifests/profile/rabbitmq.pp index 0a3dd4c4e0..8f740e3ed7 100644 --- a/puppet/zulip/manifests/profile/rabbitmq.pp +++ b/puppet/zulip/manifests/profile/rabbitmq.pp @@ -16,15 +16,6 @@ class zulip::profile::rabbitmq { ensure => absent, } - file { '/etc/default/rabbitmq-server': - ensure => file, - require => Package[rabbitmq-server], - owner => 'root', - group => 'root', - mode => '0644', - source => 'puppet:///modules/zulip/rabbitmq/rabbitmq-server', - } - file { '/etc/rabbitmq/rabbitmq.config': ensure => file, require => Package[rabbitmq-server],