From a9f0477b904e979f9c4067eee9df52e95d09c1bd Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 2 Dec 2020 14:38:55 +0000 Subject: [PATCH] Allow disabling federation --- dendrite-config.yaml | 4 ++++ internal/config/config_global.go | 4 ++++ internal/setup/base.go | 15 ++++++++++++-- internal/setup/federation.go | 35 ++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 internal/setup/federation.go diff --git a/dendrite-config.yaml b/dendrite-config.yaml index 2a8650db6..ccdb32432 100644 --- a/dendrite-config.yaml +++ b/dendrite-config.yaml @@ -60,6 +60,10 @@ global: - matrix.org - vector.im + # Disables federation. Dendrite will not be able to make any outbound HTTP requests + # to other servers and the federation API will not be exposed. + disable_federation: false + # Configuration for Kafka/Naffka. kafka: # List of Kafka broker addresses to connect to. This is not needed if using diff --git a/internal/config/config_global.go b/internal/config/config_global.go index d210a3aca..956522176 100644 --- a/internal/config/config_global.go +++ b/internal/config/config_global.go @@ -34,6 +34,10 @@ type Global struct { // Defaults to 24 hours. KeyValidityPeriod time.Duration `yaml:"key_validity_period"` + // Disables federation. Dendrite will not be able to make any outbound HTTP requests + // to other servers and the federation API will not be exposed. + DisableFederation bool `yaml:"disable_federation"` + // List of domains that the server will trust as identity servers to // verify third-party identifiers. // Defaults to an empty array. diff --git a/internal/setup/base.go b/internal/setup/base.go index 4e1cee479..1820778ad 100644 --- a/internal/setup/base.go +++ b/internal/setup/base.go @@ -249,6 +249,9 @@ func (b *BaseDendrite) CreateAccountsDB() accounts.Database { // CreateClient creates a new client (normally used for media fetch requests). // Should only be called once per component. func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { + if b.Cfg.Global.DisableFederation { + return gomatrixserverlib.NewClientWithTransport(noOpHTTPTransport) + } client := gomatrixserverlib.NewClient( b.Cfg.FederationSender.DisableTLSValidation, ) @@ -259,6 +262,12 @@ func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { // CreateFederationClient creates a new federation client. Should only be called // once per component. func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient { + if b.Cfg.Global.DisableFederation { + return gomatrixserverlib.NewFederationClientWithTransport( + b.Cfg.Global.ServerName, b.Cfg.Global.KeyID, b.Cfg.Global.PrivateKey, + b.Cfg.FederationSender.DisableTLSValidation, noOpHTTPTransport, + ) + } client := gomatrixserverlib.NewFederationClientWithTimeout( b.Cfg.Global.ServerName, b.Cfg.Global.KeyID, b.Cfg.Global.PrivateKey, b.Cfg.FederationSender.DisableTLSValidation, time.Minute*5, @@ -308,8 +317,10 @@ func (b *BaseDendrite) SetupAndServeHTTP( } externalRouter.PathPrefix(httputil.PublicClientPathPrefix).Handler(b.PublicClientAPIMux) - externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux) - externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(b.PublicFederationAPIMux) + if !b.Cfg.Global.DisableFederation { + externalRouter.PathPrefix(httputil.PublicKeyPathPrefix).Handler(b.PublicKeyAPIMux) + externalRouter.PathPrefix(httputil.PublicFederationPathPrefix).Handler(b.PublicFederationAPIMux) + } externalRouter.PathPrefix(httputil.PublicMediaPathPrefix).Handler(b.PublicMediaAPIMux) if internalAddr != NoListener && internalAddr != externalAddr { diff --git a/internal/setup/federation.go b/internal/setup/federation.go new file mode 100644 index 000000000..ac3484ef4 --- /dev/null +++ b/internal/setup/federation.go @@ -0,0 +1,35 @@ +package setup + +import ( + "context" + "fmt" + "net" + "net/http" +) + +// noOpHTTPTransport is used to disable federation. +var noOpHTTPTransport = &http.Transport{ + Dial: func(_, _ string) (net.Conn, error) { + return nil, fmt.Errorf("federation prohibited by configuration") + }, + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return nil, fmt.Errorf("federation prohibited by configuration") + }, + DialTLS: func(_, _ string) (net.Conn, error) { + return nil, fmt.Errorf("federation prohibited by configuration") + }, + DialTLSContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return nil, fmt.Errorf("federation prohibited by configuration") + }, +} + +func init() { + noOpHTTPTransport.RegisterProtocol("matrix", &noOpHTTPRoundTripper{}) +} + +type noOpHTTPRoundTripper struct { +} + +func (y *noOpHTTPRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("federation prohibited by configuration") +}