Merge pull request #2435 from silkeh/listen-ipv6-default

Adapt the default config to bind on both IPv4 and IPv6 on all platforms
This commit is contained in:
Richard van der Hoff 2017-12-18 22:34:50 +00:00 committed by GitHub
commit 48fa4e1e5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 247 additions and 231 deletions

View file

@ -25,7 +25,9 @@ except Exception:
from daemonize import Daemonize from daemonize import Daemonize
from synapse.util import PreserveLoggingContext from synapse.util import PreserveLoggingContext
from synapse.util.rlimit import change_resource_limit from synapse.util.rlimit import change_resource_limit
from twisted.internet import reactor from twisted.internet import error, reactor
logger = logging.getLogger(__name__)
def start_worker_reactor(appname, config): def start_worker_reactor(appname, config):
@ -120,3 +122,57 @@ def quit_with_error(error_string):
sys.stderr.write(" %s\n" % (line.rstrip(),)) sys.stderr.write(" %s\n" % (line.rstrip(),))
sys.stderr.write("*" * line_length + '\n') sys.stderr.write("*" * line_length + '\n')
sys.exit(1) sys.exit(1)
def listen_tcp(bind_addresses, port, factory, backlog=50):
"""
Create a TCP socket for a port and several addresses
"""
for address in bind_addresses:
try:
reactor.listenTCP(
port,
factory,
backlog,
address
)
except error.CannotListenError as e:
check_bind_error(e, address, bind_addresses)
def listen_ssl(bind_addresses, port, factory, context_factory, backlog=50):
"""
Create an SSL socket for a port and several addresses
"""
for address in bind_addresses:
try:
reactor.listenSSL(
port,
factory,
context_factory,
backlog,
address
)
except error.CannotListenError as e:
check_bind_error(e, address, bind_addresses)
def check_bind_error(e, address, bind_addresses):
"""
This method checks an exception occurred while binding on 0.0.0.0.
If :: is specified in the bind addresses a warning is shown.
The exception is still raised otherwise.
Binding on both 0.0.0.0 and :: causes an exception on Linux and macOS
because :: binds on both IPv4 and IPv6 (as per RFC 3493).
When binding on 0.0.0.0 after :: this can safely be ignored.
Args:
e (Exception): Exception that was caught.
address (str): Address on which binding was attempted.
bind_addresses (list): Addresses on which the service listens.
"""
if address == '0.0.0.0' and '::' in bind_addresses:
logger.warn('Failed to listen on 0.0.0.0, continuing because listening on [::]')
else:
raise e

View file

@ -79,17 +79,16 @@ class AppserviceServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse appservice now listening on port %d", port) logger.info("Synapse appservice now listening on port %d", port)
@ -98,18 +97,15 @@ class AppserviceServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -103,17 +103,16 @@ class ClientReaderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse client reader now listening on port %d", port) logger.info("Synapse client reader now listening on port %d", port)
@ -122,18 +121,16 @@ class ClientReaderServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -92,17 +92,16 @@ class FederationReaderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse federation reader now listening on port %d", port) logger.info("Synapse federation reader now listening on port %d", port)
@ -111,18 +110,15 @@ class FederationReaderServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -106,17 +106,16 @@ class FederationSenderServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse federation_sender now listening on port %d", port) logger.info("Synapse federation_sender now listening on port %d", port)
@ -125,18 +124,15 @@ class FederationSenderServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -157,17 +157,16 @@ class FrontendProxyServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse client reader now listening on port %d", port) logger.info("Synapse client reader now listening on port %d", port)
@ -176,18 +175,15 @@ class FrontendProxyServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -25,7 +25,7 @@ from synapse.api.urls import CONTENT_REPO_PREFIX, FEDERATION_PREFIX, \
LEGACY_MEDIA_PREFIX, MEDIA_PREFIX, SERVER_KEY_PREFIX, SERVER_KEY_V2_PREFIX, \ LEGACY_MEDIA_PREFIX, MEDIA_PREFIX, SERVER_KEY_PREFIX, SERVER_KEY_V2_PREFIX, \
STATIC_PREFIX, WEB_CLIENT_PREFIX STATIC_PREFIX, WEB_CLIENT_PREFIX
from synapse.app import _base from synapse.app import _base
from synapse.app._base import quit_with_error from synapse.app._base import quit_with_error, listen_ssl, listen_tcp
from synapse.config._base import ConfigError from synapse.config._base import ConfigError
from synapse.config.homeserver import HomeServerConfig from synapse.config.homeserver import HomeServerConfig
from synapse.crypto import context_factory from synapse.crypto import context_factory
@ -130,30 +130,29 @@ class SynapseHomeServer(HomeServer):
root_resource = create_resource_tree(resources, root_resource) root_resource = create_resource_tree(resources, root_resource)
if tls: if tls:
for address in bind_addresses: listen_ssl(
reactor.listenSSL( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.https.%s" % (site_tag,), "synapse.access.https.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
), ),
self.tls_server_context_factory, self.tls_server_context_factory,
interface=address )
)
else: else:
for address in bind_addresses: listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse now listening on port %d", port) logger.info("Synapse now listening on port %d", port)
def _configure_named_resource(self, name, compress=False): def _configure_named_resource(self, name, compress=False):
@ -229,18 +228,15 @@ class SynapseHomeServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listener_http(config, listener) self._listener_http(config, listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
elif listener["type"] == "replication": elif listener["type"] == "replication":
bind_addresses = listener["bind_addresses"] bind_addresses = listener["bind_addresses"]
for address in bind_addresses: for address in bind_addresses:

View file

@ -99,17 +99,16 @@ class MediaRepositoryServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse media repository now listening on port %d", port) logger.info("Synapse media repository now listening on port %d", port)
@ -118,18 +117,15 @@ class MediaRepositoryServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -114,17 +114,16 @@ class PusherServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse pusher now listening on port %d", port) logger.info("Synapse pusher now listening on port %d", port)
@ -133,18 +132,15 @@ class PusherServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -288,17 +288,16 @@ class SynchrotronServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse synchrotron now listening on port %d", port) logger.info("Synapse synchrotron now listening on port %d", port)
@ -307,18 +306,15 @@ class SynchrotronServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -131,17 +131,16 @@ class UserDirectoryServer(HomeServer):
root_resource = create_resource_tree(resources, Resource()) root_resource = create_resource_tree(resources, Resource())
for address in bind_addresses: _base.listen_tcp(
reactor.listenTCP( bind_addresses,
port, port,
SynapseSite( SynapseSite(
"synapse.access.http.%s" % (site_tag,), "synapse.access.http.%s" % (site_tag,),
site_tag, site_tag,
listener_config, listener_config,
root_resource, root_resource,
),
interface=address
) )
)
logger.info("Synapse user_dir now listening on port %d", port) logger.info("Synapse user_dir now listening on port %d", port)
@ -150,18 +149,15 @@ class UserDirectoryServer(HomeServer):
if listener["type"] == "http": if listener["type"] == "http":
self._listen_http(listener) self._listen_http(listener)
elif listener["type"] == "manhole": elif listener["type"] == "manhole":
bind_addresses = listener["bind_addresses"] _base.listen_tcp(
listener["bind_addresses"],
for address in bind_addresses: listener["port"],
reactor.listenTCP( manhole(
listener["port"], username="matrix",
manhole( password="rabbithole",
username="matrix", globals={"hs": self},
password="rabbithole",
globals={"hs": self},
),
interface=address
) )
)
else: else:
logger.warn("Unrecognized listener type: %s", listener["type"]) logger.warn("Unrecognized listener type: %s", listener["type"])

View file

@ -220,13 +220,12 @@ class ServerConfig(Config):
port: %(bind_port)s port: %(bind_port)s
# Local addresses to listen on. # Local addresses to listen on.
# This will listen on all IPv4 addresses by default. # On Linux and Mac OS, `::` will listen on all IPv4 and IPv6
# addresses by default. For most other OSes, this will only listen
# on IPv6.
bind_addresses: bind_addresses:
- '::'
- '0.0.0.0' - '0.0.0.0'
# Uncomment to listen on all IPv6 interfaces
# N.B: On at least Linux this will also listen on all IPv4
# addresses, so you will need to comment out the line above.
# - '::'
# This is a 'http' listener, allows us to specify 'resources'. # This is a 'http' listener, allows us to specify 'resources'.
type: http type: http
@ -264,7 +263,7 @@ class ServerConfig(Config):
# For when matrix traffic passes through loadbalancer that unwraps TLS. # For when matrix traffic passes through loadbalancer that unwraps TLS.
- port: %(unsecure_port)s - port: %(unsecure_port)s
tls: false tls: false
bind_addresses: ['0.0.0.0'] bind_addresses: ['::', '0.0.0.0']
type: http type: http
x_forwarded: false x_forwarded: false
@ -278,7 +277,7 @@ class ServerConfig(Config):
# Turn on the twisted ssh manhole service on localhost on the given # Turn on the twisted ssh manhole service on localhost on the given
# port. # port.
# - port: 9000 # - port: 9000
# bind_address: 127.0.0.1 # bind_addresses: ['::1', '127.0.0.1']
# type: manhole # type: manhole
""" % locals() """ % locals()