diff --git a/appservice/workers/transaction_scheduler.go b/appservice/workers/transaction_scheduler.go index cc9907481..6e8e8f4a3 100644 --- a/appservice/workers/transaction_scheduler.go +++ b/appservice/workers/transaction_scheduler.go @@ -185,14 +185,14 @@ func createTransaction( } } - var ev []*gomatrixserverlib.Event - for _, e := range events { - ev = append(ev, e.Event) + var ev []*gomatrixserverlib.HeaderedEvent + for i := range events { + ev = append(ev, &events[i]) } // Create a transaction and store the events inside transaction := gomatrixserverlib.ApplicationServiceTransaction{ - Events: ev, + Events: gomatrixserverlib.HeaderedToClientEvents(ev, gomatrixserverlib.FormatAll), } transactionJSON, err = json.Marshal(transaction) 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/federationsender/federationsender.go b/federationsender/federationsender.go index 78791140e..7b75cb372 100644 --- a/federationsender/federationsender.go +++ b/federationsender/federationsender.go @@ -59,8 +59,8 @@ func NewInternalAPI( consumer, _ := kafka.SetupConsumerProducer(&cfg.Matrix.Kafka) queues := queue.NewOutgoingQueues( - federationSenderDB, cfg.Matrix.ServerName, federation, - rsAPI, stats, + federationSenderDB, cfg.Matrix.DisableFederation, + cfg.Matrix.ServerName, federation, rsAPI, stats, &queue.SigningInfo{ KeyID: cfg.Matrix.KeyID, PrivateKey: cfg.Matrix.PrivateKey, diff --git a/federationsender/queue/queue.go b/federationsender/queue/queue.go index 04cb57e70..95d37b2b8 100644 --- a/federationsender/queue/queue.go +++ b/federationsender/queue/queue.go @@ -34,6 +34,7 @@ import ( // matrix servers type OutgoingQueues struct { db storage.Database + disabled bool rsAPI api.RoomserverInternalAPI origin gomatrixserverlib.ServerName client *gomatrixserverlib.FederationClient @@ -46,6 +47,7 @@ type OutgoingQueues struct { // NewOutgoingQueues makes a new OutgoingQueues func NewOutgoingQueues( db storage.Database, + disabled bool, origin gomatrixserverlib.ServerName, client *gomatrixserverlib.FederationClient, rsAPI api.RoomserverInternalAPI, @@ -53,6 +55,7 @@ func NewOutgoingQueues( signing *SigningInfo, ) *OutgoingQueues { queues := &OutgoingQueues{ + disabled: disabled, db: db, rsAPI: rsAPI, origin: origin, @@ -62,28 +65,30 @@ func NewOutgoingQueues( queues: map[gomatrixserverlib.ServerName]*destinationQueue{}, } // Look up which servers we have pending items for and then rehydrate those queues. - time.AfterFunc(time.Second*5, func() { - serverNames := map[gomatrixserverlib.ServerName]struct{}{} - if names, err := db.GetPendingPDUServerNames(context.Background()); err == nil { - for _, serverName := range names { - serverNames[serverName] = struct{}{} + if !disabled { + time.AfterFunc(time.Second*5, func() { + serverNames := map[gomatrixserverlib.ServerName]struct{}{} + if names, err := db.GetPendingPDUServerNames(context.Background()); err == nil { + for _, serverName := range names { + serverNames[serverName] = struct{}{} + } + } else { + log.WithError(err).Error("Failed to get PDU server names for destination queue hydration") } - } else { - log.WithError(err).Error("Failed to get PDU server names for destination queue hydration") - } - if names, err := db.GetPendingEDUServerNames(context.Background()); err == nil { - for _, serverName := range names { - serverNames[serverName] = struct{}{} + if names, err := db.GetPendingEDUServerNames(context.Background()); err == nil { + for _, serverName := range names { + serverNames[serverName] = struct{}{} + } + } else { + log.WithError(err).Error("Failed to get EDU server names for destination queue hydration") } - } else { - log.WithError(err).Error("Failed to get EDU server names for destination queue hydration") - } - for serverName := range serverNames { - if !queues.getQueue(serverName).statistics.Blacklisted() { - queues.getQueue(serverName).wakeQueueIfNeeded() + for serverName := range serverNames { + if !queues.getQueue(serverName).statistics.Blacklisted() { + queues.getQueue(serverName).wakeQueueIfNeeded() + } } - } - }) + }) + } return queues } @@ -122,6 +127,9 @@ func (oqs *OutgoingQueues) SendEvent( ev *gomatrixserverlib.HeaderedEvent, origin gomatrixserverlib.ServerName, destinations []gomatrixserverlib.ServerName, ) error { + if oqs.disabled { + return fmt.Errorf("federation is disabled") + } if origin != oqs.origin { // TODO: Support virtual hosting; gh issue #577. return fmt.Errorf( @@ -181,6 +189,9 @@ func (oqs *OutgoingQueues) SendEDU( e *gomatrixserverlib.EDU, origin gomatrixserverlib.ServerName, destinations []gomatrixserverlib.ServerName, ) error { + if oqs.disabled { + return fmt.Errorf("federation is disabled") + } if origin != oqs.origin { // TODO: Support virtual hosting; gh issue #577. return fmt.Errorf( @@ -243,6 +254,9 @@ func (oqs *OutgoingQueues) SendEDU( // RetryServer attempts to resend events to the given server if we had given up. func (oqs *OutgoingQueues) RetryServer(srv gomatrixserverlib.ServerName) { + if oqs.disabled { + return + } q := oqs.getQueue(srv) if q == nil { return diff --git a/go.mod b/go.mod index 42eeaf04e..d01c80860 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3 github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd - github.com/matrix-org/gomatrixserverlib v0.0.0-20201116151724-6e7b24e4956c + github.com/matrix-org/gomatrixserverlib v0.0.0-20201202134418-2ba106a5bca3 github.com/matrix-org/naffka v0.0.0-20200901083833-bcdd62999a91 github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 github.com/mattn/go-sqlite3 v1.14.2 diff --git a/go.sum b/go.sum index 1341894df..18715f86a 100644 --- a/go.sum +++ b/go.sum @@ -569,8 +569,8 @@ github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26 h1:Hr3zjRsq2bh github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0= github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd h1:xVrqJK3xHREMNjwjljkAUaadalWc0rRbmVuQatzmgwg= github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20201116151724-6e7b24e4956c h1:iiloytJig9EmlKwuSulIbNvoPz1BFZ1QdyPWpuy85XM= -github.com/matrix-org/gomatrixserverlib v0.0.0-20201116151724-6e7b24e4956c/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20201202134418-2ba106a5bca3 h1:+45Q/5FybBhHPMr10YdzJNFYO/6RRgkBcZbMzIRq5Ck= +github.com/matrix-org/gomatrixserverlib v0.0.0-20201202134418-2ba106a5bca3/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= github.com/matrix-org/naffka v0.0.0-20200901083833-bcdd62999a91 h1:HJ6U3S3ljJqNffYMcIeAncp5qT/i+ZMiJ2JC2F0aXP4= github.com/matrix-org/naffka v0.0.0-20200901083833-bcdd62999a91/go.mod h1:sjyPyRxKM5uw1nD2cJ6O2OxI6GOqyVBfNXqKjBZTBZE= github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7 h1:ntrLa/8xVzeSs8vHFHK25k0C+NV74sYMJnNSg5NoSRo= 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..7e9a22b33 --- /dev/null +++ b/internal/setup/federation.go @@ -0,0 +1,32 @@ +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") + }, +} + +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") +} diff --git a/syncapi/types/types.go b/syncapi/types/types.go index 91d33d4a6..36f30c20b 100644 --- a/syncapi/types/types.go +++ b/syncapi/types/types.go @@ -484,8 +484,7 @@ func NewInviteResponse(event *gomatrixserverlib.HeaderedEvent) *InviteResponse { // Then we'll see if we can create a partial of the invite event itself. // This is needed for clients to work out *who* sent the invite. - format, _ := event.RoomVersion.EventFormat() - inviteEvent := gomatrixserverlib.ToClientEvent(event.Unwrap(), format) + inviteEvent := gomatrixserverlib.ToClientEvent(event.Unwrap(), gomatrixserverlib.FormatSync) inviteEvent.Unsigned = nil if ev, err := json.Marshal(inviteEvent); err == nil { res.InviteState.Events = append(res.InviteState.Events, ev)